diff --git a/.github/workflows/webassembly.yml b/.github/workflows/webassembly.yml index f676877fd..c3a392215 100644 --- a/.github/workflows/webassembly.yml +++ b/.github/workflows/webassembly.yml @@ -29,7 +29,7 @@ jobs: - name: Setup emsdk uses: mymindstorm/setup-emsdk@v14 with: - version: 3.1.64 + version: 3.1.71 actions-cache-folder: 'emsdk-cache' - name: Setup Release Version diff --git a/BINDINGS.md b/BINDINGS.md index 576d9b463..860151b21 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -6,11 +6,11 @@ Some people ported raylib to other languages in the form of bindings or wrappers | Name | raylib Version | Language | License | | :--------------------------------------------------------------------------------------- | :--------------: | :------------------------------------------------------------------: | :------------------: | -| [raylib](https://github.com/raysan5/raylib) | **5.0** | [C/C++](https://en.wikipedia.org/wiki/C_(programming_language)) | Zlib | -| [raylib-beef](https://github.com/Starpelly/raylib-beef) | **5.0** | [Beef](https://www.beeflang.org) | MIT | -| [raylib-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 | -| [Raylib-cs](https://github.com/ChrisDill/Raylib-cs) | **5.0** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(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 | +| [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.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-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 | @@ -18,62 +18,69 @@ 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 | | [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 | +| [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 | | [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 | | [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 | -| [raylib-d](https://github.com/schveiguy/raylib-d) | **5.0** | [D](https://dlang.org) | Zlib | +| [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 | | [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-freebasic](https://github.com/WIITD/raylib-freebasic) | **5.0** | [FreeBASIC](https://www.freebasic.net) | MIT | -| [fortran-raylib](https://github.com/interkosmos/fortran-raylib) | 4.5 | [Fortran](https://fortran-lang.org) | ISC | -| [raylib-go](https://github.com/gen2brain/raylib-go) | **5.0** | [Go](https://golang.org) | Zlib | +| [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.5** | [Go](https://golang.org) | 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) | **???** | | [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 | | [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/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.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) | **???** | | [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 | -| [raylua](https://github.com/Rabios/raylua) | 4.0 | [Lua](http://www.lua.org) | MIT | -| [raylib-matte](https://github.com/jcorks/raylib-matte) | 4.6-dev | [Matte](https://github.com/jcorks/matte) | MIT | +| [raylib-lua](https://github.com/TSnake41/raylib-lua) | 5.0 | [Lua](http://www.lua.org) | ISC | +| [raylib-lua-bindings (WIP)](https://github.com/legendaryredfox/raylib-lua-bindings) | 5.5 | [Lua](http://www.lua.org) | ISC | +| [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-bindings](https://github.com/vaiorabbit/raylib-bindings) | 4.5 | [Ruby](https://www.ruby-lang.org/en) | Zlib | -| [naylib](https://github.com/planetis-m/naylib) | **5.1-dev** | [Nim](https://nim-lang.org) | MIT | +| [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.6-dev** | [Nim](https://nim-lang.org) | MIT | | [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-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 | -| [Ray4Laz](https://github.com/GuvaCode/Ray4Laz) | **5.0** | [Free Pascal](https://en.wikipedia.org/wiki/Free_Pascal) | Zlib | +| [Ray4Laz](https://github.com/GuvaCode/Ray4Laz) | **5.5** | [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 | -| [raylib-python-cffi](https://github.com/electronstudio/raylib-python-cffi) | 4.2 | [Python](https://www.python.org) | EPL-2.0 | -| [raylibpyctbg](https://github.com/overdev/raylibpyctbg) | 4.5 | [Python](https://www.python.org) | MIT | -| [raylib-py](https://github.com/overdev/raylib-py) | **5.0b1** | [Python](https://www.python.org) | MIT | +| [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) | 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-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-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 | -| [raylib-ffi](https://github.com/ewpratten/raylib-ffi) | 4.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-ffi](https://github.com/ewpratten/raylib-ffi) | 5.5 | [Rust](https://www.rust-lang.org) | GPLv3 | +| [raylib-rs](https://github.com/raylib-rs/raylib-rs) | **5.5** | [Rust](https://www.rust-lang.org) | Zlib | +| [raylib-ruby](https://github.com/wilsonsilva/raylib-ruby) | 4.5 | [Ruby](https://www.ruby-lang.org) | Zlib | | [Relib](https://github.com/RedCubeDev-ByteSpace/Relib) | 3.5 | [ReCT](https://github.com/RedCubeDev-ByteSpace/ReCT) | **???** | | [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-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-v](https://github.com/vlang/raylib) | 5.5 | [V](https://vlang.io) | MIT/Unlicense | | [raylib.v](https://github.com/irishgreencitrus/raylib.v) | 4.2 | [V](https://vlang.io) | Zlib | | [raylib-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-zig](https://github.com/Not-Nik/raylib-zig) | **5.0** | [Zig](https://ziglang.org) | MIT | +| [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.5** | [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 | | [hare-raylib](https://git.sr.ht/~evantj/hare-raylib) | **auto** | [Hare](https://harelang.org) | Zlib | @@ -84,15 +91,18 @@ 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-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-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 -These are utility wrappers for specific languages, they are not required to use raylib in the language but may adapt the raylib API to be more inline with the language's pardigm. +These are utility wrappers for specific languages, they are not required to use raylib in the language but may adapt the raylib API to be more inline with the language's paradigm. | Name | raylib Version | Language | License | | ---------------------------------------------------- | :------------: | :------------------------------------------: | :-----: | -| [raylib-cpp](https://github.com/robloach/raylib-cpp) | **5.0** | [C++](https://en.wikipedia.org/wiki/C%2B%2B) | Zlib | +| [raylib-cpp](https://github.com/robloach/raylib-cpp) | **5.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 | | [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 @@ -152,7 +162,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) | | [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-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-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) | diff --git a/CHANGELOG b/CHANGELOG index 7ec73066f..61e12a3d4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,23 +1,24 @@ changelog --------- -Current Release: raylib 5.0 (18 November 2023) +Current Release: raylib 5.5 (18 November 2024) ------------------------------------------------------------------------- -Release: raylib 5.5 (November 2024?) +Release: raylib 5.5 (18 November 2024) ------------------------------------------------------------------------- KEY CHANGES: - - New rcore backend: RGFW - - New raylib project creator tool + - New tool: raylib project creator + - New rcore backends: RGFW and SDL3 - New platforms supported: Dreamcast, N64, PSP, PSVita, PS4 - - GPU Skinning (all platforms and GL versions) - - raymath C++ operators + - Added GPU Skinning support (all platforms and GL versions) + - Added raymath C++ operators Detailed changes: -WIP: Last update with commit from 21-Oct-2024 +WIP: Last update with commit from 02-Nov-2024 [rcore] ADDED: Working directory info at initialization by @Ray +[rcore] ADDED: `GetClipboardImage()`, supported by multiple backends (#4459) by @evertonse [rcore] ADDED: `MakeDirectory()`, supporting recursive directory creation by @Ray [rcore] ADDED: `ComputeSHA1()` (#4390) by @Anthony Carbajal [rcore] ADDED: `ComputeCRC32()` and `ComputeMD5()` by @Ray @@ -48,6 +49,10 @@ WIP: Last update with commit from 21-Oct-2024 [rcore] REVIEWED: Fix typos in src/platforms/rcore_*.c (#3581) by @RadsammyT [rcore] REVIEWED: `ExportDataAsCode()`, change sanitization check (#3837) by @Laurentino Luna [rcore] REVIEWED: `ExportDataAsCode()`, add little sanitization to indentifier names (#3832) by @4rk +[rcore] REVIEWED: `GetScreenWidth()`/`GetScreenHeight()` align with all platforms (#4451) by @Arche Washi +[rcore] REVIEWED: `SetGamepadVibration()`, added duration parameter (#4410) by @Asdqwe -WARNING- +[rcore] REVIEWED: `GetGamepadAxisMovement()`, fix #4405 (#4420) by @Asdqwe +[rcore] REVIEWED: `GetGestureHoldDuration()` comments by @Ray [rcore][rlgl] REVIEWED: Fix scale issues when ending a view mode (#3746) by @Jeffery Myers [rcore][GLFW] REVIEWED: Keep CORE.Window.position properly in sync with glfw window position (#4190) by @Dave Green [rcore][GLFW] REVIEWED: Set AUTO_ICONIFY flag to false per default (#4188) by @Dave Green @@ -57,6 +62,7 @@ WIP: Last update with commit from 21-Oct-2024 [rcore][GLFW] REVIEWED: Remove GLFW mouse passthrough hack and increase GLFW version in CMake (#3852) by @Alexandre Almeida [rcore][GLFW] REVIEWED: Updated GLFW to 3.4 (#3827) by @Alexandre Almeida [rcore][GLFW] REVIEWED: Feature test macros before include (#3737) by @John +[rcore][GLFW] REVIEWED: Fix inconsistent dll linkage warning on windows (#4447) by @Jeffery Myers [rcore][Web] ADDED: `SetWindowOpacity()` implementation (#4403) by @Asdqwe [rcore][Web] ADDED: `MaximizeWindow()` and `RestoreWindow()` implementations (#4397) by @Asdqwe [rcore][Web] ADDED: `ToggleFullscreen()` implementation (#3634) by @ubkp @@ -70,6 +76,8 @@ WIP: Last update with commit from 21-Oct-2024 [rcore][Web] REVIEWED: Fix CORE.Input.Mouse.cursorHidden with callbacks (#3644) by @ubkp [rcore][Web] REVIEWED: Fix `IsMouseButtonUp()` (#3611) by @ubkp [rcore][Web] REVIEWED: HighDPI support #3372 by @Ray +[rcore][Web] REVIEWED: `SetWindowSize()` (#4452) by @Asdqwe +[rcore][Web] REVIEWED: `EmscriptenResizeCallback()`, simplified (#4415) by @Asdqwe [rcore][SDL] ADDED: `IsCursorOnScreen()` (#3862) by @Peter0x44 [rcore][SDL] ADDED: Gamepad rumble/vibration support (#3819) by @GideonSerf [rcore][SDL] REVIEWED: Gamepad support (#3776) by @A @@ -107,8 +115,9 @@ WIP: Last update with commit from 21-Oct-2024 [rcore][RGFW] REVIEWED: RGFW 1.0 (#4144) by @Colleague Riley [rcore][RGFW] REVIEWED: Fix errors when compiling with mingw (#4282) by @Colleague Riley [rcore][RGFW] REVIEWED: Replace long switch with a lookup table (#4108) by @Colleague Riley +[rcore][RGFW] REVIEWED: Fix MSVC build errors (#4441) by @Colleague Riley [rlgl] ADDED: More uniform data type options #4137 by @Ray -[rlgl] ADDED: Vertex normals for RLGL immediate drawing mode (#3866) by @bohonghuang +[rlgl] ADDED: Vertex normals for RLGL immediate drawing mode (#3866) by @bohonghuang -WARNING- [rlgl] ADDED: `rlCullDistance*()` variables and getters (#3912) by @KotzaBoss [rlgl] ADDED: `rlSetClipPlanes()` function (#3912) by @KotzaBoss [rlgl] ADDED: `isGpuReady` flag, allow font loading with no GPU acceleration by @Ray -WARNING- @@ -123,6 +132,7 @@ WIP: Last update with commit from 21-Oct-2024 [rlgl] REVIEWED: `rlMultMatrixf()`, fix matrix multiplication order (#3935) by @bohonghuang [rlgl] REVIEWED: `rlSetVertexAttribute()`, define last parameter as offset #3800 by @Ray [rlgl] REVIEWED: `rlDisableVertexAttribute()`, remove redundat calls for SHADER_LOC_VERTEX_COLOR (#3871) by @Kacper ZybaÅ‚a +[rlgl] REVIEWED: `rlLoadTextureCubemap()`, load mipmaps for cubemaps (#4429) by @Nikolas [rlgl] REVIEWED: `rlLoadFramebuffer()`, parameters not required by @Ray [rlgl] REVIEWED: `rlSetUniformSampler()` (#3759) by @veins1 [rlgl] REVIEWED: Renamed near/far variables (#4039) by @jgabaut @@ -132,19 +142,21 @@ WIP: Last update with commit from 21-Oct-2024 [rlgl] REVIEWED: rlgl function description and comments by @Ray [rlgl] REVIEWED: Expose glad functions when building raylib as a shared lib (#3572) by @Peter0x44 [rlgl] REVIEWED: Fix version info in rlgl.h (#3558) by @Steven Schveighoffer -[rcamera] REVIEWED: Make camera movement independant of framerate (#4247) by @hanaxars -WARNING- +[rlgl] REVIEWED: Use the vertex color to the base shader in GLSL330 (#4431) by @Jeffery Myers +[rcamera] REVIEWED: Make camera movement independant of framerate (#4247) by @hanaxars -WARNING- [rcamera] REVIEWED: Updated camera speeds with GetFrameTime() (#4362) by @Anthony Carbajal [rcamera] REVIEWED: `UpdateCamera()`, added CAMERA_CUSTOM check (#3938) by @Tomas Fabrizio Orsi [rcamera] REVIEWED: Support mouse/keyboard and gamepad coexistence for input (#3579) by @ubkp [rcamera] REVIEWED: Cleaned away unused macros(#3762) by @Brian E [rcamera] REVIEWED: Fix for free camera mode (#3603) by @lesleyrs [rcamera] REVIEWED: `GetCameraRight()` (#3784) by @Danil -[raymath] ADDED: C++ operator overloads for common math function (#4385) by @Jeffery Myers +[raymath] ADDED: C++ operator overloads for common math function (#4385) by @Jeffery Myers -WARNING- [raymath] ADDED: Vector4 math functions and Vector2 variants of some Vector3 functions (#3828) by @Bowserinator [raymath] REVIEWED: Fix MSVC warnings/errors in C++ (#4125) by @Jeffery Myers [raymath] REVIEWED: Add extern "C" to raymath header for C++ (#3978) by @Jeffery Myers [raymath] REVIEWED: `QuaternionFromAxisAngle()`, remove redundant axis length calculation (#3900) by @jtainer [raymath] REVIEWED: `Vector3Perpendicular()`, avoid implicit conversion from float to double (#3799) by @João Foscarini +[raymath] REVIEWED: `MatrixDecompose()`, incorrect output for certain scale and rotations (#4461) by @waveydave [raymath] REVIEWED: Small code refactor (#3753) by @Idir Carlos Aliane [rshapes] ADDED: `CheckCollisionCircleLine()` (#4018) by @kai-z99 [rshapes] REVIEWED: Multisegment Bezier splines (#3744) by @Santiago Pelufo @@ -152,8 +164,10 @@ WIP: Last update with commit from 21-Oct-2024 [rshapes] REVIEWED: `DrawLine()` #4075 by @Ray [rshapes] REVIEWED: `DrawPixel()` drawing by @Ray [rshapes] REVIEWED: `DrawLine()` to avoid pixel rounding issues #3931 by @Ray -[rshapes] REVIEWED: `DrawRectangleLinesEx()`, make sure accounts for square tiles (#4382) by @Jojaby +[rshapes] REVIEWED: `DrawRectangleLines()`, considering view matrix for lines "alignment" by @Ray +[rshapes] REVIEWED: `DrawRectangleLines()`, pixel offset (#4261) by @RadsammyT [rshapes] REVIEWED: `DrawRectangleLines()`, pixel offset when scaling (#3884) by @Ray +[rshapes] REVIEWED: `DrawRectangleLinesEx()`, make sure accounts for square tiles (#4382) by @Jojaby [rshapes] REVIEWED: `Draw*Gradient()` color parameter names (#4270) by @Paperdomo101 [rshapes] REVIEWED: `DrawGrid()`, remove duplicate color calls (#4148) by @Jeffery Myers [rshapes] REVIEWED: `DrawSplineLinear()` to `SUPPORT_SPLINE_MITERS` by @Ray @@ -177,7 +191,9 @@ WIP: Last update with commit from 21-Oct-2024 [rtextures] REVIEWED: `LoadImageRaw()` #3926 by @Ray [rtextures] REVIEWED: `LoadImageColors()`, advance k in loop (#4120) by @Bruno Cabral [rtextures] REVIEWED: `LoadTextureCubemap()`, added `mipmaps` #3665 by @Ray -[rtextures] REVIEWED: `LoadTextureCubemap(), assign format to cubemap (#3823) by @Gary M +[rtextures] REVIEWED: `LoadTextureCubemap()`, assign format to cubemap (#3823) by @Gary M +[rtextures] REVIEWED: `LoadTextureCubemap()`, load mipmaps for cubemaps (#4429) by @Nikolas +[rtextures] REVIEWED: `LoadTextureCubemap()`, avoid dangling re-allocated pointers (#4439) by @Nikolas [rtextures] REVIEWED: `LoadImageFromScreen()`, fix scaling (#3881) by @proberge-dev [rtextures] REVIEWED: `LoadImageFromMemory()`, warnings on invalid image data (#4179) by @Jutastre [rtextures] REVIEWED: `LoadImageAnimFromMemory()`, added security checks (#3924) by @Ray @@ -188,8 +204,11 @@ WIP: Last update with commit from 21-Oct-2024 [rtextures] REVIEWED: `ImageDrawRectangleRec()` (#3721) by @Le Juez Victor [rtextures] REVIEWED: `ImageDraw()`, don't try to blend images without alpha (#4395) by @Nikolas [rtextures] REVIEWED: `GenImagePerlinNoise()` being stretched (#4276) by @Bugsia +[rtextures] REVIEWED: `GenImageGradientLinear()`, fix some angles (#4462) by @decromo [rtextures] REVIEWED: `DrawTexturePro()` to avoid negative dest rec #4316 by @Ray [rtextures] REVIEWED: `ColorToInt()`, fix undefined behaviour (#3996) by @OetkenPurveyorOfCode +[rtextures] REVIEWED: Remove panorama cubemap layout option (#4425) by @Jeffery Myers +[rtextures] REVIEWED: Removed unneeded module check, `rtextures` should not depend on `rtext` by @Ray [rtextures] REVIEWED: Simplified for loop for some image manipulation functions (#3712) by @Alice Nyaa [rtext] ADDED: BDF fonts support (#3735) by @Stanley Fuller -WARNING- [rtext] ADDED: `TextToCamel()` (#4033) by @IoIxD @@ -207,6 +226,7 @@ WIP: Last update with commit from 21-Oct-2024 [rtext] REVIEWED: `LoadFontData()`, load image only if glyph has been found in font by @Ray [rtext] REVIEWED: `ExportFontAsCode()`, fix C++ compiler errors (#4013) by @DarkAssassin23 [rtext] REVIEWED: `MeasureTextEx()` height calculation (#3770) by @Marrony Neris +[rtext] REVIEWED: `MeasureTextEx()`, additional check for empty input string (#4448) by @mpv-enjoyer [rtext] REVIEWED: `CodepointToUTF8()`, clean static buffer #4379 by @Ray [rtext] REVIEWED: `TextToFloat()`, always multiply by sign (#4273) by @listeria [rtext] REVIEWED: `TextReplace()` const correctness (#3678) by @maverikou @@ -221,6 +241,7 @@ WIP: Last update with commit from 21-Oct-2024 [rmodels] REVIEWED: Multiple updates to gltf loading, improved macro (#4373) by @Harald Scheirich [rmodels] REVIEWED: `LoadOBJ()`, correctly split obj meshes by material (#4285) by @Jeffery Myers [rmodels] REVIEWED: `LoadOBJ()`, add warning when loading an OBJ with multiple materials (#4271) by @Jeffery Myers +[rmodels] REVIEWED: `LoadOBJ()`, fix bug that fragmented the loaded meshes (#4494) by @Eike Decker [rmodels] REVIEWED: `LoadIQM()`, set model.meshMaterial[] (#4092) by @SuperUserNameMan [rmodels] REVIEWED: `LoadIQM()`, attempt to load texture from IQM at loadtime (#4029) by @Jett [rmodels] REVIEWED: `LoadM3D(), fix vertex colors for m3d files (#3859) by @Jeffery Myers @@ -237,9 +258,12 @@ WIP: Last update with commit from 21-Oct-2024 [rmodels] REVIEWED: `LoadModelAnimationsGLTF()`, added missing interpolation types (#3919) by @Benji [rmodels] REVIEWED: `LoadModelAnimationsGLTF()` (#4107) by @VitoTringolo [rmodels] REVIEWED: `LoadBoneInfoGLTF()`, add check for animation name being NULL (#4053) by @VitoTringolo +[rmodels] REVIEWED: `GenMeshSphere()`, fix artifacts (#4460) by @MikiZX1 [rmodels] REVIEWED: `GenMeshTangents()`, read uninitialized values, fix bounding case (#4066) by @kai-z99 [rmodels] REVIEWED: `GenMeshTangents()`, fixed out of bounds error (#3990) by @Salvador Galindo +[rmodels] REVIEWED: `UpdateModelAnimation()`, performance speedup (#4470) by @JettMonstersGoBoom [rmodels] REVIEWED: `DrawCylinder()`, fix drawing due to imprecise angle (#4034) by @Paul Melis +[rmodels] REVIEWED: `DrawCylinder()`, fix drawing of cap (#4478) by @JeffM2501 [rmodels] REVIEWED: `DrawMesh()`, send full matModel to shader in DrawMesh (#4005) (#4022) by @David Holland [rmodels] REVIEWED: `DrawMesh()`, fix material specular map retrieval (#3758) by @Victor Gallet [rmodels] REVIEWED: `DrawModelEx()`, simplified multiplication of colors (#4002) by @Le Juez Victor @@ -258,6 +282,8 @@ WIP: Last update with commit from 21-Oct-2024 [raudio] REVIEWED: Fix crash when switching playback device at runtime (#4102) by @jkaup [raudio] REVIEWED: Support 24 bits samples for FLAC format (#4058) by @Alexey Kutepov [examples] ADDED: `core_random_sequence` (#3846) by @Dalton Overmyer +[examples] ADDED: `core_input_virtual_controls` (#4342) by @oblerion +[examples] ADDED: `shapes_rectangle_advanced `, implementing `DrawRectangleRoundedGradientH()` (#4435) by @Everton Jr. [examples] ADDED: `models_bone_socket` (#3833) by @iP [examples] ADDED: `shaders_vertex_displacement` (#4186) by @Alex ZH [examples] ADDED: `shaders_shadowmap` (#3653) by @TheManTheMythTheGameDev @@ -265,6 +291,8 @@ WIP: Last update with commit from 21-Oct-2024 [examples] REVIEWED: `core_2d_camera_mouse_zoom`, use logarithmic scaling for a 2d zoom functionality (#3977) by @Mike Will [examples] REVIEWED: `core_input_gamepad_info`, all buttons displayed within the window (#4241) by @Asdqwe [examples] REVIEWED: `core_input_gamepad_info`, show ps3 controller (#4040) by @Konrad Gutvik Grande +[examples] REVIEWED: `core_input_gamepad`, add drawing for generic gamepad (#4424) by @Asdqwe +[examples] REVIEWED: `core_input_gamepad`, add deadzone handling (#4422) by @Asdqwe [examples] REVIEWED: `shapes_bouncing_ball` (#4226) by @Anthony Carbajal [examples] REVIEWED: `shapes_following_eyes` (#3710) by @Hongyu Ouyang [examples] REVIEWED: `shapes_draw_rectangle_rounded` by @Ray @@ -288,6 +316,8 @@ WIP: Last update with commit from 21-Oct-2024 [examples] REVIEWED: `shaders_basic_pbr` (#3621) by @devdad [examples] REVIEWED: `shaders_basic_pbr`, remove dependencies (#3649) by @TheManTheMythTheGameDev [examples] REVIEWED: `shaders_basic_pbr`, added more comments by @Ray +[examples] REVIEWED: `shaders_gpu_skinning`, to work with OpenGL ES 2.0 #4412 by @Ray +[examples] REVIEWED: `shaders_model_shader`, use free camera (#4428) by @IcyLeave6109 [examples] REVIEWED: `audio_stream_effects` (#3618) by @lipx [examples] REVIEWED: `audio_raw_stream` (#3624) by @riadbettole [examples] REVIEWED: `audio_mixed_processor` (#4214) by @Anthony Carbajal @@ -302,10 +332,15 @@ WIP: Last update with commit from 21-Oct-2024 [build] REVIEWED: Makefile, fix -Wstringop-truncation warning (#4096) by @Peter0x44 [build] REVIEWED: Makefile, fix issues for RGFW on Linux/macOS (#3969) by @Colleague Riley [build] REVIEWED: Makefile, update RAYLIB_VERSION (#3901) by @Belllg -[build] REVIEWED: Makefile (#4054) by @Lázaro Albuquerque +[build] REVIEWED: Makefile, use mingw32-make for Windows (#4436) by @Asdqwe +[build] REVIEWED: Makefile, move CUSTOM_CFLAGS for better visibility (#4054) by @Lázaro Albuquerque +[build] REVIEWED: Makefile, update emsdk paths to latest versions by @Ray [build] REVIEWED: Makefile examples, align /usr/local with /src Makefile (#4286) by @Tchan0 [build] REVIEWED: Makefile examples, added `textures_image_kernel` (#3555) by @Sergey Zapunidi [build] REVIEWED: Makefile examples (#4209) by @Anthony Carbajal +[build] REVIEWED: Makefile examples, to work on NetBSD (#4438) by @NishiOwO +[build] REVIEWED: Makefile examples, WebGL2 (OpenGL ES 3.0) backend flags #4330 by @Ray +[build] REVIEWED: Makefile examples, web building (#4434) by @Asdqwe [build] REVIEWED: build.zig, fix various issues around `-Dconfig` (#4398) by @Sage Hane [build] REVIEWED: build.zig, fix type mismatch (#4383) by @yuval_dev [build] REVIEWED: build.zig, minor fixes (#4381) by @Sage Hane @@ -334,6 +369,7 @@ WIP: Last update with commit from 21-Oct-2024 [build] REVIEWED: build.zig, remove all uses of deps/mingw (#3805) by @Peter0x44 [build] REVIEWED: build.zig, fixed illegal instruction crash (#3682) by @WisonYe [build] REVIEWED: build.zig, fix broken build on #3863 (#3891) by @Nikolas Mauropoulos +[build] REVIEWED: build.zig, improve cross-compilation (#4468) by @deathbeam [build] REVIEWED: CMake, update to raylib 5.0 (#3623) by @Peter0x44 [build] REVIEWED: CMake, added PLATFORM option for Desktop SDL (#3809) by @mooff [build] REVIEWED: CMake, fix GRAPHICS_* check (#4359) by @Kacper ZybaÅ‚a @@ -351,8 +387,10 @@ WIP: Last update with commit from 21-Oct-2024 [build] REVIEWED: CMake, disable SDL rlgl_standalone example (#3861) by @Rob Loach [build] REVIEWED: CMake, bump version required to avoid deprecated #3639 by @Ray [build] REVIEWED: CMake, fix examples linking -DPLATFORM=SDL (#3825) by @Peter0x44 -[build] REVIEWED: VS2022 project by @Ray +[build] REVIEWED: CMake, don't build for wayland by default (#4432) by @Peter0x44 +[build] REVIEWED: VS2022, misc improvements by @Ray [build] REVIEWED: VS2022, fix build warnings (#4095) by @Jeffery Myers +[build] REVIEWED: VS2022, added new examples (#4492) by @Jeffery Myers [build] REVIEWED: Fix fix-build-paths (#3849) by @Caleb Barger [build] REVIEWED: Fix build paths (#3835) by @Steve Biedermann [build] REVIEWED: Fix VSCode sample project for macOS (#3666) by @Tim Romero @@ -406,6 +444,13 @@ WIP: Last update with commit from 21-Oct-2024 [bindings] UPDATED: Raylib.nelua (#3552) by @Auz [bindings] UPDATED: raylib-cpp to 5.0 (#3551) by @Rob Loach [bindings] UPDATED: Pascal binding (#3548) by @Gunko Vadim +[external] UPDATED: stb_truetype.h to latest version by @Ray +[external] UPDATED: stb_image_resize2.h to latest version by @Ray +[external] UPDATED: stb_image.h to latest version by @Ray +[external] UPDATED: qoa.h to latest version by @Ray +[external] UPDATED: dr_wav.h to latest version by @Ray +[external] UPDATED: dr_mp3.h to latest version by @Ray +[external] UPDATED: cgltf.h to latest version by @Ray [external] REVIEWED: rl_gputex, correctly load mipmaps from DDS files (#4399) by @Nikolas [external] REVIEWED: stb_image_resize2, dix vld1q_f16 undeclared in arm (#4309) by @masnm [external] REVIEWED: miniaudio, fix library and Makefile for NetBSD (#4212) by @NishiOwO diff --git a/CMakeLists.txt b/CMakeLists.txt index 678d8e372..9905ba144 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.12) project(raylib) # Avoid excessive expansion of variables in conditionals. In particular, if diff --git a/CMakeOptions.txt b/CMakeOptions.txt index b387922b4..00ecb594d 100644 --- a/CMakeOptions.txt +++ b/CMakeOptions.txt @@ -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_X11 "Build the bundled GLFW with X11 support" ON) -option(INCLUDE_EVERYTHING "Include everything disabled by default (for CI usage" OFF) +option(INCLUDE_EVERYTHING "Include everything disabled by default (for CI usage)" OFF) set(OFF ${INCLUDE_EVERYTHING} CACHE INTERNAL "Replace any OFF by default with \${OFF} to have it covered by this option") include(ParseConfigHeader) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d70617c13..7d4c8acf1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -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. - 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. - - 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 diff --git a/FAQ.md b/FAQ.md index d2f9308ac..778e3455d 100644 --- a/FAQ.md +++ b/FAQ.md @@ -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? -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? diff --git a/HISTORY.md b/HISTORY.md index 6b1a5be29..02e226437 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -475,16 +475,50 @@ Undoubtedly, this is the **biggest raylib update in 10 years**. Many new feature notes on raylib 5.5 ------------------- -It's been **1 year** since latest raylib release and **11 years** since raylib 1.0 was officially released... +One year after raylib 5.0 release, arrives `raylib 5.5`, the next big revision of the library. It's been **11 years** since raylib 1.0 release and in all this time it has never stopped growing and improving. With an outstanding number of new contributors and improvements, it's, again, the biggest raylib release to date. Some numbers for this release: - **+270** closed issues (for a TOTAL of **+1810**!) - - **+760** commits since previous RELEASE (for a TOTAL of **+7730**!) + - **+800** commits since previous RELEASE (for a TOTAL of **+7770**!) - **+30** functions ADDED to raylib API (for a TOTAL of **580**!) - **+110** functions REVIEWED with fixes and improvements - **+140** new contributors (for a TOTAL of **+640**!) Highlights for `raylib 5.5`: -TODO. + - **`NEW` raylib pre-configured Windows package**: The new raylib **portable and self-contained Windows package** for `raylib 5.5`, intended for nobel devs that start in programming world, comes with one big addition: support for **C code building for Web platform with one-single-mouse-click!** For the last 10 years, the pre-configured raylib Windows package allowed to edit simple C projects on Notepad++ and easely compile Windows executables with an automatic script; this new release adds the possibility to compile the same C projects for Web platform with a simple mouse click. This new addition **greatly simplifies C to WebAssembly project building for new users**. The `raylib Windows Installer` package can be downloaded for free from [raylib on itch.io](https://raysan5.itch.io/raylib). + + - **`NEW` raylib project creator tool**: A brand new tool developed to help raylib users to **setup new projects in a professional way**. `raylib project creator` generates a complete project structure with **multiple build systems ready-to-use** and **GitHub CI/CD actions pre-configured**. It only requires providing some C files and basic project parameters! The tools is [free and open-source](https://raysan5.itch.io/raylib-project-creator), and [it can be used online](https://raysan5.itch.io/raylib-project-creator)!. + + - **`NEW` Platform backend supported: RGFW**: Thanks to the `rcore` platform-split implemented in `raylib 5.0`, **adding new platforms backends has been greatly simplified**, new backends can be added using provided template, self-contained in a single C module, completely portable. A new platform backend has been added: [`RGFW`](https://github.com/raysan5/raylib/blob/master/src/platforms/rcore_desktop_rgfw.c). `RGFW` is a **new single-file header-only portable library** ([`RGFW.h`](https://github.com/ColleagueRiley/RGFW)) intended for platform-functionality management (windowing and inputs); in this case for **desktop platforms** (Windows, Linux, macOS) but also for **Web platform**. It adds a new alternative to the already existing `GLFW` and `SDL` platform backends. + + - **`NEW` Platform backend version supported: SDL3**: Previous `raylib 5.0` added support for `SDL2` library, and `raylib 5.5` not only improves SDL2 functionality, with several issues reviewed, but also adds support for the recently released big SDL update in years: [`SDL3`](https://wiki.libsdl.org/SDL3/FrontPage). Now users can **select at compile time the desired SDL version to use**, increasing the number of potential platforms supported in the future! + + - **`NEW` Retro-console platforms supported: Dreamcast, N64, PSP, PSVita, PS4**: Thanks to the platform-split on `raylib 5.0`, **supporting new platform backends is easier than ever!** Along the raylib `rlgl` module support for the `OpenGL 1.1` graphics API, it opened the door to [**multiple homebrew retro-consoles backend implementations!**](https://github.com/raylib4Consoles) It's amazing to see raylib running on +20 year old consoles like [Dreamcast](https://github.com/raylib4Consoles/raylib4Dreamcast), [PSP](https://github.com/raylib4Consoles/raylib4Psp) or [PSVita](https://github.com/psp2dev/raylib4Vita), considering the hardware constraints of those platforms and proves **raylib outstanding versability!** Those additional platforms can be found in separate repositories and have been created by the amazing programmer Antonio Jose Ramos Marquez (@psxdev). + + - **`NEW` GPU Skinning support**: After lots of requests for this feature, it has been finally added to raylib thanks to the contributor Daniel Holden (@orangeduck), probably the developer that has further pushed models animations with raylib, developing two amazing tools to visualize and test animations: [GenoView](https://github.com/orangeduck/GenoView) and [BVHView](https://github.com/orangeduck/BVHView). Adding GPU skinning was a tricky feature, considering it had to be **available for all raylib supported platforms**, including limited ones like Raspberry Pi with OpenGL ES 2.0, where some advance OpenGL features are not available (UBO, SSBO, Transform Feedback) but a multi-platform solution was found to make it possible. A new example, [`models_gpu_skinning`](https://github.com/raysan5/raylib/blob/master/examples/models/models_gpu_skinning.c) has been added to illustrate this new functionality. As an extra, previous existing CPU animation system has been greatly improved, multiplying performance by a factor (simplifiying required maths). + + - **`NEW` [`raymath`](https://github.com/raysan5/raylib/blob/master/src/raymath.h) C++ operators**: After several requested for this feature, C++ math operators for `Vector2`, `Vector3`, `Vector4`, `Quaternion` and `Matrix` has been added to `raymath` as an extension to current implementation. Despite being only available for C++ because C does not support it, these operators **simplify C++ code when doing math operations**. + +Beside those new big features, `raylib 5.5` comes with MANY other improvements: + +- Normals support on batching system +- Clipboard images reading support +- CRC32/MD5/SHA1 hash computation +- Gamepad vibration support +- Improved font loading (no GPU required) with BDF fonts support +- Time-based camera movement +- Improved GLTF animations loading + +...and [much much more](https://github.com/raysan5/raylib/blob/master/CHANGELOG), including **many functions reviews and new functions added!** + +Make sure to check raylib [CHANGELOG](https://github.com/raysan5/raylib/blob/master/CHANGELOG) for a detailed list of changes! + +To end with, I want to **thank all the contributors (+640!**) that along the years have **greatly improved raylib** and pushed it further and better day after day. Thanks to all of them, raylib is the amazing library it is today. + +Last but not least, I want to thank **raylib sponsors and all the raylib community** for their support and continuous engagement with the library, creating and sharing amazing raylib projects on a daily basis. **Thanks for making raylib a great platform to enjoy games/tools/graphic programming!** + +**After 11 years of development, `raylib 5.5` is the best raylib ever.** + +**Enjoy programming with raylib!** :) diff --git a/LICENSE b/LICENSE index d1bfe3b1a..e96f876a2 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2013-2024 Ramon Santamaria (@raysan5) +Copyright (c) 2013-2025 Ramon Santamaria (@raysan5) This software is provided "as-is", without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. diff --git a/README.md b/README.md index 29173d665..4b242f171 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Ready to learn? Jump to [code examples!](https://www.raylib.com/examples.html) [![GitHub Releases Downloads](https://img.shields.io/github/downloads/raysan5/raylib/total)](https://github.com/raysan5/raylib/releases) [![GitHub Stars](https://img.shields.io/github/stars/raysan5/raylib?style=flat&label=stars)](https://github.com/raysan5/raylib/stargazers) -[![GitHub commits since tagged version](https://img.shields.io/github/commits-since/raysan5/raylib/5.0)](https://github.com/raysan5/raylib/commits/master) +[![GitHub commits since tagged version](https://img.shields.io/github/commits-since/raysan5/raylib/5.5)](https://github.com/raysan5/raylib/commits/master) [![GitHub Sponsors](https://img.shields.io/github/sponsors/raysan5?label=sponsors)](https://github.com/sponsors/raysan5) [![Packaging Status](https://repology.org/badge/tiny-repos/raylib.svg)](https://repology.org/project/raylib/versions) [![License](https://img.shields.io/badge/license-zlib%2Flibpng-blue.svg)](LICENSE) @@ -130,6 +130,7 @@ raylib is present in several networks and raylib community is growing everyday. - Webpage: [https://www.raylib.com](https://www.raylib.com) - Discord: [https://discord.gg/raylib](https://discord.gg/raylib) - Twitter: [https://www.twitter.com/raysan5](https://www.twitter.com/raysan5) + - BlueSky: [https://bsky.app/profile/raysan5](https://bsky.app/profile/raysan5.bsky.social) - Twitch: [https://www.twitch.tv/raysan5](https://www.twitch.tv/raysan5) - Reddit: [https://www.reddit.com/r/raylib](https://www.reddit.com/r/raylib) - Patreon: [https://www.patreon.com/raylib](https://www.patreon.com/raylib) diff --git a/build.zig b/build.zig index 75a77dd51..0f6f29755 100644 --- a/build.zig +++ b/build.zig @@ -2,7 +2,7 @@ const std = @import("std"); const builtin = @import("builtin"); /// Minimum supported version of Zig -const min_ver = "0.12.0"; +const min_ver = "0.13.0"; comptime { const order = std.SemanticVersion.order; @@ -11,44 +11,36 @@ comptime { @compileError("Raylib requires zig version " ++ min_ver); } -// NOTE(freakmangd): I don't like using a global here, but it prevents having to -// get the flags a second time when adding raygui -var raylib_flags_arr: std.ArrayListUnmanaged([]const u8) = .{}; - -// This has been tested with zig version 0.12.0 -pub fn addRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: Options) !*std.Build.Step.Compile { - const raylib_dep = b.dependencyFromBuildZig(@This(), .{ - .target = target, - .optimize = optimize, - .raudio = options.raudio, - .rmodels = options.rmodels, - .rshapes = options.rshapes, - .rtext = options.rtext, - .rtextures = options.rtextures, - .platform = options.platform, - .shared = options.shared, - .linux_display_backend = options.linux_display_backend, - .opengl_version = options.opengl_version, - .config = options.config, - }); - const raylib = raylib_dep.artifact("raylib"); - - if (options.raygui) { - const raygui_dep = b.dependency(options.raygui_dependency_name, .{}); - addRaygui(b, raylib, raygui_dep); +fn setDesktopPlatform(raylib: *std.Build.Step.Compile, platform: PlatformBackend) void { + switch (platform) { + .glfw => raylib.root_module.addCMacro("PLATFORM_DESKTOP_GLFW", ""), + .rgfw => raylib.root_module.addCMacro("PLATFORM_DESKTOP_RGFW", ""), + .sdl => raylib.root_module.addCMacro("PLATFORM_DESKTOP_SDL", ""), + else => {}, } - - return raylib; } -fn setDesktopPlatform(raylib: *std.Build.Step.Compile, platform: PlatformBackend) void { - raylib.defineCMacro("PLATFORM_DESKTOP", null); +fn createEmsdkStep(b: *std.Build, emsdk: *std.Build.Dependency) *std.Build.Step.Run { + if (builtin.os.tag == .windows) { + return b.addSystemCommand(&.{emsdk.path("emsdk.bat").getPath(b)}); + } else { + return b.addSystemCommand(&.{emsdk.path("emsdk").getPath(b)}); + } +} - switch (platform) { - .glfw => raylib.defineCMacro("PLATFORM_DESKTOP_GLFW", null), - .rgfw => raylib.defineCMacro("PLATFORM_DESKTOP_RGFW", null), - .sdl => raylib.defineCMacro("PLATFORM_DESKTOP_SDL", null), - else => {}, +fn emSdkSetupStep(b: *std.Build, emsdk: *std.Build.Dependency) !?*std.Build.Step.Run { + const dot_emsc_path = emsdk.path(".emscripten").getPath(b); + const dot_emsc_exists = !std.meta.isError(std.fs.accessAbsolute(dot_emsc_path, .{})); + + if (!dot_emsc_exists) { + const emsdk_install = createEmsdkStep(b, emsdk); + emsdk_install.addArgs(&.{ "install", "latest" }); + const emsdk_activate = createEmsdkStep(b, emsdk); + emsdk_activate.addArgs(&.{ "activate", "latest" }); + emsdk_activate.step.dependOn(&emsdk_install.step); + return emsdk_activate; + } else { + return null; } } @@ -64,6 +56,7 @@ const config_h_flags = outer: { var lines = std.mem.tokenizeScalar(u8, config_h, '\n'); while (lines.next()) |line| { if (!std.mem.containsAtLeast(u8, line, 1, "SUPPORT")) continue; + if (std.mem.containsAtLeast(u8, line, 1, "MODULE")) continue; if (std.mem.startsWith(u8, line, "//")) continue; if (std.mem.startsWith(u8, line, "#if")) continue; @@ -83,22 +76,26 @@ const config_h_flags = outer: { }; fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: Options) !*std.Build.Step.Compile { - raylib_flags_arr.clearRetainingCapacity(); + var raylib_flags_arr = std.ArrayList([]const u8).init(b.allocator); + defer raylib_flags_arr.deinit(); - const shared_flags = &[_][]const u8{ - "-fPIC", - "-DBUILD_LIBTYPE_SHARED", - }; - try raylib_flags_arr.appendSlice(b.allocator, &[_][]const u8{ + try raylib_flags_arr.appendSlice(&[_][]const u8{ "-std=gnu99", "-D_GNU_SOURCE", "-DGL_SILENCE_DEPRECATION=199309L", "-fno-sanitize=undefined", // https://github.com/raysan5/raylib/issues/3674 }); - if (options.config.len > 0) { - // Sets a flag indiciating the use of a custom `config.h` - try raylib_flags_arr.append(b.allocator, "-DEXTERNAL_CONFIG_FLAGS"); + if (options.shared) { + try raylib_flags_arr.appendSlice(&[_][]const u8{ + "-fPIC", + "-DBUILD_LIBTYPE_SHARED", + }); + } + + // Sets a flag indiciating the use of a custom `config.h` + try raylib_flags_arr.append("-DEXTERNAL_CONFIG_FLAGS"); + if (options.config.len > 0) { // Splits a space-separated list of config flags into multiple flags // // Note: This means certain flags like `-x c++` won't be processed properly. @@ -107,7 +104,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. // Apply config flags supplied by the user while (config_iter.next()) |config_flag| - try raylib_flags_arr.append(b.allocator, config_flag); + try raylib_flags_arr.append(config_flag); // Apply all relevant configs from `src/config.h` *except* the user-specified ones // @@ -125,12 +122,11 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. } // Otherwise, append default value from config.h to compile flags - try raylib_flags_arr.append(b.allocator, flag); + try raylib_flags_arr.append(flag); } - } - - if (options.shared) { - try raylib_flags_arr.appendSlice(b.allocator, shared_flags); + } else { + // Set default config if no custome config got set + try raylib_flags_arr.appendSlice(&config_h_flags); } const raylib = if (options.shared) @@ -155,26 +151,32 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. var c_source_files = try std.ArrayList([]const u8).initCapacity(b.allocator, 2); c_source_files.appendSliceAssumeCapacity(&.{ "src/rcore.c", "src/utils.c" }); - if (options.raudio) { - try c_source_files.append("src/raudio.c"); - } - if (options.rmodels) { - try c_source_files.append("src/rmodels.c"); - } if (options.rshapes) { try c_source_files.append("src/rshapes.c"); - } - if (options.rtext) { - try c_source_files.append("src/rtext.c"); + try raylib_flags_arr.append("-DSUPPORT_MODULE_RSHAPES"); } if (options.rtextures) { try c_source_files.append("src/rtextures.c"); + try raylib_flags_arr.append("-DSUPPORT_MODULE_RTEXTURES"); + } + if (options.rtext) { + try c_source_files.append("src/rtext.c"); + try raylib_flags_arr.append("-DSUPPORT_MODULE_RTEXT"); + } + if (options.rmodels) { + try c_source_files.append("src/rmodels.c"); + try raylib_flags_arr.append("-DSUPPORT_MODULE_RMODELS"); + } + if (options.raudio) { + try c_source_files.append("src/raudio.c"); + try raylib_flags_arr.append("-DSUPPORT_MODULE_RAUDIO"); } if (options.opengl_version != .auto) { - raylib.defineCMacro(options.opengl_version.toCMacroStr(), null); + raylib.root_module.addCMacro(options.opengl_version.toCMacroStr(), ""); } + raylib.addIncludePath(b.path("src/platforms")); switch (target.result.os.tag) { .windows => { try c_source_files.append("src/rglfw.c"); @@ -189,7 +191,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. try c_source_files.append("src/rglfw.c"); if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) { - raylib.defineCMacro("_GLFW_X11", null); + raylib.root_module.addCMacro("_GLFW_X11", ""); raylib.linkSystemLibrary("GLX"); raylib.linkSystemLibrary("X11"); raylib.linkSystemLibrary("Xcursor"); @@ -209,7 +211,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. , .{}); @panic("`wayland-scanner` not found"); }; - raylib.defineCMacro("_GLFW_WAYLAND", null); + raylib.root_module.addCMacro("_GLFW_WAYLAND", ""); raylib.linkSystemLibrary("EGL"); raylib.linkSystemLibrary("wayland-client"); raylib.linkSystemLibrary("xkbcommon"); @@ -223,20 +225,21 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. waylandGenerate(b, raylib, "xdg-activation-v1.xml", "xdg-activation-v1-client-protocol"); waylandGenerate(b, raylib, "idle-inhibit-unstable-v1.xml", "idle-inhibit-unstable-v1-client-protocol"); } + setDesktopPlatform(raylib, options.platform); } else { if (options.opengl_version == .auto) { raylib.linkSystemLibrary("GLESv2"); - raylib.defineCMacro("GRAPHICS_API_OPENGL_ES2", null); + raylib.root_module.addCMacro("GRAPHICS_API_OPENGL_ES2", ""); } raylib.linkSystemLibrary("EGL"); raylib.linkSystemLibrary("gbm"); raylib.linkSystemLibrary2("libdrm", .{ .use_pkg_config = .force }); - raylib.defineCMacro("PLATFORM_DRM", null); - raylib.defineCMacro("EGL_NO_X11", null); - raylib.defineCMacro("DEFAULT_BATCH_BUFFER_ELEMENT", "2048"); + raylib.root_module.addCMacro("PLATFORM_DRM", ""); + raylib.root_module.addCMacro("EGL_NO_X11", ""); + raylib.root_module.addCMacro("DEFAULT_BATCH_BUFFER_ELEMENT", ""); } }, .freebsd, .openbsd, .netbsd, .dragonfly => { @@ -255,8 +258,15 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. setDesktopPlatform(raylib, options.platform); }, .macos => { + // Include xcode_frameworks for cross compilation + if (b.lazyDependency("xcode_frameworks", .{})) |dep| { + raylib.addSystemFrameworkPath(dep.path("Frameworks")); + raylib.addSystemIncludePath(dep.path("include")); + raylib.addLibraryPath(dep.path("lib")); + } + // On macos rglfw.c include Objective-C files. - try raylib_flags_arr.append(b.allocator, "-ObjC"); + try raylib_flags_arr.append("-ObjC"); raylib.root_module.addCSourceFile(.{ .file = b.path("src/rglfw.c"), .flags = raylib_flags_arr.items, @@ -271,20 +281,19 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. setDesktopPlatform(raylib, options.platform); }, .emscripten => { - raylib.defineCMacro("PLATFORM_WEB", null); + // Include emscripten for cross compilation + if (b.lazyDependency("emsdk", .{})) |dep| { + if (try emSdkSetupStep(b, dep)) |emSdkStep| { + raylib.step.dependOn(&emSdkStep.step); + } + + raylib.addIncludePath(dep.path("upstream/emscripten/cache/sysroot/include")); + } + + raylib.root_module.addCMacro("PLATFORM_WEB", ""); if (options.opengl_version == .auto) { - raylib.defineCMacro("GRAPHICS_API_OPENGL_ES2", null); + raylib.root_module.addCMacro("GRAPHICS_API_OPENGL_ES2", ""); } - - if (b.sysroot == null) { - @panic("Pass '--sysroot \"$EMSDK/upstream/emscripten\"'"); - } - - const cache_include = b.pathJoin(&.{ b.sysroot.?, "cache", "sysroot", "include" }); - - var dir = std.fs.openDirAbsolute(cache_include, std.fs.Dir.OpenDirOptions{ .access_sub_paths = true, .no_follow = true }) catch @panic("No emscripten cache. Generate it!"); - dir.close(); - raylib.addIncludePath(.{ .cwd_relative = cache_include }); }, else => { @panic("Unsupported OS"); @@ -299,20 +308,15 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. return raylib; } -/// This function does not need to be called if you passed .raygui = true to addRaylib pub fn addRaygui(b: *std.Build, raylib: *std.Build.Step.Compile, raygui_dep: *std.Build.Dependency) void { - if (raylib_flags_arr.items.len == 0) { - @panic( - \\argument 2 `raylib` in `addRaygui` must come from b.dependency("raylib", ...).artifact("raylib") - ); - } - + const raylib_dep = b.dependencyFromBuildZig(@This(), .{}); var gen_step = b.addWriteFiles(); raylib.step.dependOn(&gen_step.step); const raygui_c_path = gen_step.add("raygui.c", "#define RAYGUI_IMPLEMENTATION\n#include \"raygui.h\"\n"); - raylib.addCSourceFile(.{ .file = raygui_c_path, .flags = raylib_flags_arr.items }); + raylib.addCSourceFile(.{ .file = raygui_c_path }); raylib.addIncludePath(raygui_dep.path("src")); + raylib.addIncludePath(raylib_dep.path("src")); raylib.installHeader(raygui_dep.path("src/raygui.h"), "raygui.h"); } @@ -323,7 +327,6 @@ pub const Options = struct { rshapes: bool = true, rtext: bool = true, rtextures: bool = true, - raygui: bool = false, platform: PlatformBackend = .glfw, shared: bool = false, linux_display_backend: LinuxDisplayBackend = .Both, @@ -331,15 +334,12 @@ pub const Options = struct { /// config should be a list of space-separated cflags, eg, "-DSUPPORT_CUSTOM_FRAME_CONTROL" config: []const u8 = &.{}, - raygui_dependency_name: []const u8 = "raygui", - const defaults = Options{}; - fn getOptions(b: *std.Build) Options { + pub fn getOptions(b: *std.Build) Options { return .{ .platform = b.option(PlatformBackend, "platform", "Choose the platform backedn for desktop target") orelse defaults.platform, .raudio = b.option(bool, "raudio", "Compile with audio support") orelse defaults.raudio, - .raygui = b.option(bool, "raygui", "Compile with raygui support") orelse defaults.raygui, .rmodels = b.option(bool, "rmodels", "Compile with models support") orelse defaults.rmodels, .rtext = b.option(bool, "rtext", "Compile with text support") orelse defaults.rtext, .rtextures = b.option(bool, "rtextures", "Compile with textures support") orelse defaults.rtextures, @@ -401,6 +401,7 @@ pub fn build(b: *std.Build) !void { const lib = try compileRaylib(b, target, optimize, Options.getOptions(b)); 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/rlgl.h"), "rlgl.h"); diff --git a/build.zig.zon b/build.zig.zon new file mode 100644 index 000000000..077865978 --- /dev/null +++ b/build.zig.zon @@ -0,0 +1,24 @@ +.{ + .name = "raylib", + .version = "5.5.0", + .minimum_zig_version = "0.13.0", + + .dependencies = .{ + .xcode_frameworks = .{ + .url = "git+https://github.com/hexops/xcode-frameworks#9a45f3ac977fd25dff77e58c6de1870b6808c4a7", + .hash = "122098b9174895f9708bc824b0f9e550c401892c40a900006459acf2cbf78acd99bb", + .lazy = true, + }, + .emsdk = .{ + .url = "git+https://github.com/emscripten-core/emsdk#3.1.50", + .hash = "1220e8fe9509f0843e5e22326300ca415c27afbfbba3992f3c3184d71613540b5564", + .lazy = true, + }, + }, + + .paths = .{ + "build.zig", + "build.zig.zon", + "src", + }, +} diff --git a/cmake/LibraryConfigurations.cmake b/cmake/LibraryConfigurations.cmake index fb7898306..00dda033a 100644 --- a/cmake/LibraryConfigurations.cmake +++ b/cmake/LibraryConfigurations.cmake @@ -69,6 +69,14 @@ elseif (${PLATFORM} MATCHES "Android") set(CMAKE_POSITION_INDEPENDENT_CODE ON) list(APPEND raylib_sources ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) include_directories(${ANDROID_NDK}/sources/android/native_app_glue) + + # NOTE: We remove '-Wl,--no-undefined' (set by default) as it conflicts with '-Wl,-undefined,dynamic_lookup' needed + # for compiling with the missing 'void main(void)' declaration in `android_main()`. + # We also remove other unnecessary or problematic flags. + + string(REPLACE "-Wl,--no-undefined -Qunused-arguments" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") + string(REPLACE "-static-libstdc++" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--exclude-libs,libatomic.a -Wl,--build-id -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--warn-shared-textrel -Wl,--fatal-warnings -u ANativeActivity_onCreate -Wl,-undefined,dynamic_lookup") find_library(OPENGL_LIBRARY OpenGL) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 64b6d7604..f77ece4c0 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -124,7 +124,21 @@ endif () # The rlgl_standalone example only targets desktop, without shared libraries. if (BUILD_SHARED_LIBS OR NOT ${PLATFORM} MATCHES "Desktop") list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/rlgl_standalone.c) +endif() +# The audio examples fail to link if raylib is built without raudio +if (NOT SUPPORT_MODULE_RAUDIO) + list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/audio/audio_mixed_processor.c) + list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/audio/audio_module_playing.c) + list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/audio/audio_music_stream.c) + list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/audio/audio_raw_stream.c) + list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/audio/audio_sound_loading.c) + list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/audio/audio_sound_multi.c) + list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/audio/audio_stream_effects.c) + + list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/embedded_files_loading.c) + list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/textures/textures_sprite_button.c) + list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/textures/textures_sprite_explosion.c) endif() include_directories(BEFORE SYSTEM others/external/include) diff --git a/examples/Makefile b/examples/Makefile index 304599cf8..834007c26 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -20,6 +20,8 @@ # - Linux (X11 desktop mode) # - macOS/OSX (x64, arm64 (not tested)) # - Others (not tested) +# > PLATFORM_WEB_RGFW: +# - HTML5 (WebAssembly) # > PLATFORM_WEB: # - HTML5 (WebAssembly) # > PLATFORM_DRM: @@ -28,7 +30,7 @@ # > PLATFORM_ANDROID: # - Android (ARM, ARM64) # -# Copyright (c) 2013-2024 Ramon Santamaria (@raysan5) +# Copyright (c) 2013-2025 Ramon Santamaria (@raysan5) # # This software is provided "as-is", without any express or implied warranty. In no event # will the authors be held liable for any damages arising from the use of this software. @@ -51,13 +53,18 @@ # Define required environment variables #------------------------------------------------------------------------------------------------ -# Define target platform: PLATFORM_DESKTOP, PLATFORM_DESKTOP_SDL, PLATFORM_DRM, PLATFORM_ANDROID, PLATFORM_WEB +# Define target platform: PLATFORM_DESKTOP, PLATFORM_DESKTOP_SDL, PLATFORM_DRM, PLATFORM_ANDROID, PLATFORM_WEB, PLATFORM_WEB_RGFW PLATFORM ?= PLATFORM_DESKTOP -ifeq ($(PLATFORM), PLATFORM_DESKTOP) - TARGET_PLATFORM = PLATFORM_DESKTOP_GLFW +ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_DESKTOP_GLFW PLATFORM_DESKTOP_SDL PLATFORM_DESKTOP_RGFW)) + TARGET_PLATFORM := $(PLATFORM) + override PLATFORM = PLATFORM_DESKTOP else - TARGET_PLATFORM = $(PLATFORM) + ifeq ($(PLATFORM), PLATFORM_DESKTOP) + TARGET_PLATFORM = PLATFORM_DESKTOP_GLFW + else + TARGET_PLATFORM = $(PLATFORM) + endif endif # Define required raylib variables @@ -87,6 +94,8 @@ USE_EXTERNAL_GLFW ?= FALSE # WARNING: Library is not included in raylib, it MUST be configured by users SDL_INCLUDE_PATH ?= $(RAYLIB_SRC_PATH)/external/SDL2/include SDL_LIBRARY_PATH ?= $(RAYLIB_SRC_PATH)/external/SDL2/lib +SDL_LIBRARIES ?= -lSDL2 -lSDL2main + # Use Wayland display server protocol on Linux desktop (by default it uses X11 windowing system) # NOTE: This variable is only used for PLATFORM_OS: LINUX @@ -100,7 +109,7 @@ BUILD_WEB_RESOURCES ?= TRUE BUILD_WEB_RESOURCES_PATH ?= $(dir $<)resources@resources # Determine PLATFORM_OS when required -ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW PLATFORM_DESKTOP_SDL PLATFORM_DESKTOP_RGFW PLATFORM_WEB)) +ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW PLATFORM_DESKTOP_SDL PLATFORM_DESKTOP_RGFW PLATFORM_WEB PLATFORM_WEB_RGFW)) # No uname.exe on MinGW!, but OS=Windows_NT on Windows! # ifeq ($(UNAME),Msys) -> Windows ifeq ($(OS),Windows_NT) @@ -151,10 +160,10 @@ endif # Define raylib release directory for compiled library RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/src -ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) +ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) ifeq ($(PLATFORM_OS),WINDOWS) # Emscripten required variables - EMSDK_PATH ?= C:/emsdk + EMSDK_PATH ?= C:/raylib/emsdk EMSCRIPTEN_PATH ?= $(EMSDK_PATH)/upstream/emscripten CLANG_PATH = $(EMSDK_PATH)/upstream/bin PYTHON_PATH = $(EMSDK_PATH)/python/3.9.2-nuget_64bit @@ -177,8 +186,8 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) CC = clang endif endif -ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) - # HTML5 emscripten compiler +ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) + # HTML5 emscripten compiler # WARNING: To compile to HTML5, code must be redesigned # to use emscripten.h and emscripten_set_main_loop() CC = emcc @@ -196,7 +205,7 @@ endif ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) MAKE = mingw32-make endif -ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) +ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) ifeq ($(OS),Windows_NT) MAKE = mingw32-make else @@ -224,11 +233,11 @@ CFLAGS = -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces -Wunused-result ifeq ($(BUILD_MODE),DEBUG) CFLAGS += -g -D_DEBUG - ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) + ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) CFLAGS += -sASSERTIONS=1 --profiling endif -else - ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) +else + ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) ifeq ($(BUILD_WEB_ASYNCIFY),TRUE) CFLAGS += -O3 else @@ -263,9 +272,9 @@ endif # Define include paths for required headers: INCLUDE_PATHS # NOTE: Some external/extras libraries could be required (stb, easings...) #------------------------------------------------------------------------------------------------ -INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external - +INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external $(EXTRA_INCLUDE_PATHS) # Define additional directories containing required header files + ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) ifeq ($(PLATFORM_OS),BSD) INCLUDE_PATHS += -I$(RAYLIB_INCLUDE_PATH) -I/usr/pkg/include -I/usr/X11R7/include @@ -318,25 +327,31 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_SDL) endif LDFLAGS += -L$(SDL_LIBRARY_PATH) endif -ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) +ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) # -Os # size optimization # -O2 # optimization level 2, if used, also set --memory-init-file 0 - # -sUSE_GLFW=3 # Use glfw3 library (context/input management) - # -sALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL! - # -sTOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) (67108864 = 64MB) - # -sUSE_PTHREADS=1 # multithreading support - # -sWASM=0 # disable Web Assembly, emitted by default - # -sASYNCIFY # lets synchronous C/C++ code interact with asynchronous JS - # -sFORCE_FILESYSTEM=1 # force filesystem to load/save files data - # -sASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off) - # -sGL_ENABLE_GET_PROC_ADDRESS # enable using the *glGetProcAddress() family of functions, required for extensions loading + # -sUSE_GLFW=3 # Use glfw3 library (context/input management) + # -sALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL! + # -sTOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) (67108864 = 64MB) + # -sUSE_PTHREADS=1 # multithreading support + # -sWASM=0 # disable Web Assembly, emitted by default + # -sASYNCIFY # lets synchronous C/C++ code interact with asynchronous JS + # -sFORCE_FILESYSTEM=1 # force filesystem to load/save files data + # -sASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off) + # -sMINIFY_HTML=0 # minify generated html from shell.html # --profiling # include information for code profiling # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) # --preload-file resources # specify a resources folder for data compilation # --source-map-base # allow debugging in browser with source map - LDFLAGS += -sUSE_GLFW=3 -sTOTAL_MEMORY=$(BUILD_WEB_HEAP_SIZE) -sFORCE_FILESYSTEM=1 - - # Build using asyncify + # --shell-file shell.html # define a custom shell .html and output extension + LDFLAGS += -sTOTAL_MEMORY=$(BUILD_WEB_HEAP_SIZE) -sFORCE_FILESYSTEM=1 -sMINIFY_HTML=0 + + # Using GLFW3 library (instead of RGFW) + ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) + LDFLAGS += -sUSE_GLFW=3 + endif + + # Build using asyncify ifeq ($(BUILD_WEB_ASYNCIFY),TRUE) LDFLAGS += -sASYNCIFY endif @@ -415,12 +430,12 @@ endif ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_SDL) ifeq ($(PLATFORM_OS),WINDOWS) # Libraries for Windows desktop compilation - LDLIBS = -lraylib -lSDL2 -lSDL2main -lopengl32 -lgdi32 + LDLIBS = -lraylib $(SDL_LIBRARIES) -lopengl32 -lgdi32 endif ifeq ($(PLATFORM_OS),LINUX) # Libraries for Debian GNU/Linux desktop compiling # NOTE: Required packages: libegl1-mesa-dev - LDLIBS = -lraylib -lSDL2 -lSDL2main -lGL -lm -lpthread -ldl -lrt + LDLIBS = -lraylib $(SDL_LIBRARIES) -lGL -lm -lpthread -ldl -lrt # On X11 requires also below libraries LDLIBS += -lX11 @@ -473,9 +488,9 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) # NOTE: Required packages: libasound2-dev (ALSA) LDLIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lgbm -ldrm -ldl -latomic endif -ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) +ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) # Libraries for web (HTML5) compiling - LDLIBS = $(RAYLIB_RELEASE_PATH)/libraylib.a + LDLIBS = $(RAYLIB_RELEASE_PATH)/libraylib.web.a endif # Define source code object files required @@ -498,7 +513,6 @@ CORE = \ core/core_custom_logging \ core/core_drop_files \ core/core_input_gamepad \ - core/core_input_gamepad_info \ core/core_input_gestures \ core/core_input_gestures_web \ core/core_input_keys \ @@ -533,10 +547,11 @@ SHAPES = \ shapes/shapes_lines_bezier \ shapes/shapes_logo_raylib \ shapes/shapes_logo_raylib_anim \ + shapes/shapes_rectangle_advanced \ shapes/shapes_rectangle_scaling \ shapes/shapes_splines_drawing \ - shapes/shapes_top_down_lights \ - shapes/shapes_rectangle_advanced + shapes/shapes_top_down_lights + TEXTURES = \ textures/textures_background_scrolling \ @@ -589,6 +604,7 @@ MODELS = \ models/models_draw_cube_texture \ models/models_first_person_maze \ models/models_geometric_shapes \ + models/models_gpu_skinning \ models/models_heightmap \ models/models_loading \ models/models_loading_gltf \ @@ -600,9 +616,9 @@ MODELS = \ models/models_point_rendering \ models/models_rlgl_solar_system \ models/models_skybox \ + models/models_tesseract_view \ models/models_waving_cubes \ - models/models_yaw_pitch_roll \ - models/models_gpu_skinning + models/models_yaw_pitch_roll SHADERS = \ shaders/shaders_basic_lighting \ @@ -646,8 +662,12 @@ OTHERS = \ others/embedded_files_loading \ others/raylib_opengl_interop \ others/raymath_vector_angle \ - others/rlgl_compute_shader \ - others/rlgl_standalone + others/rlgl_compute_shader + +ifeq ($(TARGET_PLATFORM), PLATFORM_DESKTOP_GFLW) + OTHERS += others/rlgl_standalone +endif + CURRENT_MAKEFILE = $(lastword $(MAKEFILE_LIST)) @@ -670,7 +690,7 @@ others: $(OTHERS) %: %.c ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) $(MAKE) -f Makefile.Android PROJECT_NAME=$@ PROJECT_SOURCE_FILES=$< -else ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) +else ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) $(MAKE) -f Makefile.Web $@ else $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) -D$(TARGET_PLATFORM) @@ -699,7 +719,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) find . -type f -executable -delete rm -fv *.o endif -ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) +ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) ifeq ($(PLATFORM_OS),WINDOWS) del *.wasm *.html *.js *.data else diff --git a/examples/Makefile.Android b/examples/Makefile.Android index 01d88fa49..c00da171e 100644 --- a/examples/Makefile.Android +++ b/examples/Makefile.Android @@ -2,7 +2,7 @@ # # raylib makefile for Android project (APK building) # -# Copyright (c) 2017-2024 Ramon Santamaria (@raysan5) +# Copyright (c) 2017-2025 Ramon Santamaria (@raysan5) # # This software is provided "as-is", without any express or implied warranty. In no event # will the authors be held liable for any damages arising from the use of this software. diff --git a/examples/Makefile.Web b/examples/Makefile.Web index 250145053..c9becc29b 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -1,8 +1,8 @@ #************************************************************************************************** # -# raylib makefile for Desktop platforms, Raspberry Pi, Android and HTML5 +# raylib makefile for Web platform # -# Copyright (c) 2013-2024 Ramon Santamaria (@raysan5) +# Copyright (c) 2013-2025 Ramon Santamaria (@raysan5) # # This software is provided "as-is", without any express or implied warranty. In no event # will the authors be held liable for any damages arising from the use of this software. @@ -30,9 +30,12 @@ PLATFORM ?= PLATFORM_WEB # Define required raylib variables PROJECT_NAME ?= raylib_examples -RAYLIB_VERSION ?= 5.0.0 +RAYLIB_VERSION ?= 5.5.0 RAYLIB_PATH ?= .. +# Define raylib source code path +RAYLIB_SRC_PATH ?= ../src + # Locations of raylib.h and libraylib.a/libraylib.so # NOTE: Those variables are only used for PLATFORM_OS: LINUX, BSD DESTDIR ?= /usr/local @@ -52,12 +55,17 @@ USE_EXTERNAL_GLFW ?= FALSE # NOTE: This variable is only used for PLATFORM_OS: LINUX USE_WAYLAND_DISPLAY ?= FALSE +# PLATFORM_WEB: Default properties +BUILD_WEB_ASYNCIFY ?= TRUE +BUILD_WEB_SHELL ?= $(RAYLIB_PATH)/src/shell.html +BUILD_WEB_HEAP_SIZE ?= 134217728 + # Use WebGL2 backend (OpenGL 3.0) # WARNING: Requires raylib compiled with GRAPHICS_API_OPENGL_ES3 USE_WEBGL2 ?= FALSE # Determine PLATFORM_OS in case PLATFORM_DESKTOP or PLATFORM_WEB selected -ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_DESKTOP PLATFORM_WEB)) +ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_DESKTOP PLATFORM_WEB PLATFORM_WEB_RGFW)) # No uname.exe on MinGW!, but OS=Windows_NT on Windows! # ifeq ($(UNAME),Msys) -> Windows ifeq ($(OS),Windows_NT) @@ -108,10 +116,10 @@ endif # Define raylib release directory for compiled library RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/src -ifeq ($(PLATFORM),PLATFORM_WEB) +ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) ifeq ($(PLATFORM_OS),WINDOWS) # Emscripten required variables - EMSDK_PATH ?= C:/emsdk + EMSDK_PATH ?= C:/raylib/emsdk EMSCRIPTEN_PATH ?= $(EMSDK_PATH)/upstream/emscripten CLANG_PATH = $(EMSDK_PATH)/upstream/bin PYTHON_PATH = $(EMSDK_PATH)/python/3.9.2-nuget_64bit @@ -134,7 +142,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) CC = clang endif endif -ifeq ($(PLATFORM),PLATFORM_WEB) +ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) # HTML5 emscripten compiler # WARNING: To compile to HTML5, code must be redesigned # to use emscripten.h and emscripten_set_main_loop() @@ -153,7 +161,7 @@ endif ifeq ($(PLATFORM),PLATFORM_ANDROID) MAKE = mingw32-make endif -ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) +ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) ifeq ($(OS),Windows_NT) MAKE = mingw32-make else @@ -181,11 +189,11 @@ CFLAGS = -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces -Wunused-result ifeq ($(BUILD_MODE),DEBUG) CFLAGS += -g -D_DEBUG - ifeq ($(PLATFORM),PLATFORM_WEB) + ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) CFLAGS += -sASSERTIONS=1 --profiling endif else - ifeq ($(PLATFORM),PLATFORM_WEB) + ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) ifeq ($(BUILD_WEB_ASYNCIFY),TRUE) CFLAGS += -O3 else @@ -255,24 +263,34 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) LDFLAGS += -Lsrc -L$(RAYLIB_LIB_PATH) endif endif -ifeq ($(PLATFORM),PLATFORM_WEB) +ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) # -Os # size optimization # -O2 # optimization level 2, if used, also set --memory-init-file 0 - # -sUSE_GLFW=3 # Use glfw3 library (context/input management) - # -sALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL! - # -sTOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) (67108864 = 64MB) - # -sUSE_PTHREADS=1 # multithreading support - # -sWASM=0 # disable Web Assembly, emitted by default - # -sASYNCIFY # lets synchronous C/C++ code interact with asynchronous JS - # -sFORCE_FILESYSTEM=1 # force filesystem to load/save files data - # -sASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off) - # -sEXPORTED_RUNTIME_METHODS=ccall # require exporting some LEGACY_RUNTIME functions, ccall() is required by miniaudio - # -sGL_ENABLE_GET_PROC_ADDRESS # enable using the *glGetProcAddress() family of functions, required for extensions loading + # -sUSE_GLFW=3 # Use glfw3 library (context/input management) + # -sALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL! + # -sTOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) (67108864 = 64MB) + # -sUSE_PTHREADS=1 # multithreading support + # -sWASM=0 # disable Web Assembly, emitted by default + # -sASYNCIFY # lets synchronous C/C++ code interact with asynchronous JS + # -sFORCE_FILESYSTEM=1 # force filesystem to load/save files data + # -sASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off) + # -sMINIFY_HTML=0 # minify generated html from shell.html # --profiling # include information for code profiling # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) # --preload-file resources # specify a resources folder for data compilation # --source-map-base # allow debugging in browser with source map - LDFLAGS += -sUSE_GLFW=3 -sASYNCIFY -sEXPORTED_RUNTIME_METHODS=ccall + # --shell-file shell.html # define a custom shell .html and output extension + LDFLAGS += -sTOTAL_MEMORY=$(BUILD_WEB_HEAP_SIZE) -sFORCE_FILESYSTEM=1 -sEXPORTED_RUNTIME_METHODS=ccall -sMINIFY_HTML=0 + + # Using GLFW3 library (instead of RGFW) + ifeq ($(PLATFORM),PLATFORM_WEB) + LDFLAGS += -sUSE_GLFW=3 + endif + + # Build using asyncify + ifeq ($(BUILD_WEB_ASYNCIFY),TRUE) + LDFLAGS += -sASYNCIFY + endif # NOTE: Flags required for WebGL 2.0 (OpenGL ES 3.0) # WARNING: Requires raylib compiled with GRAPHICS_API_OPENGL_ES3 @@ -280,17 +298,20 @@ ifeq ($(PLATFORM),PLATFORM_WEB) LDFLAGS += -sMIN_WEBGL_VERSION=2 -sMAX_WEBGL_VERSION=2 endif + # Add debug mode flags if required + ifeq ($(BUILD_MODE),DEBUG) + LDFLAGS += -sASSERTIONS=1 --profiling + endif + + # Define a custom shell .html and output extension + LDFLAGS += --shell-file $(BUILD_WEB_SHELL) + EXT = .html + # NOTE: Simple raylib examples are compiled to be interpreter with asyncify, that way, # we can compile same code for ALL platforms with no change required, but, working on bigger # projects, code needs to be refactored to avoid a blocking while() loop, moving Update and Draw # logic to a self contained function: UpdateDrawFrame(), check core_basic_window_web.c for reference. - # NOTE: Additional compilate flags for TOTAL_MEMORY, FORCE_FILESYSTEM and resources loading - # are specified per-example for optimization - - # Define a custom shell .html and output extension - LDFLAGS += --shell-file $(RAYLIB_PATH)/src/shell.html - EXT = .html endif # Define libraries required on linking: LDLIBS @@ -332,7 +353,8 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),BSD) # Libraries for FreeBSD, OpenBSD, NetBSD, DragonFly desktop compiling # NOTE: Required packages: mesa-libs - LDLIBS = -lraylib -lGL -lpthread -lm + LDFLAGS += -L/usr/X11R7/lib -Wl,-R/usr/X11R7/lib + LDLIBS = -lraylib -lGL -lm -lpthread # On XWindow requires also below libraries LDLIBS += -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor @@ -347,9 +369,9 @@ ifeq ($(PLATFORM),PLATFORM_DRM) # NOTE: Required packages: libasound2-dev (ALSA) LDLIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lgbm -ldrm -ldl -latomic endif -ifeq ($(PLATFORM),PLATFORM_WEB) +ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) # Libraries for web (HTML5) compiling - LDLIBS = $(RAYLIB_RELEASE_PATH)/libraylib.a + LDLIBS = $(RAYLIB_RELEASE_PATH)/libraylib.web.a endif # Define source code object files required @@ -367,11 +389,11 @@ CORE = \ core/core_automation_events \ core/core_basic_screen_manager \ core/core_basic_window \ + core/core_basic_window_web \ core/core_custom_frame_control \ core/core_custom_logging \ core/core_drop_files \ core/core_input_gamepad \ - core/core_input_gamepad_info \ core/core_input_gestures \ core/core_input_gestures_web \ core/core_input_keys \ @@ -406,6 +428,7 @@ SHAPES = \ shapes/shapes_lines_bezier \ shapes/shapes_logo_raylib \ shapes/shapes_logo_raylib_anim \ + shapes/shapes_rectangle_advanced \ shapes/shapes_rectangle_scaling \ shapes/shapes_splines_drawing \ shapes/shapes_top_down_lights @@ -417,6 +440,7 @@ TEXTURES = \ textures/textures_draw_tiled \ textures/textures_fog_of_war \ textures/textures_gif_player \ + textures/textures_image_channel \ textures/textures_image_drawing \ textures/textures_image_generation \ textures/textures_image_kernel \ @@ -453,13 +477,14 @@ TEXT = \ MODELS = \ models/models_animation \ - models/models_gpu_skinning \ models/models_billboard \ + models/models_bone_socket \ models/models_box_collisions \ models/models_cubicmap \ models/models_draw_cube_texture \ models/models_first_person_maze \ models/models_geometric_shapes \ + models/models_gpu_skinning \ models/models_heightmap \ models/models_loading \ models/models_loading_gltf \ @@ -471,11 +496,13 @@ MODELS = \ models/models_point_rendering \ models/models_rlgl_solar_system \ models/models_skybox \ + models/models_tesseract_view \ models/models_waving_cubes \ models/models_yaw_pitch_roll SHADERS = \ shaders/shaders_basic_lighting \ + shaders/shaders_basic_pbr \ shaders/shaders_custom_uniform \ shaders/shaders_deferred_render \ shaders/shaders_eratosthenes \ @@ -498,8 +525,8 @@ SHADERS = \ shaders/shaders_texture_outline \ shaders/shaders_texture_tiling \ shaders/shaders_texture_waves \ - shaders/shaders_write_depth \ - shaders/shaders_vertex_displacement + shaders/shaders_vertex_displacement \ + shaders/shaders_write_depth AUDIO = \ audio/audio_mixed_processor \ @@ -567,6 +594,9 @@ core/core_automation_events : core/core_automation_events.c core/core_basic_window: core/core_basic_window.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) +core/core_basic_window_web: core/core_basic_window_web.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) + core/core_basic_screen_manager: core/core_basic_screen_manager.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) @@ -584,9 +614,6 @@ core/core_input_gamepad: core/core_input_gamepad.c --preload-file core/resources/ps3.png@resources/ps3.png \ --preload-file core/resources/xbox.png@resources/xbox.png -core/core_input_gamepad_info: core/core_input_gamepad_info.c - $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) - core/core_input_gestures: core/core_input_gestures.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) @@ -605,7 +632,10 @@ core/core_input_mouse_wheel: core/core_input_mouse_wheel.c core/core_input_multitouch: core/core_input_multitouch.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) -# NOTE: To use multi-threading raylib must be compiled with multi-theading support (-s USE_PTHREADS=1) +core/core_input_virtual_controls: core/core_input_virtual_controls.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) + +# NOTE: To use multi-threading raylib must be compiled with multi-theading support (-sUSE_PTHREADS=1) # WARNING: For security reasons multi-threading is not supported on browsers, it requires cross-origin isolation (Oct.2021) # WARNING: It requires raylib to be compiled using -pthread, so atomic operations and thread-local data (if any) # in its source were transformed to non-atomic operations and non-thread-local data @@ -727,6 +757,10 @@ textures/textures_gif_player: textures/textures_gif_player.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ --preload-file textures/resources/scarfy_run.gif@resources/scarfy_run.gif +textures/textures_image_channel: textures/textures_image_channel.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ + --preload-file textures/resources/fudesumi.png@resources/fudesumi.png + textures/textures_image_drawing: textures/textures_image_drawing.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ --preload-file textures/resources/custom_jupiter_crash.png@resources/custom_jupiter_crash.png \ @@ -887,6 +921,13 @@ models/models_billboard: models/models_billboard.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ --preload-file models/resources/billboard.png@resources/billboard.png +models/models_bone_socket: models/models_bone_socket.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ + --preload-file models/resources/models/gltf/greenman.glb@resources/models/gltf/greenman.glb \ + --preload-file models/resources/models/gltf/greenman_hat.glb@resources/models/gltf/greenman_hat.glb \ + --preload-file models/resources/models/gltf/greenman_sword.glb@resources/models/gltf/greenman_sword.glb \ + --preload-file models/resources/models/gltf/greenman_shield.glb@resources/models/gltf/greenman_shield.glb + models/models_box_collisions: models/models_box_collisions.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) @@ -941,6 +982,9 @@ models/models_mesh_picking: models/models_mesh_picking.c models/models_orthographic_projection: models/models_orthographic_projection.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) +models/models_point_rendering: models/models_point_rendering.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) + models/models_rlgl_solar_system: models/models_rlgl_solar_system.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) @@ -952,6 +996,9 @@ models/models_skybox: models/models_skybox.c --preload-file models/resources/shaders/glsl100/cubemap.vs@resources/shaders/glsl100/cubemap.vs \ --preload-file models/resources/shaders/glsl100/cubemap.fs@resources/shaders/glsl100/cubemap.fs +models/models_tesseract_view: models/models_tesseract_view.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) + models/models_waving_cubes: models/models_waving_cubes.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) @@ -968,6 +1015,24 @@ shaders/shaders_basic_lighting: shaders/shaders_basic_lighting.c --preload-file shaders/resources/shaders/glsl100/lighting.fs@resources/shaders/glsl100/lighting.fs \ --preload-file shaders/resources/shaders/glsl100/lighting.vs@resources/shaders/glsl100/lighting.vs +shaders/shaders_basic_pbr: shaders/shaders_basic_pbr.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ + --preload-file shaders/resources/shaders/glsl100/pbr.vs@resources/shaders/glsl100/pbr.vs \ + --preload-file shaders/resources/shaders/glsl120/pbr.vs@resources/shaders/glsl120/pbr.vs \ + --preload-file shaders/resources/shaders/glsl330/pbr.vs@resources/shaders/glsl330/pbr.vs \ + --preload-file shaders/resources/shaders/glsl100/pbr.fs@resources/shaders/glsl100/pbr.fs \ + --preload-file shaders/resources/shaders/glsl120/pbr.fs@resources/shaders/glsl120/pbr.fs \ + --preload-file shaders/resources/shaders/glsl330/pbr.fs@resources/shaders/glsl330/pbr.fs \ + --preload-file shaders/resources/models/old_car_new.glb@resources/models/old_car_new.glb \ + --preload-file shaders/resources/old_car_d.png@resources/old_car_d.png \ + --preload-file shaders/resources/old_car_mra.png@resources/old_car_mra.png \ + --preload-file shaders/resources/old_car_n.png@resources/old_car_n.png \ + --preload-file shaders/resources/old_car_e.png@resources/old_car_e.png \ + --preload-file shaders/resources/models/plane.glb@resources/models/plane.glb \ + --preload-file shaders/resources/road_a.png@resources/road_a.png \ + --preload-file shaders/resources/road_mra.png@resources/road_mra.png \ + --preload-file shaders/resources/road_n.png@resources/road_n.png + shaders/shaders_custom_uniform: shaders/shaders_custom_uniform.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) -sTOTAL_MEMORY=67108864 \ --preload-file shaders/resources/models/barracks.obj@resources/models/barracks.obj \ @@ -977,10 +1042,10 @@ shaders/shaders_custom_uniform: shaders/shaders_custom_uniform.c shaders/shaders_deferred_render: shaders/shaders_deferred_render.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ --preload-file shaders/resources/fudesumi.png@resources/fudesumi.png \ - --preload-file shaders/resources/shaders/glsl330/gbuffer.vs@resources/shaders/glsl330/gbuffer.vs \ - --preload-file shaders/resources/shaders/glsl330/gbuffer.fs@resources/shaders/glsl330/gbuffer.fs \ - --preload-file shaders/resources/shaders/glsl330/deferred_shading.fs@resources/shaders/glsl330/deferred_shading.fs \ - --preload-file shaders/resources/shaders/glsl330/deferred_shading.fs@resources/shaders/glsl330/deferred_shading.fs + --preload-file shaders/resources/shaders/glsl100/gbuffer.vs@resources/shaders/glsl100/gbuffer.vs \ + --preload-file shaders/resources/shaders/glsl100/gbuffer.fs@resources/shaders/glsl100/gbuffer.fs \ + --preload-file shaders/resources/shaders/glsl100/deferred_shading.vs@resources/shaders/glsl100/deferred_shading.vs \ + --preload-file shaders/resources/shaders/glsl100/deferred_shading.fs@resources/shaders/glsl100/deferred_shading.fs shaders/shaders_eratosthenes: shaders/shaders_eratosthenes.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ @@ -1041,6 +1106,14 @@ shaders/shaders_raymarching: shaders/shaders_raymarching.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ --preload-file shaders/resources/shaders/glsl100/raymarching.fs@resources/shaders/glsl100/raymarching.fs +shaders/shaders_shadowmap: shaders/shaders_shadowmap.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ + --preload-file shaders/resources/shaders/glsl120/shadowmap.vs@resources/shaders/glsl120/shadowmap.vs \ + --preload-file shaders/resources/shaders/glsl330/shadowmap.vs@resources/shaders/glsl330/shadowmap.vs \ + --preload-file shaders/resources/shaders/glsl120/shadowmap.fs@resources/shaders/glsl120/shadowmap.fs \ + --preload-file shaders/resources/shaders/glsl330/shadowmap.fs@resources/shaders/glsl330/shadowmap.fs \ + --preload-file shaders/resources/models/robot.glb@resources/models/robot.glb + shaders/shaders_shapes_textures: shaders/shaders_shapes_textures.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ --preload-file shaders/resources/fudesumi.png@resources/fudesumi.png \ @@ -1081,6 +1154,13 @@ shaders/shaders_write_depth: shaders/shaders_write_depth.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ --preload-file shaders/resources/shaders/glsl100/write_depth.fs@resources/shaders/glsl100/write_depth.fs +shaders/shaders_vertex_displacement: shaders/shaders_vertex_displacement.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ + --preload-file shaders/resources/shaders/glsl100/vertex_displacement.vs@resources/shaders/glsl100/vertex_displacement.vs \ + --preload-file shaders/resources/shaders/glsl330/vertex_displacement.vs@resources/shaders/glsl330/vertex_displacement.vs \ + --preload-file shaders/resources/shaders/glsl100/vertex_displacement.fs@resources/shaders/glsl100/vertex_displacement.fs \ + --preload-file shaders/resources/shaders/glsl330/vertex_displacement.fs@resources/shaders/glsl330/vertex_displacement.fs + # Compile AUDIO examples audio/audio_mixed_processor: audio/audio_mixed_processor.c @@ -1151,7 +1231,7 @@ ifeq ($(PLATFORM),PLATFORM_DRM) find . -type f -executable -delete rm -fv *.o endif -ifeq ($(PLATFORM),PLATFORM_WEB) +ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) del *.o *.html *.js endif @echo Cleaning done diff --git a/examples/audio/audio_mixed_processor.c b/examples/audio/audio_mixed_processor.c index df46edc4e..16c83f36d 100644 --- a/examples/audio/audio_mixed_processor.c +++ b/examples/audio/audio_mixed_processor.c @@ -2,6 +2,8 @@ * * raylib [audio] example - Mixed audio processing * +* Example complexity rating: [★★★★] 4/4 +* * Example originally created with raylib 4.2, last time updated with raylib 4.2 * * Example contributed by hkc (@hatkidchan) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/audio/audio_module_playing.c b/examples/audio/audio_module_playing.c index 6234f0e55..3b77ed3e6 100644 --- a/examples/audio/audio_module_playing.c +++ b/examples/audio/audio_module_playing.c @@ -2,6 +2,8 @@ * * raylib [audio] example - Module playing (streaming) * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.5, last time updated with raylib 3.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/audio/audio_music_stream.c b/examples/audio/audio_music_stream.c index bdf141edf..99d270326 100644 --- a/examples/audio/audio_music_stream.c +++ b/examples/audio/audio_music_stream.c @@ -2,6 +2,8 @@ * * raylib [audio] example - Music playing (streaming) * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.3, last time updated with raylib 4.0 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/audio/audio_raw_stream.c b/examples/audio/audio_raw_stream.c index 0b7954293..9b8338dfc 100644 --- a/examples/audio/audio_raw_stream.c +++ b/examples/audio/audio_raw_stream.c @@ -2,6 +2,8 @@ * * raylib [audio] example - Raw audio streaming * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 1.6, last time updated with raylib 4.2 * * Example created by Ramon Santamaria (@raysan5) and reviewed by James Hofmann (@triplefox) diff --git a/examples/audio/audio_sound_loading.c b/examples/audio/audio_sound_loading.c index 41aa2160e..b96e613de 100644 --- a/examples/audio/audio_sound_loading.c +++ b/examples/audio/audio_sound_loading.c @@ -2,6 +2,8 @@ * * raylib [audio] example - Sound loading and playing * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.1, last time updated with raylib 3.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/audio/audio_sound_multi.c b/examples/audio/audio_sound_multi.c index d5472efab..8d823b8eb 100644 --- a/examples/audio/audio_sound_multi.c +++ b/examples/audio/audio_sound_multi.c @@ -2,6 +2,8 @@ * * raylib [audio] example - Playing sound multiple times * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 4.6 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/audio/audio_stream_effects.c b/examples/audio/audio_stream_effects.c index cc8273abc..ed5bdb105 100644 --- a/examples/audio/audio_stream_effects.c +++ b/examples/audio/audio_stream_effects.c @@ -2,6 +2,8 @@ * * raylib [audio] example - Music stream processing effects * +* Example complexity rating: [★★★★] 4/4 +* * Example originally created with raylib 4.2, last time updated with raylib 5.0 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/build.zig b/examples/build.zig index df0cdf8c1..301381df3 100644 --- a/examples/build.zig +++ b/examples/build.zig @@ -46,7 +46,7 @@ fn add_module(comptime module: []const u8, b: *std.Build, target: std.Build.Reso exe.linkSystemLibrary("gdi32"); exe.linkSystemLibrary("opengl32"); - exe.defineCMacro("PLATFORM_DESKTOP", null); + exe.root_module.addCMacro("PLATFORM_DESKTOP", ""); }, .linux => { exe.linkSystemLibrary("GL"); @@ -55,7 +55,7 @@ fn add_module(comptime module: []const u8, b: *std.Build, target: std.Build.Reso exe.linkSystemLibrary("m"); exe.linkSystemLibrary("X11"); - exe.defineCMacro("PLATFORM_DESKTOP", null); + exe.root_module.addCMacro("PLATFORM_DESKTOP", ""); }, .macos => { exe.linkFramework("Foundation"); @@ -65,7 +65,7 @@ fn add_module(comptime module: []const u8, b: *std.Build, target: std.Build.Reso exe.linkFramework("CoreVideo"); exe.linkFramework("IOKit"); - exe.defineCMacro("PLATFORM_DESKTOP", null); + exe.root_module.addCMacro("PLATFORM_DESKTOP", ""); }, else => { @panic("Unsupported OS"); diff --git a/examples/core/core_2d_camera.c b/examples/core/core_2d_camera.c index 99b61d4e5..6b3ef57d2 100644 --- a/examples/core/core_2d_camera.c +++ b/examples/core/core_2d_camera.c @@ -2,6 +2,8 @@ * * raylib [core] example - 2D Camera system * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 1.5, last time updated with raylib 3.0 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/core/core_2d_camera_mouse_zoom.c b/examples/core/core_2d_camera_mouse_zoom.c index 8af94440d..3b4fb5835 100644 --- a/examples/core/core_2d_camera_mouse_zoom.c +++ b/examples/core/core_2d_camera_mouse_zoom.c @@ -2,6 +2,8 @@ * * raylib [core] example - 2d camera mouse zoom * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 4.2, last time updated with raylib 4.2 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, @@ -45,7 +47,7 @@ int main () else if (IsKeyPressed(KEY_TWO)) zoomMode = 1; // Translate based on mouse right click - if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) + if (IsMouseButtonDown(MOUSE_BUTTON_LEFT)) { Vector2 delta = GetMouseDelta(); delta = Vector2Scale(delta, -1.0f/camera.zoom); @@ -76,8 +78,8 @@ int main () } else { - // Zoom based on mouse left click - if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) + // Zoom based on mouse right click + if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT)) { // Get the world point that is under the mouse Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), camera); @@ -89,7 +91,7 @@ int main () // under the cursor to the screen space point under the cursor at any zoom camera.target = mouseWorldPos; } - if (IsMouseButtonDown(MOUSE_BUTTON_LEFT)) + if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) { // Zoom increment float deltaX = GetMouseDelta().x; @@ -119,10 +121,16 @@ int main () DrawCircle(GetScreenWidth()/2, GetScreenHeight()/2, 50, MAROON); EndMode2D(); + + // Draw mouse reference + //Vector2 mousePos = GetWorldToScreen2D(GetMousePosition(), camera) + DrawCircleV(GetMousePosition(), 4, DARKGRAY); + DrawTextEx(GetFontDefault(), TextFormat("[%i, %i]", GetMouseX(), GetMouseY()), + Vector2Add(GetMousePosition(), (Vector2){ -44, -24 }), 20, 2, BLACK); DrawText("[1][2] Select mouse zoom mode (Wheel or Move)", 20, 20, 20, DARKGRAY); - if (zoomMode == 0) DrawText("Mouse right button drag to move, mouse wheel to zoom", 20, 50, 20, DARKGRAY); - else DrawText("Mouse right button drag to move, mouse press and move to zoom", 20, 50, 20, DARKGRAY); + if (zoomMode == 0) DrawText("Mouse left button drag to move, mouse wheel to zoom", 20, 50, 20, DARKGRAY); + else DrawText("Mouse left button drag to move, mouse press and move to zoom", 20, 50, 20, DARKGRAY); EndDrawing(); //---------------------------------------------------------------------------------- diff --git a/examples/core/core_2d_camera_mouse_zoom.png b/examples/core/core_2d_camera_mouse_zoom.png index b920d5c7b..1c8ab1f2d 100644 Binary files a/examples/core/core_2d_camera_mouse_zoom.png and b/examples/core/core_2d_camera_mouse_zoom.png differ diff --git a/examples/core/core_2d_camera_platformer.c b/examples/core/core_2d_camera_platformer.c index 3743de80b..2fcf77b6e 100644 --- a/examples/core/core_2d_camera_platformer.c +++ b/examples/core/core_2d_camera_platformer.c @@ -2,6 +2,8 @@ * * raylib [core] example - 2D Camera platformer * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 2.5, last time updated with raylib 3.0 * * Example contributed by arvyy (@arvyy) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/core/core_2d_camera_split_screen.c b/examples/core/core_2d_camera_split_screen.c index 60b5a2e55..a5c645797 100644 --- a/examples/core/core_2d_camera_split_screen.c +++ b/examples/core/core_2d_camera_split_screen.c @@ -2,6 +2,8 @@ * * raylib [core] example - 2d camera split screen * +* Example complexity rating: [★★★★] 4/4 +* * Addapted from the core_3d_camera_split_screen example: * https://github.com/raysan5/raylib/blob/master/examples/core/core_3d_camera_split_screen.c * diff --git a/examples/core/core_3d_camera_first_person.c b/examples/core/core_3d_camera_first_person.c index 35b18ace4..809cb3962 100644 --- a/examples/core/core_3d_camera_first_person.c +++ b/examples/core/core_3d_camera_first_person.c @@ -2,6 +2,8 @@ * * raylib [core] example - 3d camera first person * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 1.3, last time updated with raylib 1.3 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, @@ -115,7 +117,7 @@ int main(void) // Update camera computes movement internally depending on the camera mode // Some default standard keyboard/mouse inputs are hardcoded to simplify use - // For advance camera controls, it's reecommended to compute camera movement manually + // For advanced camera controls, it's recommended to compute camera movement manually UpdateCamera(&camera, cameraMode); // Update camera /* @@ -203,4 +205,4 @@ int main(void) //-------------------------------------------------------------------------------------- return 0; -} \ No newline at end of file +} diff --git a/examples/core/core_3d_camera_free.c b/examples/core/core_3d_camera_free.c index 9899dbdb5..349a458cf 100644 --- a/examples/core/core_3d_camera_free.c +++ b/examples/core/core_3d_camera_free.c @@ -2,6 +2,8 @@ * * raylib [core] example - Initialize 3d camera free * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.3, last time updated with raylib 1.3 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/core/core_3d_camera_mode.c b/examples/core/core_3d_camera_mode.c index 0600fd330..90e512965 100644 --- a/examples/core/core_3d_camera_mode.c +++ b/examples/core/core_3d_camera_mode.c @@ -2,6 +2,8 @@ * * raylib [core] example - Initialize 3d camera mode * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.0, last time updated with raylib 1.0 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/core/core_3d_camera_split_screen.c b/examples/core/core_3d_camera_split_screen.c index 5294e8949..8b457bfab 100644 --- a/examples/core/core_3d_camera_split_screen.c +++ b/examples/core/core_3d_camera_split_screen.c @@ -2,6 +2,8 @@ * * raylib [core] example - 3d cmaera split screen * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 3.7, last time updated with raylib 4.0 * * Example contributed by Jeffery Myers (@JeffM2501) and reviewed by Ramon Santamaria (@raysan5) @@ -63,7 +65,7 @@ int main(void) // Update //---------------------------------------------------------------------------------- // If anyone moves this frame, how far will they move based on the time since the last frame - // this moves thigns at 10 world units per second, regardless of the actual FPS + // this moves things at 10 world units per second, regardless of the actual FPS float offsetThisFrame = 10.0f*GetFrameTime(); // Move Player1 forward and backwards (no turning) @@ -171,4 +173,4 @@ int main(void) //-------------------------------------------------------------------------------------- return 0; -} \ No newline at end of file +} diff --git a/examples/core/core_3d_picking.c b/examples/core/core_3d_picking.c index 634afba8c..85d8482ef 100644 --- a/examples/core/core_3d_picking.c +++ b/examples/core/core_3d_picking.c @@ -2,6 +2,8 @@ * * raylib [core] example - Picking in 3d mode * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 1.3, last time updated with raylib 4.0 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/core/core_automation_events.c b/examples/core/core_automation_events.c index 64ca51fda..2a0d5503f 100644 --- a/examples/core/core_automation_events.c +++ b/examples/core/core_automation_events.c @@ -2,6 +2,8 @@ * * raylib [core] example - automation events * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 5.0, last time updated with raylib 5.0 * * Example based on 2d_camera_platformer example by arvyy (@arvyy) diff --git a/examples/core/core_basic_screen_manager.c b/examples/core/core_basic_screen_manager.c index 728ef1257..964c922e4 100644 --- a/examples/core/core_basic_screen_manager.c +++ b/examples/core/core_basic_screen_manager.c @@ -2,6 +2,8 @@ * * raylib [core] examples - basic screen manager * +* Example complexity rating: [★☆☆☆] 1/4 +* * NOTE: This example illustrates a very simple screen manager based on a states machines * * Example originally created with raylib 4.0, last time updated with raylib 4.0 @@ -46,7 +48,7 @@ int main(void) { // Update //---------------------------------------------------------------------------------- - switch(currentScreen) + switch (currentScreen) { case LOGO: { diff --git a/examples/core/core_basic_window.c b/examples/core/core_basic_window.c index 81bea16b8..976227750 100644 --- a/examples/core/core_basic_window.c +++ b/examples/core/core_basic_window.c @@ -2,11 +2,16 @@ * * raylib [core] example - Basic window * +* Example complexity rating: [★☆☆☆] 1/4 +* * Welcome to raylib! * -* To test examples, just press F6 and execute raylib_compile_execute script +* To test examples, just press F6 and execute 'raylib_compile_execute' script * Note that compiled executable is placed in the same folder as .c file * +* To test the examples on Web, press F6 and execute 'raylib_compile_execute_web' script +* Web version of the program is generated in the same folder as .c file +* * You can find all basic examples on C:\raylib\raylib\examples folder or * raylib official webpage: www.raylib.com * diff --git a/examples/core/core_custom_frame_control.c b/examples/core/core_custom_frame_control.c index 9793fc359..0f1cd2391 100644 --- a/examples/core/core_custom_frame_control.c +++ b/examples/core/core_custom_frame_control.c @@ -2,6 +2,8 @@ * * raylib [core] example - custom frame control * +* Example complexity rating: [★★★★] 4/4 +* * NOTE: WARNING: This is an example for advanced users willing to have full control over * the frame processes. By default, EndDrawing() calls the following processes: * 1. Draw remaining batch data: rlDrawRenderBatchActive() diff --git a/examples/core/core_custom_logging.c b/examples/core/core_custom_logging.c index f886267ee..7636585be 100644 --- a/examples/core/core_custom_logging.c +++ b/examples/core/core_custom_logging.c @@ -2,6 +2,8 @@ * * raylib [core] example - Custom logging * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 2.5, last time updated with raylib 2.5 * * Example contributed by Pablo Marcos Oltra (@pamarcos) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/core/core_drop_files.c b/examples/core/core_drop_files.c index 2e51d872b..addf7ec63 100644 --- a/examples/core/core_drop_files.c +++ b/examples/core/core_drop_files.c @@ -2,6 +2,8 @@ * * raylib [core] example - Windows drop files * +* Example complexity rating: [★★☆☆] 2/4 +* * NOTE: This example only works on platforms that support drag & drop (Windows, Linux, OSX, Html5?) * * Example originally created with raylib 1.3, last time updated with raylib 4.2 diff --git a/examples/core/core_input_gamepad.c b/examples/core/core_input_gamepad.c index 538e1c389..2e6e79d7f 100644 --- a/examples/core/core_input_gamepad.c +++ b/examples/core/core_input_gamepad.c @@ -2,6 +2,8 @@ * * raylib [core] example - Gamepad input * +* Example complexity rating: [★☆☆☆] 1/4 +* * NOTE: This example requires a Gamepad connected to the system * raylib is configured to work with the following gamepads: * - Xbox 360 Controller (Xbox 360, Xbox One) @@ -196,7 +198,7 @@ int main(void) { // Draw background: generic - DrawRectangleRounded((Rectangle){ 175, 110, 460, 220}, 0.3f, 0.0f, DARKGRAY); + DrawRectangleRounded((Rectangle){ 175, 110, 460, 220}, 0.3f, 16, DARKGRAY); // Draw buttons: basic DrawCircle(365, 170, 12, RAYWHITE); @@ -225,10 +227,10 @@ int main(void) if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_FACE_RIGHT)) DrawRectangle(217 + 54, 176, 30, 25, RED); // Draw buttons: left-right back - DrawRectangleRounded((Rectangle){ 215, 98, 100, 10}, 0.5f, 0.0f, DARKGRAY); - DrawRectangleRounded((Rectangle){ 495, 98, 100, 10}, 0.5f, 0.0f, DARKGRAY); - if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_TRIGGER_1)) DrawRectangleRounded((Rectangle){ 215, 98, 100, 10}, 0.5f, 0.0f, RED); - if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_TRIGGER_1)) DrawRectangleRounded((Rectangle){ 495, 98, 100, 10}, 0.5f, 0.0f, RED); + DrawRectangleRounded((Rectangle){ 215, 98, 100, 10}, 0.5f, 16, DARKGRAY); + DrawRectangleRounded((Rectangle){ 495, 98, 100, 10}, 0.5f, 16, DARKGRAY); + if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_TRIGGER_1)) DrawRectangleRounded((Rectangle){ 215, 98, 100, 10}, 0.5f, 16, RED); + if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_TRIGGER_1)) DrawRectangleRounded((Rectangle){ 495, 98, 100, 10}, 0.5f, 16, RED); // Draw axis: left joystick Color leftGamepadColor = BLACK; diff --git a/examples/core/core_input_gamepad_info.c b/examples/core/core_input_gamepad_info.c deleted file mode 100644 index 096294681..000000000 --- a/examples/core/core_input_gamepad_info.c +++ /dev/null @@ -1,83 +0,0 @@ -/******************************************************************************************* -* -* raylib [core] example - Gamepad information -* -* NOTE: This example requires a Gamepad connected to the system -* Check raylib.h for buttons configuration -* -* Example originally created with raylib 4.6, last time updated with raylib 4.6 -* -* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, -* BSD-like license that allows static linking with closed source software -* -* Copyright (c) 2013-2024 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main(void) -{ - // Initialization - //-------------------------------------------------------------------------------------- - const int screenWidth = 800; - const int screenHeight = 450; - - SetConfigFlags(FLAG_MSAA_4X_HINT); // Set MSAA 4X hint before windows creation - - InitWindow(screenWidth, screenHeight, "raylib [core] example - gamepad information"); - - SetTargetFPS(60); // Set our game to run at 60 frames-per-second - //-------------------------------------------------------------------------------------- - - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update - //---------------------------------------------------------------------------------- - // TODO: Update your variables here - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - for (int i = 0, y = 5; i < 4; i++) // MAX_GAMEPADS = 4 - { - if (IsGamepadAvailable(i)) - { - DrawText(TextFormat("Gamepad name: %s", GetGamepadName(i)), 10, y, 10, BLACK); - y += 11; - DrawText(TextFormat("\tAxis count: %d", GetGamepadAxisCount(i)), 10, y, 10, BLACK); - y += 11; - - for (int axis = 0; axis < GetGamepadAxisCount(i); axis++) - { - DrawText(TextFormat("\tAxis %d = %f", axis, GetGamepadAxisMovement(i, axis)), 10, y, 10, BLACK); - y += 11; - } - - for (int button = 0; button < 32; button++) - { - DrawText(TextFormat("\tButton %d = %d", button, IsGamepadButtonDown(i, button)), 10, y, 10, BLACK); - y += 11; - } - } - } - - DrawFPS(GetScreenWidth() - 100, 100); - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- -} diff --git a/examples/core/core_input_gestures.c b/examples/core/core_input_gestures.c index 27ecef56e..5c2fc9482 100644 --- a/examples/core/core_input_gestures.c +++ b/examples/core/core_input_gestures.c @@ -2,6 +2,8 @@ * * raylib [core] example - Input Gestures Detection * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 1.4, last time updated with raylib 4.2 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/core/core_input_keys.c b/examples/core/core_input_keys.c index 8e74b93b0..a07739b22 100644 --- a/examples/core/core_input_keys.c +++ b/examples/core/core_input_keys.c @@ -2,6 +2,8 @@ * * raylib [core] example - Keyboard input * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.0, last time updated with raylib 1.0 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/core/core_input_mouse.c b/examples/core/core_input_mouse.c index e6a3e15dc..6091ded45 100644 --- a/examples/core/core_input_mouse.c +++ b/examples/core/core_input_mouse.c @@ -2,12 +2,14 @@ * * raylib [core] example - Mouse input * -* Example originally created with raylib 1.0, last time updated with raylib 4.0 +* Example complexity rating: [★☆☆☆] 1/4 +* +* Example originally created with raylib 1.0, last time updated with raylib 5.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ @@ -27,6 +29,7 @@ int main(void) Vector2 ballPosition = { -100.0f, -100.0f }; Color ballColor = DARKBLUE; + int isCursorHidden = 0; SetTargetFPS(60); // Set our game to run at 60 frames-per-second //--------------------------------------------------------------------------------------- @@ -36,6 +39,20 @@ int main(void) { // Update //---------------------------------------------------------------------------------- + if (IsKeyPressed(KEY_H)) + { + if (isCursorHidden == 0) + { + HideCursor(); + isCursorHidden = 1; + } + else + { + ShowCursor(); + isCursorHidden = 0; + } + } + ballPosition = GetMousePosition(); if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) ballColor = MAROON; @@ -56,6 +73,10 @@ int main(void) DrawCircleV(ballPosition, 40, ballColor); DrawText("move ball with mouse and click mouse button to change color", 10, 10, 20, DARKGRAY); + DrawText("Press 'H' to toggle cursor visibility", 10, 30, 20, DARKGRAY); + + if (isCursorHidden == 1) DrawText("CURSOR HIDDEN", 20, 60, 20, RED); + else DrawText("CURSOR VISIBLE", 20, 60, 20, LIME); EndDrawing(); //---------------------------------------------------------------------------------- diff --git a/examples/core/core_input_mouse_wheel.c b/examples/core/core_input_mouse_wheel.c index d261e9348..2583ebbb5 100644 --- a/examples/core/core_input_mouse_wheel.c +++ b/examples/core/core_input_mouse_wheel.c @@ -2,6 +2,8 @@ * * raylib [core] examples - Mouse wheel input * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.1, last time updated with raylib 1.3 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/core/core_input_multitouch.c b/examples/core/core_input_multitouch.c index 73b363576..af9a77a5a 100644 --- a/examples/core/core_input_multitouch.c +++ b/examples/core/core_input_multitouch.c @@ -2,6 +2,8 @@ * * raylib [core] example - Input multitouch * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 2.1, last time updated with raylib 2.5 * * Example contributed by Berni (@Berni8k) and reviewed by Ramon Santamaria (@raysan5) @@ -42,7 +44,7 @@ int main(void) // Get the touch point count ( how many fingers are touching the screen ) int tCount = GetTouchPointCount(); // Clamp touch points available ( set the maximum touch points allowed ) - if(tCount > MAX_TOUCH_POINTS) tCount = MAX_TOUCH_POINTS; + if (tCount > MAX_TOUCH_POINTS) tCount = MAX_TOUCH_POINTS; // Get touch points positions for (int i = 0; i < tCount; ++i) touchPositions[i] = GetTouchPosition(i); //---------------------------------------------------------------------------------- diff --git a/examples/core/core_input_virtual_controls.c b/examples/core/core_input_virtual_controls.c index 2d2b91e67..799c927c0 100644 --- a/examples/core/core_input_virtual_controls.c +++ b/examples/core/core_input_virtual_controls.c @@ -6,7 +6,8 @@ * * Example create by GreenSnakeLinux (@GreenSnakeLinux), * 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, * BSD-like license that allows static linking with closed source software @@ -17,6 +18,16 @@ #include "raylib.h" #include + +typedef enum { + BUTTON_NONE = -1, + BUTTON_UP, + BUTTON_LEFT, + BUTTON_RIGHT, + BUTTON_DOWN, + BUTTON_MAX +} PadButton; + //------------------------------------------------------------------------------------ // Program main entry point //------------------------------------------------------------------------------------ @@ -29,24 +40,38 @@ int main(void) InitWindow(screenWidth, screenHeight, "raylib [core] example - input virtual controls"); - const int dpadX = 90; - const int dpadY = 300; - const int dpadRad = 25;//radius of each pad - Color dpadColor = BLUE; - int dpadKeydown = -1;//-1 if not down, else 0,1,2,3 + Vector2 padPosition = { 100, 350 }; + float buttonRadius = 30; - - const float dpadCollider[4][2]= // collider array with x,y position + Vector2 buttonPositions[BUTTON_MAX] = { - {dpadX,dpadY-dpadRad*1.5},//up - {dpadX-dpadRad*1.5,dpadY},//left - {dpadX+dpadRad*1.5,dpadY},//right - {dpadX,dpadY+dpadRad*1.5}//down + { padPosition.x,padPosition.y - buttonRadius*1.5f }, // Up + { padPosition.x - buttonRadius*1.5f, padPosition.y }, // Left + { padPosition.x + buttonRadius*1.5f, padPosition.y }, // Right + { padPosition.x, padPosition.y + buttonRadius*1.5f } // Down }; - const char dpadLabel[4]="XYBA";//label of Dpad - float playerX=100; - float playerY=100; + const char *buttonLabels[BUTTON_MAX] = + { + "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); //-------------------------------------------------------------------------------------- @@ -54,63 +79,73 @@ int main(void) // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { - // Update - //-------------------------------------------------------------------------- - dpadKeydown = -1; //reset - float inputX=0; - float inputY=0; - if(GetTouchPointCount()>0) - {//use touch pos - inputX = GetTouchX(); - inputY = GetTouchY(); + // Update + //-------------------------------------------------------------------------- + if ((GetTouchPointCount() > 0)) + { + // Use touch position + inputPosition = GetTouchPosition(0); } else - {//use mouse pos - inputX = GetMouseX(); - inputY = GetMouseY(); - } - for(int i=0;i<4;i++) { - //test distance each collider and input < radius - if( fabsf(dpadCollider[i][1]-inputY) + fabsf(dpadCollider[i][0]-inputX) < dpadRad) - { - dpadKeydown = i; - break; - } + // Use mouse position + inputPosition = GetMousePosition(); } - // move player - switch(dpadKeydown){ - case 0: playerY -= 50*GetFrameTime(); - break; - case 1: playerX -= 50*GetFrameTime(); - break; - case 2: playerX += 50*GetFrameTime(); - break; - case 3: playerY += 50*GetFrameTime(); - default:; - }; - //-------------------------------------------------------------------------- - // Draw - //-------------------------------------------------------------------------- - BeginDrawing(); - ClearBackground(RAYWHITE); - for(int i=0;i<4;i++) + + // Reset pressed button to none + pressedButton = BUTTON_NONE; + + // Make sure user is pressing left mouse button if they're from desktop + if ((GetTouchPointCount() > 0) || ((GetTouchPointCount() == 0) && IsMouseButtonDown(MOUSE_BUTTON_LEFT))) + { + // Find nearest D-Pad button to the input position + for (int i = 0; i < BUTTON_MAX; i++) { - //draw all pad - DrawCircle(dpadCollider[i][0],dpadCollider[i][1],dpadRad,dpadColor); - if(i!=dpadKeydown) + float distX = fabsf(buttonPositions[i].x - inputPosition.x); + float distY = fabsf(buttonPositions[i].y - inputPosition.y); + + if ((distX + distY < buttonRadius)) { - //draw label - DrawText(TextSubtext(dpadLabel,i,1), - dpadCollider[i][0]-7, - dpadCollider[i][1]-8,20,BLACK); + pressedButton = i; + break; } } + } + + // 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); - DrawRectangle(playerX-4,playerY-4,75,28,RED); - DrawText("Player",playerX,playerY,20,WHITE); EndDrawing(); - //-------------------------------------------------------------------------- + //-------------------------------------------------------------------------- } // De-Initialization diff --git a/examples/core/core_input_virtual_controls.png b/examples/core/core_input_virtual_controls.png index cb1444598..83097a54c 100644 Binary files a/examples/core/core_input_virtual_controls.png and b/examples/core/core_input_virtual_controls.png differ diff --git a/examples/core/core_loading_thread.c b/examples/core/core_loading_thread.c index 8e09c99da..8d4302a16 100644 --- a/examples/core/core_loading_thread.c +++ b/examples/core/core_loading_thread.c @@ -2,6 +2,8 @@ * * raylib [core] example - loading thread * +* Example complexity rating: [★★★☆] 3/4 +* * NOTE: This example requires linking with pthreads library on MinGW, * it can be accomplished passing -static parameter to compiler * diff --git a/examples/core/core_random_sequence.c b/examples/core/core_random_sequence.c index 2f7c3be95..2cb067db4 100644 --- a/examples/core/core_random_sequence.c +++ b/examples/core/core_random_sequence.c @@ -18,159 +18,168 @@ #include // Required for: malloc() and free() -typedef struct ColorRect{ - Color c; - Rectangle r; +typedef struct ColorRect { + Color c; + Rectangle r; } ColorRect; +//------------------------------------------------------------------------------------ +// Module functions declaration +//------------------------------------------------------------------------------------ static Color GenerateRandomColor(); -static ColorRect* GenerateRandomColorRectSequence(float rectCount, float rectWidth, float screenWidth, float screenHeight); -static void ShuffleColorRectSequence(ColorRect* rectangles, int rectCount); -static void DrawTextCenterKeyHelp(const char* key, const char* text, int posX, int posY, int fontSize, Color color); +static ColorRect *GenerateRandomColorRectSequence(float rectCount, float rectWidth, float screenWidth, float screenHeight); +static void ShuffleColorRectSequence(ColorRect *rectangles, int rectCount); +static void DrawTextCenterKeyHelp(const char *key, const char *text, int posX, int posY, int fontSize, Color color); //------------------------------------------------------------------------------------ // Program main entry point //------------------------------------------------------------------------------------ -int main(void) { - // Initialization - //-------------------------------------------------------------------------------------- - const int screenWidth = 800; - const int screenHeight = 450; +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; - InitWindow(screenWidth, screenHeight, "raylib [core] example - Generates a random sequence"); + InitWindow(screenWidth, screenHeight, "raylib [core] example - Generates a random sequence"); - int rectCount = 20; - float rectSize = (float)screenWidth/rectCount; - ColorRect* rectangles = GenerateRandomColorRectSequence((float)rectCount, rectSize, (float)screenWidth, 0.75f * screenHeight); + int rectCount = 20; + float rectSize = (float)screenWidth/rectCount; + ColorRect *rectangles = GenerateRandomColorRectSequence((float)rectCount, rectSize, (float)screenWidth, 0.75f*screenHeight); - SetTargetFPS(60); - //-------------------------------------------------------------------------------------- + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update - //---------------------------------------------------------------------------------- - - if(IsKeyPressed(KEY_SPACE)) + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key { - ShuffleColorRectSequence(rectangles, rectCount); + // Update + //---------------------------------------------------------------------------------- + if (IsKeyPressed(KEY_SPACE)) ShuffleColorRectSequence(rectangles, rectCount); + + if (IsKeyPressed(KEY_UP)) + { + rectCount++; + rectSize = (float)screenWidth/rectCount; + free(rectangles); + rectangles = GenerateRandomColorRectSequence((float)rectCount, rectSize, (float)screenWidth, 0.75f*screenHeight); + } + + if (IsKeyPressed(KEY_DOWN)) + { + if (rectCount >= 4) + { + rectCount--; + rectSize = (float)screenWidth/rectCount; + free(rectangles); + rectangles = GenerateRandomColorRectSequence((float)rectCount, rectSize, (float)screenWidth, 0.75f*screenHeight); + } + } + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + int fontSize = 20; + for (int i = 0; i < rectCount; i++) + { + DrawRectangleRec(rectangles[i].r, rectangles[i].c); + DrawTextCenterKeyHelp("SPACE", "to shuffle the sequence.", 10, screenHeight - 96, fontSize, BLACK); + DrawTextCenterKeyHelp("UP", "to add a rectangle and generate a new sequence.", 10, screenHeight - 64, fontSize, BLACK); + DrawTextCenterKeyHelp("DOWN", "to remove a rectangle and generate a new sequence.", 10, screenHeight - 32, fontSize, BLACK); + } + + const char *rectCountText = TextFormat("%d rectangles", rectCount); + int rectCountTextSize = MeasureText(rectCountText, fontSize); + DrawText(rectCountText, screenWidth - rectCountTextSize - 10, 10, fontSize, BLACK); + + DrawFPS(10, 10); + + EndDrawing(); + //---------------------------------------------------------------------------------- } - if(IsKeyPressed(KEY_UP)) - { - rectCount++; - rectSize = (float)screenWidth/rectCount; - free(rectangles); - rectangles = GenerateRandomColorRectSequence((float)rectCount, rectSize, (float)screenWidth, 0.75f * screenHeight); - } + // De-Initialization + //-------------------------------------------------------------------------------------- + free(rectangles); + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- - if(IsKeyPressed(KEY_DOWN)) - { - if(rectCount >= 4){ - rectCount--; - rectSize = (float)screenWidth/rectCount; - free(rectangles); - rectangles = GenerateRandomColorRectSequence((float)rectCount, rectSize, (float)screenWidth, 0.75f * screenHeight); - } - } - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - int fontSize = 20; - for(int x=0;xc = r2->c; - r1->r.height = r2->r.height; - r1->r.y = r2->r.y; - r2->c = tmp.c; - r2->r.height = tmp.r.height; - r2->r.y = tmp.r.y; - - } - UnloadRandomSequence(seq); + for (int i = 0; i < rectCount; i++) + { + int rectHeight = (int)Remap((float)seq[i], 0, rectCount - 1, 0, screenHeight); + + rectangles[i].c = GenerateRandomColor(); + rectangles[i].r = CLITERAL(Rectangle){ startX + i*rectWidth, screenHeight - rectHeight, rectWidth, (float)rectHeight }; + } + + UnloadRandomSequence(seq); + + return rectangles; } -static void DrawTextCenterKeyHelp(const char* key, const char* text, int posX, int posY, int fontSize, Color color) +static void ShuffleColorRectSequence(ColorRect *rectangles, int rectCount) { - int spaceSize = MeasureText(" ", fontSize); - int pressSize = MeasureText("Press", fontSize); - int keySize = MeasureText(key, fontSize); - int textSize = MeasureText(text, fontSize); - int totalSize = pressSize + 2 * spaceSize + keySize + 2 * spaceSize + textSize; - int textSizeCurrent = 0; + int *seq = LoadRandomSequence(rectCount, 0, rectCount - 1); + + for (int i1 = 0; i1 < rectCount; i1++) + { + ColorRect *r1 = &rectangles[i1]; + ColorRect *r2 = &rectangles[seq[i1]]; - DrawText("Press", posX, posY, fontSize, color); - textSizeCurrent += pressSize + 2 * spaceSize; - DrawText(key, posX + textSizeCurrent, posY, fontSize, RED); - DrawRectangle(posX + textSizeCurrent, posY + fontSize, keySize, 3, RED); - textSizeCurrent += keySize + 2 * spaceSize; - DrawText(text, posX + textSizeCurrent, posY, fontSize, color); + // Swap only the color and height + ColorRect tmp = *r1; + r1->c = r2->c; + r1->r.height = r2->r.height; + r1->r.y = r2->r.y; + r2->c = tmp.c; + r2->r.height = tmp.r.height; + r2->r.y = tmp.r.y; + } + + UnloadRandomSequence(seq); +} + +static void DrawTextCenterKeyHelp(const char *key, const char *text, int posX, int posY, int fontSize, Color color) +{ + int spaceSize = MeasureText(" ", fontSize); + int pressSize = MeasureText("Press", fontSize); + int keySize = MeasureText(key, fontSize); + int textSize = MeasureText(text, fontSize); + int textSizeCurrent = 0; + + DrawText("Press", posX, posY, fontSize, color); + textSizeCurrent += pressSize + 2*spaceSize; + DrawText(key, posX + textSizeCurrent, posY, fontSize, RED); + DrawRectangle(posX + textSizeCurrent, posY + fontSize, keySize, 3, RED); + textSizeCurrent += keySize + 2*spaceSize; + DrawText(text, posX + textSizeCurrent, posY, fontSize, color); } \ No newline at end of file diff --git a/examples/core/core_random_values.c b/examples/core/core_random_values.c index 46516ea1c..cff33c69d 100644 --- a/examples/core/core_random_values.c +++ b/examples/core/core_random_values.c @@ -2,6 +2,8 @@ * * raylib [core] example - Generate random values * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.1, last time updated with raylib 1.1 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/core/core_scissor_test.c b/examples/core/core_scissor_test.c index 62ae080cb..d349feaa2 100644 --- a/examples/core/core_scissor_test.c +++ b/examples/core/core_scissor_test.c @@ -2,6 +2,8 @@ * * raylib [core] example - Scissor test * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 2.5, last time updated with raylib 3.0 * * Example contributed by Chris Dill (@MysteriousSpace) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/core/core_smooth_pixelperfect.c b/examples/core/core_smooth_pixelperfect.c index d76557651..133f41700 100644 --- a/examples/core/core_smooth_pixelperfect.c +++ b/examples/core/core_smooth_pixelperfect.c @@ -2,6 +2,8 @@ * * raylib [core] example - Smooth Pixel-perfect camera * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 3.7, last time updated with raylib 4.0 * * Example contributed by Giancamillo Alessandroni (@NotManyIdeasDev) and diff --git a/examples/core/core_storage_values.c b/examples/core/core_storage_values.c index 70386da6c..f0004bf9f 100644 --- a/examples/core/core_storage_values.c +++ b/examples/core/core_storage_values.c @@ -2,6 +2,8 @@ * * raylib [core] example - Storage save/load values * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 1.4, last time updated with raylib 4.2 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/core/core_vr_simulator.c b/examples/core/core_vr_simulator.c index 021698edb..bfea082e8 100644 --- a/examples/core/core_vr_simulator.c +++ b/examples/core/core_vr_simulator.c @@ -2,6 +2,8 @@ * * raylib [core] example - VR Simulator (Oculus Rift CV1 parameters) * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 2.5, last time updated with raylib 4.0 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/core/core_window_flags.c b/examples/core/core_window_flags.c index c9f858929..7e0ba8341 100644 --- a/examples/core/core_window_flags.c +++ b/examples/core/core_window_flags.c @@ -2,6 +2,8 @@ * * raylib [core] example - window flags * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 3.5, last time updated with raylib 3.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/core/core_window_letterbox.c b/examples/core/core_window_letterbox.c index ded782431..293022eed 100644 --- a/examples/core/core_window_letterbox.c +++ b/examples/core/core_window_letterbox.c @@ -2,6 +2,8 @@ * * raylib [core] example - window scale letterbox (and virtual mouse) * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 2.5, last time updated with raylib 4.0 * * Example contributed by Anata (@anatagawa) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/core/core_window_should_close.c b/examples/core/core_window_should_close.c index e28ef7dbd..f401bcfab 100644 --- a/examples/core/core_window_should_close.c +++ b/examples/core/core_window_should_close.c @@ -2,6 +2,8 @@ * * raylib [core] example - Window should close * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 4.2, last time updated with raylib 4.2 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/core/core_world_screen.c b/examples/core/core_world_screen.c index 82fa31281..21c17b023 100644 --- a/examples/core/core_world_screen.c +++ b/examples/core/core_world_screen.c @@ -2,6 +2,8 @@ * * raylib [core] example - World to screen * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 1.3, last time updated with raylib 1.4 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/examples.rc b/examples/examples.rc index 4767ad480..e5024b731 100644 --- a/examples/examples.rc +++ b/examples/examples.rc @@ -13,7 +13,7 @@ BEGIN VALUE "FileDescription", "raylib example" VALUE "FileVersion", "1.0" VALUE "InternalName", "raylib-example" - VALUE "LegalCopyright", "(c) 2024 raylib technologies (@raylibtech)" + VALUE "LegalCopyright", "(c) 2025 raylib technologies (@raylibtech)" //VALUE "OriginalFilename", "raylib_app.exe" VALUE "ProductName", "raylib-example" VALUE "ProductVersion", "1.0" diff --git a/examples/models/models_animation.c b/examples/models/models_animation.c index 76998d1ec..b7fec2f47 100644 --- a/examples/models/models_animation.c +++ b/examples/models/models_animation.c @@ -2,6 +2,8 @@ * * raylib [models] example - Load 3d model with animations and play them * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 2.5, last time updated with raylib 3.5 * * Example contributed by Culacant (@culacant) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/models/models_billboard.c b/examples/models/models_billboard.c index cfb49e55c..c7c6f0e84 100644 --- a/examples/models/models_billboard.c +++ b/examples/models/models_billboard.c @@ -2,6 +2,8 @@ * * raylib [models] example - Drawing billboards * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 1.3, last time updated with raylib 3.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/models/models_box_collisions.c b/examples/models/models_box_collisions.c index 4d98a776a..33f387fa3 100644 --- a/examples/models/models_box_collisions.c +++ b/examples/models/models_box_collisions.c @@ -2,6 +2,8 @@ * * raylib [models] example - Detect basic 3d collisions (box vs sphere vs box) * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.3, last time updated with raylib 3.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/models/models_cubicmap.c b/examples/models/models_cubicmap.c index 2c6267ede..1e0cff91e 100644 --- a/examples/models/models_cubicmap.c +++ b/examples/models/models_cubicmap.c @@ -2,6 +2,8 @@ * * raylib [models] example - Cubicmap loading and drawing * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 1.8, last time updated with raylib 3.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/models/models_draw_cube_texture.c b/examples/models/models_draw_cube_texture.c index 87d83c8f3..d6655ce84 100644 --- a/examples/models/models_draw_cube_texture.c +++ b/examples/models/models_draw_cube_texture.c @@ -2,6 +2,8 @@ * * raylib [models] example - Draw textured cube * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 4.5, last time updated with raylib 4.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/models/models_first_person_maze.c b/examples/models/models_first_person_maze.c index b1af7d47b..41520dfbc 100644 --- a/examples/models/models_first_person_maze.c +++ b/examples/models/models_first_person_maze.c @@ -2,6 +2,8 @@ * * raylib [models] example - first person maze * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 2.5, last time updated with raylib 3.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/models/models_geometric_shapes.c b/examples/models/models_geometric_shapes.c index 7f66a69fe..75ef62888 100644 --- a/examples/models/models_geometric_shapes.c +++ b/examples/models/models_geometric_shapes.c @@ -2,6 +2,8 @@ * * raylib [models] example - Draw some basic geometric shapes (cube, sphere, cylinder...) * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.0, last time updated with raylib 3.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/models/models_gpu_skinning.c b/examples/models/models_gpu_skinning.c index 7e81b0d82..98bf09922 100644 --- a/examples/models/models_gpu_skinning.c +++ b/examples/models/models_gpu_skinning.c @@ -82,7 +82,7 @@ int main(void) ModelAnimation anim = modelAnimations[animIndex]; animCurrentFrame = (animCurrentFrame + 1)%anim.frameCount; characterModel.transform = MatrixTranslate(position.x, position.y, position.z); - UpdateModelAnimationBoneMatrices(characterModel, anim, animCurrentFrame); + UpdateModelAnimationBones(characterModel, anim, animCurrentFrame); //---------------------------------------------------------------------------------- // Draw diff --git a/examples/models/models_gpu_skinning.png b/examples/models/models_gpu_skinning.png new file mode 100644 index 000000000..8003c16ef Binary files /dev/null and b/examples/models/models_gpu_skinning.png differ diff --git a/examples/models/models_heightmap.c b/examples/models/models_heightmap.c index d59e82814..e55228741 100644 --- a/examples/models/models_heightmap.c +++ b/examples/models/models_heightmap.c @@ -2,6 +2,8 @@ * * raylib [models] example - Heightmap loading and drawing * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.8, last time updated with raylib 3.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/models/models_loading.c b/examples/models/models_loading.c index d35db347c..01277b994 100644 --- a/examples/models/models_loading.c +++ b/examples/models/models_loading.c @@ -2,6 +2,8 @@ * * raylib [models] example - Models loading * +* Example complexity rating: [★☆☆☆] 1/4 +* * NOTE: raylib supports multiple models file formats: * * - OBJ > Text file format. Must include vertex position-texcoords-normals information, diff --git a/examples/models/models_loading_gltf.c b/examples/models/models_loading_gltf.c index 8b8838c8d..867191843 100644 --- a/examples/models/models_loading_gltf.c +++ b/examples/models/models_loading_gltf.c @@ -2,6 +2,8 @@ * * raylib [models] example - loading gltf with animations * +* Example complexity rating: [★☆☆☆] 1/4 +* * LIMITATIONS: * - Only supports 1 armature per file, and skips loading it if there are multiple armatures * - Only supports linear interpolation (default method in Blender when checked diff --git a/examples/models/models_loading_m3d.c b/examples/models/models_loading_m3d.c index 6091d95f8..f79681432 100644 --- a/examples/models/models_loading_m3d.c +++ b/examples/models/models_loading_m3d.c @@ -2,6 +2,8 @@ * * raylib [models] example - Load models M3D * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 4.5, last time updated with raylib 4.5 * * Example contributed by bzt (@bztsrc) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/models/models_loading_vox.c b/examples/models/models_loading_vox.c index 1a2721a63..4796c9aa5 100644 --- a/examples/models/models_loading_vox.c +++ b/examples/models/models_loading_vox.c @@ -2,6 +2,8 @@ * * raylib [models] example - Load models vox (MagicaVoxel) * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 4.0, last time updated with raylib 4.0 * * Example contributed by Johann Nadalutti (@procfxgen) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/models/models_mesh_generation.c b/examples/models/models_mesh_generation.c index 59aebe7c9..24816236e 100644 --- a/examples/models/models_mesh_generation.c +++ b/examples/models/models_mesh_generation.c @@ -1,6 +1,8 @@ /******************************************************************************************* * -* raylib example - procedural mesh generation +* raylib [models] example - procedural mesh generation +* +* Example complexity rating: [★★☆☆] 2/4 * * Example originally created with raylib 1.8, last time updated with raylib 4.0 * @@ -112,7 +114,7 @@ int main(void) DrawRectangleLines(30, 400, 310, 30, Fade(DARKBLUE, 0.5f)); DrawText("MOUSE LEFT BUTTON to CYCLE PROCEDURAL MODELS", 40, 410, 10, BLUE); - switch(currentModel) + switch (currentModel) { case 0: DrawText("PLANE", 680, 10, 20, DARKBLUE); break; case 1: DrawText("CUBE", 680, 10, 20, DARKBLUE); break; diff --git a/examples/models/models_mesh_picking.c b/examples/models/models_mesh_picking.c index 15723e39d..5cdfe1584 100644 --- a/examples/models/models_mesh_picking.c +++ b/examples/models/models_mesh_picking.c @@ -2,6 +2,8 @@ * * raylib [models] example - Mesh picking in 3d mode, ground plane, triangle, mesh * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 1.7, last time updated with raylib 4.0 * * Example contributed by Joel Davis (@joeld42) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/models/models_orthographic_projection.c b/examples/models/models_orthographic_projection.c index b0f74413d..9889ac7f6 100644 --- a/examples/models/models_orthographic_projection.c +++ b/examples/models/models_orthographic_projection.c @@ -2,6 +2,8 @@ * * raylib [models] example - Show the difference between perspective and orthographic projection * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 2.0, last time updated with raylib 3.7 * * Example contributed by Max Danielsson (@autious) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/models/models_point_rendering.c b/examples/models/models_point_rendering.c index 68d498453..f4f095c1d 100644 --- a/examples/models/models_point_rendering.c +++ b/examples/models/models_point_rendering.c @@ -22,7 +22,7 @@ #define MIN_POINTS 1000 // 1 thousand // Generate mesh using points -Mesh GenMeshPoints(int numPoints); +static Mesh GenMeshPoints(int numPoints); //------------------------------------------------------------------------------------ // Program main entry point @@ -56,7 +56,7 @@ int main() //-------------------------------------------------------------------------------------- // Main game loop - while(!WindowShouldClose()) + while (!WindowShouldClose()) { // Update //---------------------------------------------------------------------------------- @@ -147,7 +147,7 @@ int main() } // Generate a spherical point cloud -Mesh GenMeshPoints(int numPoints) +static Mesh GenMeshPoints(int numPoints) { Mesh mesh = { .triangleCount = 1, @@ -159,13 +159,13 @@ Mesh GenMeshPoints(int numPoints) // https://en.wikipedia.org/wiki/Spherical_coordinate_system for (int i = 0; i < numPoints; i++) { - float theta = PI*rand()/RAND_MAX; - float phi = 2.0f*PI*rand()/RAND_MAX; - float r = 10.0f*rand()/RAND_MAX; + float theta = ((float)PI*rand())/RAND_MAX; + float phi = (2.0f*PI*rand())/RAND_MAX; + float r = (10.0f*rand())/RAND_MAX; - mesh.vertices[i*3 + 0] = r*sin(theta)*cos(phi); - mesh.vertices[i*3 + 1] = r*sin(theta)*sin(phi); - mesh.vertices[i*3 + 2] = r*cos(theta); + mesh.vertices[i*3 + 0] = r*sinf(theta)*cosf(phi); + mesh.vertices[i*3 + 1] = r*sinf(theta)*sinf(phi); + mesh.vertices[i*3 + 2] = r*cosf(theta); Color color = ColorFromHSV(r*360.0f, 1.0f, 1.0f); diff --git a/examples/models/models_rlgl_solar_system.c b/examples/models/models_rlgl_solar_system.c index 7b35263ac..769a9da32 100644 --- a/examples/models/models_rlgl_solar_system.c +++ b/examples/models/models_rlgl_solar_system.c @@ -2,6 +2,8 @@ * * raylib [models] example - rlgl module usage with push/pop matrix transformations * +* Example complexity rating: [★★★★] 4/4 +* * NOTE: This example uses [rlgl] module functionality (pseudo-OpenGL 1.1 style coding) * * Example originally created with raylib 2.5, last time updated with raylib 4.0 diff --git a/examples/models/models_skybox.c b/examples/models/models_skybox.c index 4689acd77..b8b89f03b 100644 --- a/examples/models/models_skybox.c +++ b/examples/models/models_skybox.c @@ -2,6 +2,8 @@ * * raylib [models] example - Skybox loading and drawing * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 1.8, last time updated with raylib 4.0 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/models/models_tesseract_view.c b/examples/models/models_tesseract_view.c new file mode 100644 index 000000000..495e9af9c --- /dev/null +++ b/examples/models/models_tesseract_view.c @@ -0,0 +1,124 @@ +/******************************************************************************************* +* +* raylib [models] example - Tesseract view +* +* NOTE: This example only works on platforms that support drag & drop (Windows, Linux, OSX, Html5?) +* +* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev +* +* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, +* BSD-like license that allows static linking with closed source software +* +* Copyright (c) 2024-2025 raylib contributor (?) & Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#include "raymath.h" + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [models] example - tesseract view"); + + // Define the camera to look into our 3d world + Camera camera = { 0 }; + camera.position = (Vector3){ 4.0f, 4.0f, 4.0f }; // Camera position + camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point + camera.up = (Vector3){ 0.0f, 0.0f, 1.0f }; // Camera up vector (rotation towards target) + camera.fovy = 50.0f; // Camera field-of-view Y + camera.projection = CAMERA_PERSPECTIVE; // Camera mode type + + // Find the coordinates by setting XYZW to +-1 + Vector4 tesseract[16] = { + { 1, 1, 1, 1 }, { 1, 1, 1, -1 }, + { 1, 1, -1, 1 }, { 1, 1, -1, -1 }, + { 1, -1, 1, 1 }, { 1, -1, 1, -1 }, + { 1, -1, -1, 1 }, { 1, -1, -1, -1 }, + { -1, 1, 1, 1 }, { -1, 1, 1, -1 }, + { -1, 1, -1, 1 }, { -1, 1, -1, -1 }, + { -1, -1, 1, 1 }, { -1, -1, 1, -1 }, + { -1, -1, -1, 1 }, { -1, -1, -1, -1 }, + }; + + float rotation = 0.0f; + Vector3 transformed[16] = { 0 }; + float wValues[16] = { 0 }; + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + rotation = DEG2RAD*45.0f*GetTime(); + + for (int i = 0; i < 16; i++) + { + Vector4 p = tesseract[i]; + + // Rotate the XW part of the vector + Vector2 rotXW = Vector2Rotate((Vector2){ p.x, p.w }, rotation); + p.x = rotXW.x; + p.w = rotXW.y; + + // Projection from XYZW to XYZ from perspective point (0, 0, 0, 3) + // NOTE: Trace a ray from (0, 0, 0, 3) > p and continue until W = 0 + float c = 3.0f/(3.0f - p.w); + p.x = c * p.x; + p.y = c * p.y; + p.z = c * p.z; + + // Split XYZ coordinate and W values later for drawing + transformed[i] = (Vector3){ p.x, p.y, p.z }; + wValues[i] = p.w; + } + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + BeginMode3D(camera); + for (int i = 0; i < 16; i++) + { + // Draw spheres to indicate the W value + DrawSphere(transformed[i], fabsf(wValues[i]*0.1f), RED); + + for (int j = 0; j < 16; j++) + { + // Two lines are connected if they differ by 1 coordinate + // This way we dont have to keep an edge list + Vector4 v1 = tesseract[i]; + Vector4 v2 = tesseract[j]; + int diff = (int)(v1.x == v2.x) + (int)(v1.y == v2.y) + (int)(v1.z == v2.z) + (int)(v1.w == v2.w); + + // Draw only differing by 1 coordinate and the lower index only (duplicate lines) + if (diff == 3 && i < j) DrawLine3D(transformed[i], transformed[j], MAROON); + } + } + EndMode3D(); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} \ No newline at end of file diff --git a/examples/models/models_tesseract_view.png b/examples/models/models_tesseract_view.png new file mode 100644 index 000000000..664e560b2 Binary files /dev/null and b/examples/models/models_tesseract_view.png differ diff --git a/examples/models/models_waving_cubes.c b/examples/models/models_waving_cubes.c index 521a4afd5..8a07c68cf 100644 --- a/examples/models/models_waving_cubes.c +++ b/examples/models/models_waving_cubes.c @@ -2,6 +2,8 @@ * * raylib [models] example - Waving cubes * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 2.5, last time updated with raylib 3.7 * * Example contributed by Codecat (@codecat) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/models/models_yaw_pitch_roll.c b/examples/models/models_yaw_pitch_roll.c index 5374c035e..679b011cc 100644 --- a/examples/models/models_yaw_pitch_roll.c +++ b/examples/models/models_yaw_pitch_roll.c @@ -2,6 +2,8 @@ * * raylib [models] example - Plane rotations (yaw, pitch, roll) * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 1.8, last time updated with raylib 4.0 * * Example contributed by Berni (@Berni8k) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/models/resources/shaders/glsl330/skinning.vs b/examples/models/resources/shaders/glsl330/skinning.vs index 73ecca51e..43bbca76c 100644 --- a/examples/models/resources/shaders/glsl330/skinning.vs +++ b/examples/models/resources/shaders/glsl330/skinning.vs @@ -6,16 +6,19 @@ in vec3 vertexPosition; in vec2 vertexTexCoord; in vec4 vertexColor; +in vec3 vertexNormal; in vec4 vertexBoneIds; in vec4 vertexBoneWeights; // Input uniform values uniform mat4 mvp; +uniform mat4 matNormal; uniform mat4 boneMatrices[MAX_BONE_NUM]; // Output vertex attributes (to fragment shader) out vec2 fragTexCoord; out vec4 fragColor; +out vec3 fragNormal; void main() { @@ -29,9 +32,18 @@ void main() vertexBoneWeights.y*(boneMatrices[boneIndex1]*vec4(vertexPosition, 1.0)) + vertexBoneWeights.z*(boneMatrices[boneIndex2]*vec4(vertexPosition, 1.0)) + vertexBoneWeights.w*(boneMatrices[boneIndex3]*vec4(vertexPosition, 1.0)); - + + vec4 skinnedNormal = + vertexBoneWeights.x*(boneMatrices[boneIndex0]*vec4(vertexNormal, 0.0)) + + vertexBoneWeights.y*(boneMatrices[boneIndex1]*vec4(vertexNormal, 0.0)) + + vertexBoneWeights.z*(boneMatrices[boneIndex2]*vec4(vertexNormal, 0.0)) + + vertexBoneWeights.w*(boneMatrices[boneIndex3]*vec4(vertexNormal, 0.0)); + skinnedNormal.w = 0.0; + fragTexCoord = vertexTexCoord; fragColor = vertexColor; + fragNormal = normalize(vec3(matNormal*skinnedNormal)); + gl_Position = mvp*skinnedPosition; } \ No newline at end of file diff --git a/examples/others/raymath_vector_angle.c b/examples/others/raymath_vector_angle.c index d0f81548c..5a69345b4 100644 --- a/examples/others/raymath_vector_angle.c +++ b/examples/others/raymath_vector_angle.c @@ -51,7 +51,7 @@ int main(void) if (IsKeyPressed(KEY_SPACE)) angleMode = !angleMode; - if(angleMode == 0 && IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) v1 = GetMousePosition(); + if ((angleMode == 0) && IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) v1 = GetMousePosition(); if (angleMode == 0) { diff --git a/examples/shaders/resources/shaders/glsl100/deferred_shading.fs b/examples/shaders/resources/shaders/glsl100/deferred_shading.fs new file mode 100644 index 000000000..d782792b9 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl100/deferred_shading.fs @@ -0,0 +1,59 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D gPosition; +uniform sampler2D gNormal; +uniform sampler2D gAlbedoSpec; + +struct Light { + int enabled; + int type; // Unused in this demo. + vec3 position; + vec3 target; // Unused in this demo. + vec4 color; +}; + +const int NR_LIGHTS = 4; +uniform Light lights[NR_LIGHTS]; +uniform vec3 viewPosition; + +const float QUADRATIC = 0.032; +const float LINEAR = 0.09; + +void main() +{ + vec3 fragPosition = texture2D(gPosition, fragTexCoord).rgb; + vec3 normal = texture2D(gNormal, fragTexCoord).rgb; + vec3 albedo = texture2D(gAlbedoSpec, fragTexCoord).rgb; + float specular = texture2D(gAlbedoSpec, fragTexCoord).a; + + vec3 ambient = albedo*vec3(0.1); + vec3 viewDirection = normalize(viewPosition - fragPosition); + + for (int i = 0; i < NR_LIGHTS; ++i) + { + if(lights[i].enabled == 0) continue; + vec3 lightDirection = lights[i].position - fragPosition; + vec3 diffuse = max(dot(normal, lightDirection), 0.0)*albedo*lights[i].color.xyz; + + vec3 halfwayDirection = normalize(lightDirection + viewDirection); + float spec = pow(max(dot(normal, halfwayDirection), 0.0), 32.0); + vec3 specular = specular*spec*lights[i].color.xyz; + + // Attenuation + float distance = length(lights[i].position - fragPosition); + float attenuation = 1.0/(1.0 + LINEAR * distance + QUADRATIC*distance*distance); + diffuse *= attenuation; + specular *= attenuation; + ambient += diffuse + specular; + } + + gl_FragColor = vec4(ambient, 1.0); +} + diff --git a/examples/shaders/resources/shaders/glsl100/deferred_shading.vs b/examples/shaders/resources/shaders/glsl100/deferred_shading.vs new file mode 100644 index 000000000..bb108ce09 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl100/deferred_shading.vs @@ -0,0 +1,16 @@ +#version 100 + +// Input vertex attributes +attribute vec3 vertexPosition; +attribute vec2 vertexTexCoord; + +// Output vertex attributes (to fragment shader) +varying vec2 fragTexCoord; + +void main() +{ + fragTexCoord = vertexTexCoord; + + // Calculate final vertex position + gl_Position = vec4(vertexPosition, 1.0); +} diff --git a/examples/shaders/resources/shaders/glsl100/depth.fs b/examples/shaders/resources/shaders/glsl100/depth.fs index 780992784..001cca087 100644 --- a/examples/shaders/resources/shaders/glsl100/depth.fs +++ b/examples/shaders/resources/shaders/glsl100/depth.fs @@ -22,5 +22,5 @@ void main() float depth = (2.0*zNear)/(zFar + zNear - z*(zFar - zNear)); // Calculate final fragment color - gl_FragColor = vec4(depth, depth, depth, 1.0f); + gl_FragColor = vec4(depth, depth, depth, 1.0); } \ No newline at end of file diff --git a/examples/shaders/resources/shaders/glsl100/gbuffer.fs b/examples/shaders/resources/shaders/glsl100/gbuffer.fs new file mode 100644 index 000000000..2945c5ddd --- /dev/null +++ b/examples/shaders/resources/shaders/glsl100/gbuffer.fs @@ -0,0 +1,36 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec3 fragPosition; +varying vec2 fragTexCoord; +varying vec3 fragNormal; +varying vec4 fragColor; + +// TODO: Is there some alternative for GLSL100 +//layout (location = 0) out vec3 gPosition; +//layout (location = 1) out vec3 gNormal; +//layout (location = 2) out vec4 gAlbedoSpec; +//uniform vec3 gPosition; +//uniform vec3 gNormal; +//uniform vec4 gAlbedoSpec; + +// Input uniform values +uniform sampler2D texture0; // Diffuse texture +uniform sampler2D specularTexture; + +void main() +{ + // Store the fragment position vector in the first gbuffer texture + //gPosition = fragPosition; + + // Store the per-fragment normals into the gbuffer + //gNormal = normalize(fragNormal); + + // Store the diffuse per-fragment color + gl_FragColor.rgb = texture2D(texture0, fragTexCoord).rgb; + + // Store specular intensity in gAlbedoSpec's alpha component + gl_FragColor.a = texture2D(specularTexture, fragTexCoord).r; +} diff --git a/examples/shaders/resources/shaders/glsl100/gbuffer.vs b/examples/shaders/resources/shaders/glsl100/gbuffer.vs new file mode 100644 index 000000000..2791ce5ee --- /dev/null +++ b/examples/shaders/resources/shaders/glsl100/gbuffer.vs @@ -0,0 +1,60 @@ +#version 100 + +// Input vertex attributes +attribute vec3 vertexPosition; +attribute vec2 vertexTexCoord; +attribute vec3 vertexNormal; +attribute vec4 vertexColor; + +// Input uniform values +uniform mat4 matModel; +uniform mat4 matView; +uniform mat4 matProjection; + +// Output vertex attributes (to fragment shader) +varying vec3 fragPosition; +varying vec2 fragTexCoord; +varying vec3 fragNormal; +varying vec4 fragColor; + + +// https://github.com/glslify/glsl-inverse +mat3 inverse(mat3 m) +{ + float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2]; + float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2]; + float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2]; + + float b01 = a22*a11 - a12*a21; + float b11 = -a22*a10 + a12*a20; + float b21 = a21*a10 - a11*a20; + + float det = a00*b01 + a01*b11 + a02*b21; + + return mat3(b01, (-a22*a01 + a02*a21), (a12*a01 - a02*a11), + b11, (a22*a00 - a02*a20), (-a12*a00 + a02*a10), + b21, (-a21*a00 + a01*a20), (a11*a00 - a01*a10))/det; +} + +// https://github.com/glslify/glsl-transpose +mat3 transpose(mat3 m) +{ + return mat3(m[0][0], m[1][0], m[2][0], + m[0][1], m[1][1], m[2][1], + m[0][2], m[1][2], m[2][2]); +} + +void main() +{ + // Calculate vertex attributes for fragment shader + vec4 worldPos = matModel*vec4(vertexPosition, 1.0); + fragPosition = worldPos.xyz; + fragTexCoord = vertexTexCoord; + fragColor = vertexColor; + + mat3 normalMatrix = transpose(inverse(mat3(matModel))); + fragNormal = normalMatrix*vertexNormal; + + // Calculate final vertex position + gl_Position = matProjection*matView*worldPos; +} diff --git a/examples/shaders/resources/shaders/glsl100/julia_set.fs b/examples/shaders/resources/shaders/glsl100/julia_set.fs index 82d0a75ab..9ee8c6f4d 100644 --- a/examples/shaders/resources/shaders/glsl100/julia_set.fs +++ b/examples/shaders/resources/shaders/glsl100/julia_set.fs @@ -13,23 +13,20 @@ uniform float zoom; // Zoom of the scale. // NOTE: Maximum number of shader for-loop iterations depend on GPU, // for example, on RasperryPi for this examply only supports up to 60 const int maxIterations = 48; // Max iterations to do. -const float colorCycles = 1.0f; // Number of times the color palette repeats. +const float colorCycles = 1.0; // Number of times the color palette repeats. // Square a complex number vec2 ComplexSquare(vec2 z) { - return vec2( - z.x*z.x - z.y*z.y, - z.x*z.y*2.0f - ); + return vec2(z.x*z.x - z.y*z.y, z.x*z.y*2.0); } // Convert Hue Saturation Value (HSV) color into RGB vec3 Hsv2rgb(vec3 c) { - vec4 K = vec4(1.0f, 2.0f/3.0f, 1.0f/3.0f, 3.0f); - vec3 p = abs(fract(c.xxx + K.xyz)*6.0f - K.www); - return c.z*mix(K.xxx, clamp(p - K.xxx, 0.0f, 1.0f), c.y); + vec4 K = vec4(1.0, 2.0/3.0, 1.0/3.0, 3.0); + vec3 p = abs(fract(c.xxx + K.xyz)*6.0 - K.www); + return c.z*mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); } void main() @@ -55,7 +52,7 @@ void main() // The pixel coordinates are scaled so they are on the mandelbrot scale // NOTE: fragTexCoord already comes as normalized screen coordinates but offset must be normalized before scaling and zoom - vec2 z = vec2((fragTexCoord.x - 0.5f)*2.5f, (fragTexCoord.y - 0.5f)*1.5f)/zoom; + vec2 z = vec2((fragTexCoord.x - 0.5)*2.5, (fragTexCoord.y - 0.5)*1.5)/zoom; z.x += offset.x; z.y += offset.y; @@ -63,7 +60,7 @@ void main() for (int iterations = 0; iterations < 60; iterations++) { z = ComplexSquare(z) + c; // Iterate function - if (dot(z, z) > 4.0f) break; + if (dot(z, z) > 4.0) break; iter = iterations; } @@ -74,12 +71,12 @@ void main() z = ComplexSquare(z) + c; // This last part smooths the color (again see link above). - float smoothVal = float(iter) + 1.0f - (log(log(length(z)))/log(2.0f)); + float smoothVal = float(iter) + 1.0 - (log(log(length(z)))/log(2.0)); // Normalize the value so it is between 0 and 1. float norm = smoothVal/float(maxIterations); // If in set, color black. 0.999 allows for some float accuracy error. - if (norm > 0.999f) gl_FragColor = vec4(0.0f, 0.0f, 0.0f, 1.0f); - else gl_FragColor = vec4(Hsv2rgb(vec3(norm*colorCycles, 1.0f, 1.0f)), 1.0f); + if (norm > 0.999) gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); + else gl_FragColor = vec4(Hsv2rgb(vec3(norm*colorCycles, 1.0, 1.0)), 1.0); } diff --git a/examples/shaders/resources/shaders/glsl100/lighting.fs b/examples/shaders/resources/shaders/glsl100/lighting.fs index 73531a8bb..f9b0bd3c1 100644 --- a/examples/shaders/resources/shaders/glsl100/lighting.fs +++ b/examples/shaders/resources/shaders/glsl100/lighting.fs @@ -40,6 +40,8 @@ void main() vec3 viewD = normalize(viewPos - fragPosition); vec3 specular = vec3(0.0); + vec4 tint = colDiffuse * fragColor; + // NOTE: Implement here your fragment shader code for (int i = 0; i < MAX_LIGHTS; i++) @@ -67,7 +69,7 @@ void main() } } - vec4 finalColor = (texelColor*((colDiffuse + vec4(specular, 1.0))*vec4(lightDot, 1.0))); + vec4 finalColor = (texelColor*((tint + vec4(specular, 1.0))*vec4(lightDot, 1.0))); finalColor += texelColor*(ambient/10.0); // Gamma correction diff --git a/examples/shaders/resources/shaders/glsl100/pbr.fs b/examples/shaders/resources/shaders/glsl100/pbr.fs index 1ada83317..48688ebe9 100644 --- a/examples/shaders/resources/shaders/glsl100/pbr.fs +++ b/examples/shaders/resources/shaders/glsl100/pbr.fs @@ -1,6 +1,6 @@ #version 100 -precision mediump float; +precision highp float; #define MAX_LIGHTS 4 #define LIGHT_DIRECTIONAL 0 @@ -17,13 +17,12 @@ struct Light { }; // Input vertex attributes (from vertex shader) -varying in vec3 fragPosition; -varying in vec2 fragTexCoord; -varying in vec4 fragColor; -varying in vec3 fragNormal; -varying in vec4 shadowPos; -varying in mat3 TBN; - +varying vec3 fragPosition; +varying vec2 fragTexCoord; +varying vec4 fragColor; +varying vec3 fragNormal; +varying vec4 shadowPos; +varying mat3 TBN; // Input uniform values uniform int numOfLights; @@ -55,102 +54,108 @@ uniform vec3 viewPos; uniform vec3 ambientColor; uniform float ambient; -// refl in range 0 to 1 -// returns base reflectivity to 1 -// incrase reflectivity when surface view at larger angle -vec3 schlickFresnel(float hDotV,vec3 refl) +// Reflectivity in range 0.0 to 1.0 +// NOTE: Reflectivity is increased when surface view at larger angle +vec3 SchlickFresnel(float hDotV,vec3 refl) { - return refl + (1.0 - refl) * pow(1.0 - hDotV,5.0); + return refl + (1.0 - refl)*pow(1.0 - hDotV, 5.0); } -float ggxDistribution(float nDotH,float roughness) +float GgxDistribution(float nDotH,float roughness) { - float a = roughness * roughness * roughness * roughness; - float d = nDotH * nDotH * (a - 1.0) + 1.0; - d = PI * d * d; - return a / max(d,0.0000001); + float a = roughness*roughness*roughness*roughness; + float d = nDotH*nDotH*(a - 1.0) + 1.0; + d = PI*d*d; + return (a/max(d,0.0000001)); } -float geomSmith(float nDotV,float nDotL,float roughness) +float GeomSmith(float nDotV,float nDotL,float roughness) { - float r = roughness + 1.0; - float k = r * r / 8.0; - float ik = 1.0 - k; - float ggx1 = nDotV / (nDotV * ik + k); - float ggx2 = nDotL / (nDotL * ik + k); - return ggx1 * ggx2; + float r = roughness + 1.0; + float k = r*r/8.0; + float ik = 1.0 - k; + float ggx1 = nDotV/(nDotV*ik + k); + float ggx2 = nDotL/(nDotL*ik + k); + return ggx1*ggx2; } -vec3 pbr(){ - vec3 albedo = texture2D(albedoMap,vec2(fragTexCoord.x*tiling.x+offset.x,fragTexCoord.y*tiling.y+offset.y)).rgb; - albedo = vec3(albedoColor.x*albedo.x,albedoColor.y*albedo.y,albedoColor.z*albedo.z); - float metallic = clamp(metallicValue,0.0,1.0); - float roughness = clamp(roughnessValue,0.0,1.0); - float ao = clamp(aoValue,0.0,1.0); - if(useTexMRA == 1) { - vec4 mra = texture2D(mraMap, vec2(fragTexCoord.x * tiling.x + offset.x, fragTexCoord.y * tiling.y + offset.y)); - metallic = clamp(mra.r+metallicValue,0.04,1.0); - roughness = clamp(mra.g+roughnessValue,0.04,1.0); - ao = (mra.b+aoValue)*0.5; - } +vec3 ComputePBR() +{ + vec3 albedo = texture2D(albedoMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb; + albedo = vec3(albedoColor.x*albedo.x, albedoColor.y*albedo.y, albedoColor.z*albedo.z); + + float metallic = clamp(metallicValue, 0.0, 1.0); + float roughness = clamp(roughnessValue, 0.0, 1.0); + float ao = clamp(aoValue, 0.0, 1.0); + + if (useTexMRA == 1) + { + vec4 mra = texture2D(mraMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)); + metallic = clamp(mra.r + metallicValue, 0.04, 1.0); + roughness = clamp(mra.g + roughnessValue, 0.04, 1.0); + ao = (mra.b + aoValue)*0.5; + } + vec3 N = normalize(fragNormal); + if (useTexNormal == 1) + { + N = texture2D(normalMap, vec2(fragTexCoord.x*tiling.x + offset.y, fragTexCoord.y*tiling.y + offset.y)).rgb; + N = normalize(N*2.0 - 1.0); + N = normalize(N*TBN); + } + vec3 V = normalize(viewPos - fragPosition); - vec3 N = normalize(fragNormal); - if(useTexNormal == 1) { - N = texture2D(normalMap, vec2(fragTexCoord.x * tiling.x + offset.y, fragTexCoord.y * tiling.y + offset.y)).rgb; - N = normalize(N * 2.0 - 1.0); - N = normalize(N * TBN); - } + vec3 emissive = vec3(0); + emissive = (texture2D(emissiveMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb).g*emissiveColor.rgb*emissivePower*float(useTexEmissive); + + // return N;//vec3(metallic,metallic,metallic); + // If dia-electric use base reflectivity of 0.04 otherwise ut is a metal use albedo as base reflectivity + vec3 baseRefl = mix(vec3(0.04), albedo.rgb, metallic); + vec3 lightAccum = vec3(0.0); // Acumulate lighting lum + + for (int i = 0; i < 4; i++) + { + vec3 L = normalize(lights[i].position - fragPosition); // Compute light vector + vec3 H = normalize(V + L); // Compute halfway bisecting vector + float dist = length(lights[i].position - fragPosition); // Compute distance to light + float attenuation = 1.0/(dist*dist*0.23); // Compute attenuation + vec3 radiance = lights[i].color.rgb*lights[i].intensity*attenuation; // Compute input radiance, light energy comming in + + // Cook-Torrance BRDF distribution function + float nDotV = max(dot(N,V), 0.0000001); + float nDotL = max(dot(N,L), 0.0000001); + float hDotV = max(dot(H,V), 0.0); + float nDotH = max(dot(N,H), 0.0); + float D = GgxDistribution(nDotH, roughness); // Larger the more micro-facets aligned to H + float G = GeomSmith(nDotV, nDotL, roughness); // Smaller the more micro-facets shadow + vec3 F = SchlickFresnel(hDotV, baseRefl); // Fresnel proportion of specular reflectance + + vec3 spec = (D*G*F)/(4.0*nDotV*nDotL); - vec3 V = normalize(viewPos - fragPosition); + // Difuse and spec light can't be above 1.0 + // kD = 1.0 - kS diffuse component is equal 1.0 - spec comonent + vec3 kD = vec3(1.0) - F; - vec3 e = vec3(0); - e = (texture2D(emissiveMap, vec2(fragTexCoord.x*tiling.x+offset.x, fragTexCoord.y*tiling.y+offset.y)).rgb).g * emissiveColor.rgb*emissivePower * float(useTexEmissive); - - //return N;//vec3(metallic,metallic,metallic); - //if dia-electric use base reflectivity of 0.04 otherwise ut is a metal use albedo as base reflectivity - vec3 baseRefl = mix(vec3(0.04),albedo.rgb,metallic); - vec3 Lo = vec3(0.0); // acumulate lighting lum - - for(int i=0;i sampleDepth) - { - shadowCounter++; - } + float sampleDepth = texture2D(shadowMap, sampleCoords + texelSize*vec2(x, y)).r; + if (curDepth - bias > sampleDepth) shadowCounter++; } } - finalColor = mix(finalColor, vec4(0, 0, 0, 1), float(shadowCounter) / float(numSamples)); + + finalColor = mix(finalColor, vec4(0, 0, 0, 1), float(shadowCounter)/float(numSamples)); // Add ambient lighting whether in shadow or not finalColor += texelColor*(ambient/10.0)*colDiffuse; diff --git a/examples/shaders/resources/shaders/glsl330/depth.fs b/examples/shaders/resources/shaders/glsl330/depth.fs index f7546bbb8..5c4a3de99 100644 --- a/examples/shaders/resources/shaders/glsl330/depth.fs +++ b/examples/shaders/resources/shaders/glsl330/depth.fs @@ -23,5 +23,5 @@ void main() float depth = (2.0*zNear)/(zFar + zNear - z*(zFar - zNear)); // Calculate final fragment color - finalColor = vec4(depth, depth, depth, 1.0f); + finalColor = vec4(depth, depth, depth, 1.0); } \ No newline at end of file diff --git a/examples/shaders/resources/shaders/glsl330/hybrid_raster.fs b/examples/shaders/resources/shaders/glsl330/hybrid_raster.fs index 85ef492c0..26c7e8f26 100644 --- a/examples/shaders/resources/shaders/glsl330/hybrid_raster.fs +++ b/examples/shaders/resources/shaders/glsl330/hybrid_raster.fs @@ -1,14 +1,22 @@ -#version 330 +#version 330 +// Input vertex attributes (from vertex shader) in vec2 fragTexCoord; in vec4 fragColor; +// Input uniform values uniform sampler2D texture0; uniform vec4 colDiffuse; +// Output fragment color +//out vec4 finalColor; + +// NOTE: Add here your custom variables + void main() { - vec4 texelColor = texture2D(texture0, fragTexCoord); + vec4 texelColor = texture(texture0, fragTexCoord); + gl_FragColor = texelColor*colDiffuse*fragColor; gl_FragDepth = gl_FragCoord.z; } \ No newline at end of file diff --git a/examples/shaders/resources/shaders/glsl330/julia_set.fs b/examples/shaders/resources/shaders/glsl330/julia_set.fs index 7a6f069c8..3a8e25deb 100644 --- a/examples/shaders/resources/shaders/glsl330/julia_set.fs +++ b/examples/shaders/resources/shaders/glsl330/julia_set.fs @@ -12,23 +12,20 @@ uniform vec2 offset; // Offset of the scale. uniform float zoom; // Zoom of the scale. const int maxIterations = 255; // Max iterations to do. -const float colorCycles = 2.0f; // Number of times the color palette repeats. Can show higher detail for higher iteration numbers. +const float colorCycles = 2.0; // Number of times the color palette repeats. Can show higher detail for higher iteration numbers. // Square a complex number vec2 ComplexSquare(vec2 z) { - return vec2( - z.x*z.x - z.y*z.y, - z.x*z.y*2.0f - ); + return vec2(z.x*z.x - z.y*z.y, z.x*z.y*2.0); } // Convert Hue Saturation Value (HSV) color into RGB vec3 Hsv2rgb(vec3 c) { - vec4 K = vec4(1.0f, 2.0f/3.0f, 1.0f/3.0f, 3.0f); - vec3 p = abs(fract(c.xxx + K.xyz)*6.0f - K.www); - return c.z*mix(K.xxx, clamp(p - K.xxx, 0.0f, 1.0f), c.y); + vec4 K = vec4(1.0, 2.0/3.0, 1.0/3.0, 3.0); + vec3 p = abs(fract(c.xxx + K.xyz)*6.0 - K.www); + return c.z*mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); } void main() @@ -54,7 +51,7 @@ void main() // The pixel coordinates are scaled so they are on the mandelbrot scale // NOTE: fragTexCoord already comes as normalized screen coordinates but offset must be normalized before scaling and zoom - vec2 z = vec2((fragTexCoord.x - 0.5f)*2.5f, (fragTexCoord.y - 0.5f)*1.5f)/zoom; + vec2 z = vec2((fragTexCoord.x - 0.5f)*2.5, (fragTexCoord.y - 0.5)*1.5)/zoom; z.x += offset.x; z.y += offset.y; @@ -63,7 +60,7 @@ void main() { z = ComplexSquare(z) + c; // Iterate function - if (dot(z, z) > 4.0f) break; + if (dot(z, z) > 4.0) break; } // Another few iterations decreases errors in the smoothing calculation. @@ -72,12 +69,12 @@ void main() z = ComplexSquare(z) + c; // This last part smooths the color (again see link above). - float smoothVal = float(iterations) + 1.0f - (log(log(length(z)))/log(2.0f)); + float smoothVal = float(iterations) + 1.0 - (log(log(length(z)))/log(2.0)); // Normalize the value so it is between 0 and 1. float norm = smoothVal/float(maxIterations); // If in set, color black. 0.999 allows for some float accuracy error. - if (norm > 0.999f) finalColor = vec4(0.0f, 0.0f, 0.0f, 1.0f); - else finalColor = vec4(Hsv2rgb(vec3(norm*colorCycles, 1.0f, 1.0f)), 1.0f); + if (norm > 0.999) finalColor = vec4(0.0, 0.0, 0.0, 1.0); + else finalColor = vec4(Hsv2rgb(vec3(norm*colorCycles, 1.0, 1.0)), 1.0); } diff --git a/examples/shaders/resources/shaders/glsl330/lighting.fs b/examples/shaders/resources/shaders/glsl330/lighting.fs index d1f3140a1..d2a8e8743 100644 --- a/examples/shaders/resources/shaders/glsl330/lighting.fs +++ b/examples/shaders/resources/shaders/glsl330/lighting.fs @@ -3,7 +3,7 @@ // Input vertex attributes (from vertex shader) in vec3 fragPosition; in vec2 fragTexCoord; -//in vec4 fragColor; +in vec4 fragColor; in vec3 fragNormal; // Input uniform values @@ -41,6 +41,8 @@ void main() vec3 viewD = normalize(viewPos - fragPosition); vec3 specular = vec3(0.0); + vec4 tint = colDiffuse * fragColor; + // NOTE: Implement here your fragment shader code for (int i = 0; i < MAX_LIGHTS; i++) @@ -68,8 +70,8 @@ void main() } } - finalColor = (texelColor*((colDiffuse + vec4(specular, 1.0))*vec4(lightDot, 1.0))); - finalColor += texelColor*(ambient/10.0)*colDiffuse; + finalColor = (texelColor*((tint + vec4(specular, 1.0))*vec4(lightDot, 1.0))); + finalColor += texelColor*(ambient/10.0)*tint; // Gamma correction finalColor = pow(finalColor, vec4(1.0/2.2)); diff --git a/examples/shaders/resources/shaders/glsl330/lighting_instancing.vs b/examples/shaders/resources/shaders/glsl330/lighting_instancing.vs index 3e4da1e28..32db8cdd4 100644 --- a/examples/shaders/resources/shaders/glsl330/lighting_instancing.vs +++ b/examples/shaders/resources/shaders/glsl330/lighting_instancing.vs @@ -25,7 +25,7 @@ void main() // Send vertex attributes to fragment shader fragPosition = vec3(instanceTransform*vec4(vertexPosition, 1.0)); fragTexCoord = vertexTexCoord; - //fragColor = vertexColor; + fragColor = vec4(1.0); fragNormal = normalize(vec3(matNormal*vec4(vertexNormal, 1.0))); // Calculate final vertex position, note that we multiply mvp by instanceTransform diff --git a/examples/shaders/resources/shaders/glsl330/pbr.fs b/examples/shaders/resources/shaders/glsl330/pbr.fs index d7544d310..d439841df 100644 --- a/examples/shaders/resources/shaders/glsl330/pbr.fs +++ b/examples/shaders/resources/shaders/glsl330/pbr.fs @@ -64,16 +64,16 @@ vec3 SchlickFresnel(float hDotV,vec3 refl) float GgxDistribution(float nDotH,float roughness) { - float a = roughness * roughness * roughness * roughness; - float d = nDotH * nDotH * (a - 1.0) + 1.0; - d = PI * d * d; - return a / max(d,0.0000001); + float a = roughness*roughness*roughness*roughness; + float d = nDotH*nDotH*(a - 1.0) + 1.0; + d = PI*d*d; + return (a/max(d,0.0000001)); } float GeomSmith(float nDotV,float nDotL,float roughness) { float r = roughness + 1.0; - float k = r*r / 8.0; + float k = r*r/8.0; float ik = 1.0 - k; float ggx1 = nDotV/(nDotV*ik + k); float ggx2 = nDotL/(nDotL*ik + k); @@ -91,7 +91,7 @@ vec3 ComputePBR() if (useTexMRA == 1) { - vec4 mra = texture(mraMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y))*useTexMRA; + vec4 mra = texture(mraMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)); metallic = clamp(mra.r + metallicValue, 0.04, 1.0); roughness = clamp(mra.g + roughnessValue, 0.04, 1.0); ao = (mra.b + aoValue)*0.5; @@ -108,10 +108,10 @@ vec3 ComputePBR() vec3 V = normalize(viewPos - fragPosition); vec3 emissive = vec3(0); - emissive = (texture(emissiveMap, vec2(fragTexCoord.x*tiling.x+offset.x, fragTexCoord.y*tiling.y+offset.y)).rgb).g * emissiveColor.rgb*emissivePower * useTexEmissive; + emissive = (texture(emissiveMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb).g*emissiveColor.rgb*emissivePower*useTexEmissive; // return N;//vec3(metallic,metallic,metallic); - // if dia-electric use base reflectivity of 0.04 otherwise ut is a metal use albedo as base reflectivity + // If dia-electric use base reflectivity of 0.04 otherwise ut is a metal use albedo as base reflectivity vec3 baseRefl = mix(vec3(0.04), albedo.rgb, metallic); vec3 lightAccum = vec3(0.0); // Acumulate lighting lum @@ -145,7 +145,7 @@ vec3 ComputePBR() vec3 ambientFinal = (ambientColor + albedo)*ambient*0.5; - return ambientFinal + lightAccum*ao + emissive; + return (ambientFinal + lightAccum*ao + emissive); } void main() diff --git a/examples/shaders/resources/shaders/glsl330/pbr.vs b/examples/shaders/resources/shaders/glsl330/pbr.vs index 94b0062cf..6f262313c 100644 --- a/examples/shaders/resources/shaders/glsl330/pbr.vs +++ b/examples/shaders/resources/shaders/glsl330/pbr.vs @@ -27,12 +27,12 @@ void main() { // Compute binormal from vertex normal and tangent vec3 vertexBinormal = cross(vertexNormal, vertexTangent); - + // Compute fragment normal based on normal transformations mat3 normalMatrix = transpose(inverse(mat3(matModel))); - + // Compute fragment position based on model transformations - fragPosition = vec3(matModel*vec4(vertexPosition, 1.0f)); + fragPosition = vec3(matModel*vec4(vertexPosition, 1.0)); fragTexCoord = vertexTexCoord*2.0; fragNormal = normalize(normalMatrix*vertexNormal); diff --git a/examples/shaders/resources/shaders/glsl330/shadowmap.fs b/examples/shaders/resources/shaders/glsl330/shadowmap.fs index 506b51a8b..d535de2bc 100644 --- a/examples/shaders/resources/shaders/glsl330/shadowmap.fs +++ b/examples/shaders/resources/shaders/glsl330/shadowmap.fs @@ -51,32 +51,31 @@ void main() // Shadow calculations vec4 fragPosLightSpace = lightVP * vec4(fragPosition, 1); fragPosLightSpace.xyz /= fragPosLightSpace.w; // Perform the perspective division - fragPosLightSpace.xyz = (fragPosLightSpace.xyz + 1.0f) / 2.0f; // Transform from [-1, 1] range to [0, 1] range + fragPosLightSpace.xyz = (fragPosLightSpace.xyz + 1.0)/2.0; // Transform from [-1, 1] range to [0, 1] range vec2 sampleCoords = fragPosLightSpace.xy; float curDepth = fragPosLightSpace.z; + // Slope-scale depth bias: depth biasing reduces "shadow acne" artifacts, where dark stripes appear all over the scene. // The solution is adding a small bias to the depth // In this case, the bias is proportional to the slope of the surface, relative to the light - float bias = max(0.0002 * (1.0 - dot(normal, l)), 0.00002) + 0.00001; + float bias = max(0.0002*(1.0 - dot(normal, l)), 0.00002) + 0.00001; int shadowCounter = 0; const int numSamples = 9; + // PCF (percentage-closer filtering) algorithm: // Instead of testing if just one point is closer to the current point, // we test the surrounding points as well. // This blurs shadow edges, hiding aliasing artifacts. - vec2 texelSize = vec2(1.0f / float(shadowMapResolution)); + vec2 texelSize = vec2(1.0/float(shadowMapResolution)); for (int x = -1; x <= 1; x++) { for (int y = -1; y <= 1; y++) { - float sampleDepth = texture(shadowMap, sampleCoords + texelSize * vec2(x, y)).r; - if (curDepth - bias > sampleDepth) - { - shadowCounter++; - } + float sampleDepth = texture(shadowMap, sampleCoords + texelSize*vec2(x, y)).r; + if (curDepth - bias > sampleDepth) shadowCounter++; } } - finalColor = mix(finalColor, vec4(0, 0, 0, 1), float(shadowCounter) / float(numSamples)); + finalColor = mix(finalColor, vec4(0, 0, 0, 1), float(shadowCounter)/float(numSamples)); // Add ambient lighting whether in shadow or not finalColor += texelColor*(ambient/10.0)*colDiffuse; diff --git a/examples/shaders/resources/shaders/glsl330/sobel.fs b/examples/shaders/resources/shaders/glsl330/sobel.fs index f76e9cab9..80883710d 100644 --- a/examples/shaders/resources/shaders/glsl330/sobel.fs +++ b/examples/shaders/resources/shaders/glsl330/sobel.fs @@ -20,22 +20,22 @@ void main() float y = 1.0/resolution.y; vec4 horizEdge = vec4(0.0); - horizEdge -= texture2D(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y - y))*1.0; - horizEdge -= texture2D(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y ))*2.0; - horizEdge -= texture2D(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y + y))*1.0; - horizEdge += texture2D(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y - y))*1.0; - horizEdge += texture2D(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y ))*2.0; - horizEdge += texture2D(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y + y))*1.0; + horizEdge -= texture(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y - y))*1.0; + horizEdge -= texture(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y ))*2.0; + horizEdge -= texture(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y + y))*1.0; + horizEdge += texture(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y - y))*1.0; + horizEdge += texture(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y ))*2.0; + horizEdge += texture(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y + y))*1.0; vec4 vertEdge = vec4(0.0); - vertEdge -= texture2D(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y - y))*1.0; - vertEdge -= texture2D(texture0, vec2(fragTexCoord.x , fragTexCoord.y - y))*2.0; - vertEdge -= texture2D(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y - y))*1.0; - vertEdge += texture2D(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y + y))*1.0; - vertEdge += texture2D(texture0, vec2(fragTexCoord.x , fragTexCoord.y + y))*2.0; - vertEdge += texture2D(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y + y))*1.0; + vertEdge -= texture(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y - y))*1.0; + vertEdge -= texture(texture0, vec2(fragTexCoord.x , fragTexCoord.y - y))*2.0; + vertEdge -= texture(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y - y))*1.0; + vertEdge += texture(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y + y))*1.0; + vertEdge += texture(texture0, vec2(fragTexCoord.x , fragTexCoord.y + y))*2.0; + vertEdge += texture(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y + y))*1.0; vec3 edge = sqrt((horizEdge.rgb*horizEdge.rgb) + (vertEdge.rgb*vertEdge.rgb)); - finalColor = vec4(edge, texture2D(texture0, fragTexCoord).a); + finalColor = vec4(edge, texture(texture0, fragTexCoord).a); } \ No newline at end of file diff --git a/examples/shaders/resources/shaders/glsl330/swirl.fs b/examples/shaders/resources/shaders/glsl330/swirl.fs index bb0732c55..6a71e3696 100644 --- a/examples/shaders/resources/shaders/glsl330/swirl.fs +++ b/examples/shaders/resources/shaders/glsl330/swirl.fs @@ -41,7 +41,7 @@ void main() } tc += center; - vec4 color = texture2D(texture0, tc/texSize)*colDiffuse*fragColor;; + vec4 color = texture(texture0, tc/texSize)*colDiffuse*fragColor;; finalColor = vec4(color.rgb, 1.0);; } \ No newline at end of file diff --git a/examples/shaders/resources/shaders/glsl330/tiling.fs b/examples/shaders/resources/shaders/glsl330/tiling.fs index 6e7f52434..86f054a8a 100644 --- a/examples/shaders/resources/shaders/glsl330/tiling.fs +++ b/examples/shaders/resources/shaders/glsl330/tiling.fs @@ -1,14 +1,20 @@ #version 330 core -uniform sampler2D diffuseMap; +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + uniform vec2 tiling; -in vec2 fragTexCoord; - -out vec4 fragColor; +out vec4 finalColor; void main() { - vec2 texCoord = fragTexCoord * tiling; - fragColor = texture(diffuseMap, texCoord); + vec2 texCoord = fragTexCoord*tiling; + + finalColor = texture(texture0, texCoord)*colDiffuse; } diff --git a/examples/shaders/shaders_basic_lighting.c b/examples/shaders/shaders_basic_lighting.c index 77fedfeb9..9eff43379 100644 --- a/examples/shaders/shaders_basic_lighting.c +++ b/examples/shaders/shaders_basic_lighting.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - basic lighting * +* Example complexity rating: [★★★★] 4/4 +* * NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, * OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. * diff --git a/examples/shaders/shaders_basic_pbr.c b/examples/shaders/shaders_basic_pbr.c index c3f2bad88..d02980afd 100644 --- a/examples/shaders/shaders_basic_pbr.c +++ b/examples/shaders/shaders_basic_pbr.c @@ -22,7 +22,7 @@ #if defined(PLATFORM_DESKTOP) #define GLSL_VERSION 330 #else // PLATFORM_ANDROID, PLATFORM_WEB - #define GLSL_VERSION 120 + #define GLSL_VERSION 100 #endif #include // Required for: NULL diff --git a/examples/shaders/shaders_custom_uniform.c b/examples/shaders/shaders_custom_uniform.c index 9d991bd1a..1c8419c91 100644 --- a/examples/shaders/shaders_custom_uniform.c +++ b/examples/shaders/shaders_custom_uniform.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Postprocessing with custom uniform variable * +* Example complexity rating: [★★☆☆] 2/4 +* * NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, * OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. * diff --git a/examples/shaders/shaders_deferred_render.c b/examples/shaders/shaders_deferred_render.c index 4f652fe33..13600bc09 100644 --- a/examples/shaders/shaders_deferred_render.c +++ b/examples/shaders/shaders_deferred_render.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - deferred rendering * +* Example complexity rating: [★★★★] 4/4 +* * NOTE: This example requires raylib OpenGL 3.3 or OpenGL ES 3.0 * * Example originally created with raylib 4.5, last time updated with raylib 4.5 @@ -76,11 +78,11 @@ int main(void) Model cube = LoadModelFromMesh(GenMeshCube(2.0f, 2.0f, 2.0f)); // Load geometry buffer (G-buffer) shader and deferred shader - Shader gbufferShader = LoadShader("resources/shaders/glsl330/gbuffer.vs", - "resources/shaders/glsl330/gbuffer.fs"); + Shader gbufferShader = LoadShader(TextFormat("resources/shaders/glsl%i/gbuffer.vs", GLSL_VERSION), + TextFormat("resources/shaders/glsl%i/gbuffer.fs", GLSL_VERSION)); - Shader deferredShader = LoadShader("resources/shaders/glsl330/deferred_shading.vs", - "resources/shaders/glsl330/deferred_shading.fs"); + Shader deferredShader = LoadShader(TextFormat("resources/shaders/glsl%i/deferred_shading.vs", GLSL_VERSION), + TextFormat("resources/shaders/glsl%i/deferred_shading.fs", GLSL_VERSION)); deferredShader.locs[SHADER_LOC_VECTOR_VIEW] = GetShaderLocation(deferredShader, "viewPosition"); // Initialize the G-buffer @@ -95,11 +97,19 @@ int main(void) rlEnableFramebuffer(gBuffer.framebuffer); - // Since we are storing position and normal data in these textures, - // we need to use a floating point format. - gBuffer.positionTexture = rlLoadTexture(NULL, screenWidth, screenHeight, RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32, 1); + // NOTE: Vertex positions are stored in a texture for simplicity. A better approach would use a depth texture + // (instead of a detph renderbuffer) to reconstruct world positions in the final render shader via clip-space position, + // 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. // The color in RGB, and the specular strength in the alpha channel. gBuffer.albedoSpecTexture = rlLoadTexture(NULL, screenWidth, screenHeight, RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1); @@ -122,18 +132,18 @@ int main(void) if (!rlFramebufferComplete(gBuffer.framebuffer)) { TraceLog(LOG_WARNING, "Framebuffer is not complete"); - exit(1); } // Now we initialize the sampler2D uniform's in the deferred shader. - // We do this by setting the uniform's value to the color channel slot we earlier - // bound our textures to. + // We do this by setting the uniform's values to the texture units that + // we later bind our g-buffer textures to. rlEnableShader(deferredShader.id); - - rlSetUniformSampler(rlGetLocationUniform(deferredShader.id, "gPosition"), 0); - rlSetUniformSampler(rlGetLocationUniform(deferredShader.id, "gNormal"), 1); - rlSetUniformSampler(rlGetLocationUniform(deferredShader.id, "gAlbedoSpec"), 2); - + int texUnitPosition = 0; + int texUnitNormal = 1; + int texUnitAlbedoSpec = 2; + SetShaderValue(deferredShader, rlGetLocationUniform(deferredShader.id, "gPosition"), &texUnitPosition, RL_SHADER_UNIFORM_SAMPLER2D); + SetShaderValue(deferredShader, rlGetLocationUniform(deferredShader.id, "gNormal"), &texUnitNormal, RL_SHADER_UNIFORM_SAMPLER2D); + SetShaderValue(deferredShader, rlGetLocationUniform(deferredShader.id, "gAlbedoSpec"), &texUnitAlbedoSpec, RL_SHADER_UNIFORM_SAMPLER2D); rlDisableShader(); // Assign out lighting shader to model @@ -200,11 +210,10 @@ int main(void) // Draw // --------------------------------------------------------------------------------- BeginDrawing(); - - ClearBackground(RAYWHITE); - + // Draw to the geometry buffer by first activating it rlEnableFramebuffer(gBuffer.framebuffer); + rlClearColor(0, 0, 0, 0); rlClearScreenBuffers(); // Clear color and depth buffer rlDisableColorBlend(); @@ -238,14 +247,14 @@ int main(void) BeginMode3D(camera); rlDisableColorBlend(); rlEnableShader(deferredShader.id); - // Activate our g-buffer textures - // These will now be bound to the sampler2D uniforms `gPosition`, `gNormal`, + // Bind our g-buffer textures + // We are binding them to locations that we earlier set in sampler2D uniforms `gPosition`, `gNormal`, // and `gAlbedoSpec` - rlActiveTextureSlot(0); + rlActiveTextureSlot(texUnitPosition); rlEnableTexture(gBuffer.positionTexture); - rlActiveTextureSlot(1); + rlActiveTextureSlot(texUnitNormal); rlEnableTexture(gBuffer.normalTexture); - rlActiveTextureSlot(2); + rlActiveTextureSlot(texUnitAlbedoSpec); rlEnableTexture(gBuffer.albedoSpecTexture); // Finally, we draw a fullscreen quad to our default framebuffer @@ -261,11 +270,11 @@ int main(void) rlBlitFramebuffer(0, 0, screenWidth, screenHeight, 0, 0, screenWidth, screenHeight, 0x00000100); // GL_DEPTH_BUFFER_BIT rlDisableFramebuffer(); - // Since our shader is now done and disabled, we can draw our lights in default - // forward rendering + // Since our shader is now done and disabled, we can draw spheres + // that represent light positions in default forward rendering BeginMode3D(camera); rlEnableShader(rlGetShaderIdDefault()); - for(int i = 0; i < MAX_LIGHTS; i++) + for (int i = 0; i < MAX_LIGHTS; i++) { if (lights[i].enabled) DrawSphereEx(lights[i].position, 0.2f, 8, 8, lights[i].color); else DrawSphereWires(lights[i].position, 0.2f, 8, 8, ColorAlpha(lights[i].color, 0.3f)); diff --git a/examples/shaders/shaders_eratosthenes.c b/examples/shaders/shaders_eratosthenes.c index 21b7ea8f9..0b8b08186 100644 --- a/examples/shaders/shaders_eratosthenes.c +++ b/examples/shaders/shaders_eratosthenes.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Sieve of Eratosthenes * +* Example complexity rating: [★★★☆] 3/4 +* * NOTE: Sieve of Eratosthenes, the earliest known (ancient Greek) prime number sieve. * * "Sift the twos and sift the threes, diff --git a/examples/shaders/shaders_fog.c b/examples/shaders/shaders_fog.c index ad514077d..eefce44fc 100644 --- a/examples/shaders/shaders_fog.c +++ b/examples/shaders/shaders_fog.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - fog * +* Example complexity rating: [★★★☆] 3/4 +* * NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, * OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. * diff --git a/examples/shaders/shaders_hot_reloading.c b/examples/shaders/shaders_hot_reloading.c index 2a9ea2d6d..f620a6247 100644 --- a/examples/shaders/shaders_hot_reloading.c +++ b/examples/shaders/shaders_hot_reloading.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Hot reloading * +* Example complexity rating: [★★★☆] 3/4 +* * NOTE: This example requires raylib OpenGL 3.3 for shaders support and only #version 330 * is currently supported. OpenGL ES 2.0 platforms are not supported at the moment. * diff --git a/examples/shaders/shaders_hybrid_render.c b/examples/shaders/shaders_hybrid_render.c index 5bf2e49a8..5f90f1724 100644 --- a/examples/shaders/shaders_hybrid_render.c +++ b/examples/shaders/shaders_hybrid_render.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Hybrid Rendering * +* Example complexity rating: [★★★★] 4/4 +* * Example originally created with raylib 4.2, last time updated with raylib 4.2 * * Example contributed by BuÄŸra Alptekin Sarı (@BugraAlptekinSari) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/shaders/shaders_julia_set.c b/examples/shaders/shaders_julia_set.c index 93a3436a8..3b30205f8 100644 --- a/examples/shaders/shaders_julia_set.c +++ b/examples/shaders/shaders_julia_set.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Julia sets * +* Example complexity rating: [★★★☆] 3/4 +* * NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, * OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. * diff --git a/examples/shaders/shaders_lightmap.c b/examples/shaders/shaders_lightmap.c index 91ed8bfd2..305399b98 100644 --- a/examples/shaders/shaders_lightmap.c +++ b/examples/shaders/shaders_lightmap.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - lightmap * +* Example complexity rating: [★★★☆] 3/4 +* * NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, * OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. * diff --git a/examples/shaders/shaders_mesh_instancing.c b/examples/shaders/shaders_mesh_instancing.c index eb42cb471..ca975beea 100644 --- a/examples/shaders/shaders_mesh_instancing.c +++ b/examples/shaders/shaders_mesh_instancing.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Mesh instancing * +* Example complexity rating: [★★★★] 4/4 +* * Example originally created with raylib 3.7, last time updated with raylib 4.2 * * Example contributed by @seanpringle and reviewed by Max (@moliad) and Ramon Santamaria (@raysan5) @@ -61,7 +63,7 @@ int main(void) { 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) }); - float angle = (float)GetRandomValue(0, 10)*DEG2RAD; + float angle = (float)GetRandomValue(0, 180)*DEG2RAD; Matrix rotation = MatrixRotate(axis, angle); transforms[i] = MatrixMultiply(rotation, translation); @@ -73,7 +75,6 @@ int main(void) // Get shader locations shader.locs[SHADER_LOC_MATRIX_MVP] = GetShaderLocation(shader, "mvp"); shader.locs[SHADER_LOC_VECTOR_VIEW] = GetShaderLocation(shader, "viewPos"); - shader.locs[SHADER_LOC_MATRIX_MODEL] = GetShaderLocationAttrib(shader, "instanceTransform"); // Set shader value: ambient light level int ambientLoc = GetShaderLocation(shader, "ambient"); diff --git a/examples/shaders/shaders_model_shader.c b/examples/shaders/shaders_model_shader.c index 9faa2d589..62a4dc003 100644 --- a/examples/shaders/shaders_model_shader.c +++ b/examples/shaders/shaders_model_shader.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Model shader * +* Example complexity rating: [★★☆☆] 2/4 +* * NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, * OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. * diff --git a/examples/shaders/shaders_multi_sample2d.c b/examples/shaders/shaders_multi_sample2d.c index ccdc6fa82..5e10cddce 100644 --- a/examples/shaders/shaders_multi_sample2d.c +++ b/examples/shaders/shaders_multi_sample2d.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Multiple sample2D with default batch system * +* Example complexity rating: [★★☆☆] 2/4 +* * NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, * OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. * diff --git a/examples/shaders/shaders_palette_switch.c b/examples/shaders/shaders_palette_switch.c index 9ff86d83d..a2d01a11d 100644 --- a/examples/shaders/shaders_palette_switch.c +++ b/examples/shaders/shaders_palette_switch.c @@ -1,6 +1,8 @@ /******************************************************************************************* * * raylib [shaders] example - Color palette switch +* +* Example complexity rating: [★★★☆] 3/4 * * NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, * OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. diff --git a/examples/shaders/shaders_postprocessing.c b/examples/shaders/shaders_postprocessing.c index 54ffae931..1e5fe0d14 100644 --- a/examples/shaders/shaders_postprocessing.c +++ b/examples/shaders/shaders_postprocessing.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Apply a postprocessing shader to a scene * +* Example complexity rating: [★★★☆] 3/4 +* * NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, * OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. * diff --git a/examples/shaders/shaders_raymarching.c b/examples/shaders/shaders_raymarching.c index 812d683e6..0f21f6a56 100644 --- a/examples/shaders/shaders_raymarching.c +++ b/examples/shaders/shaders_raymarching.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Raymarching shapes generation * +* Example complexity rating: [★★★★] 4/4 +* * NOTE: This example requires raylib OpenGL 3.3 for shaders support and only #version 330 * is currently supported. OpenGL ES 2.0 platforms are not supported at the moment. * diff --git a/examples/shaders/shaders_shapes_textures.c b/examples/shaders/shaders_shapes_textures.c index 65ccef659..95be102d5 100644 --- a/examples/shaders/shaders_shapes_textures.c +++ b/examples/shaders/shaders_shapes_textures.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Apply a shader to some shape or texture * +* Example complexity rating: [★★☆☆] 2/4 +* * NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, * OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. * diff --git a/examples/shaders/shaders_simple_mask.c b/examples/shaders/shaders_simple_mask.c index 11e0ac2e7..02e6c606a 100644 --- a/examples/shaders/shaders_simple_mask.c +++ b/examples/shaders/shaders_simple_mask.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Simple shader mask * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 2.5, last time updated with raylib 3.7 * * Example contributed by Chris Camacho (@chriscamacho) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/shaders/shaders_spotlight.c b/examples/shaders/shaders_spotlight.c index 2752a2db4..98a98e973 100644 --- a/examples/shaders/shaders_spotlight.c +++ b/examples/shaders/shaders_spotlight.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Simple shader mask * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 2.5, last time updated with raylib 3.7 * * Example contributed by Chris Camacho (@chriscamacho) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/shaders/shaders_texture_drawing.c b/examples/shaders/shaders_texture_drawing.c index ada44299d..d30b6e1f1 100644 --- a/examples/shaders/shaders_texture_drawing.c +++ b/examples/shaders/shaders_texture_drawing.c @@ -1,6 +1,8 @@ /******************************************************************************************* * -* raylib [textures] example - Texture drawing +* raylib [shaders] example - Texture drawing +* +* Example complexity rating: [★★☆☆] 2/4 * * NOTE: This example illustrates how to draw into a blank texture using a shader * diff --git a/examples/shaders/shaders_texture_outline.c b/examples/shaders/shaders_texture_outline.c index f90e41769..3c14bd0f2 100644 --- a/examples/shaders/shaders_texture_outline.c +++ b/examples/shaders/shaders_texture_outline.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Apply an shdrOutline to a texture * +* Example complexity rating: [★★★☆] 3/4 +* * NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, * OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. * diff --git a/examples/shaders/shaders_texture_tiling.c b/examples/shaders/shaders_texture_tiling.c index 0d07bdff9..ca32580b6 100644 --- a/examples/shaders/shaders_texture_tiling.c +++ b/examples/shaders/shaders_texture_tiling.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - texture tiling * +* Example complexity rating: [★★☆☆] 2/4 +* * Example demonstrates how to tile a texture on a 3D model using raylib. * * Example contributed by Luis Almeida (@luis605) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/shaders/shaders_texture_waves.c b/examples/shaders/shaders_texture_waves.c index 205fc636e..8d78b7593 100644 --- a/examples/shaders/shaders_texture_waves.c +++ b/examples/shaders/shaders_texture_waves.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Texture Waves * +* Example complexity rating: [★★☆☆] 2/4 +* * NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, * OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. * diff --git a/examples/shaders/shaders_write_depth.c b/examples/shaders/shaders_write_depth.c index 531a7bfa6..c665a56d3 100644 --- a/examples/shaders/shaders_write_depth.c +++ b/examples/shaders/shaders_write_depth.c @@ -2,6 +2,8 @@ * * raylib [shaders] example - Depth buffer writing * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 4.2, last time updated with raylib 4.2 * * Example contributed by BuÄŸra Alptekin Sarı (@BugraAlptekinSari) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/shapes/raygui.h b/examples/shapes/raygui.h index 16e01a28f..85c477870 100644 --- a/examples/shapes/raygui.h +++ b/examples/shapes/raygui.h @@ -998,7 +998,7 @@ typedef enum { ICON_LAYERS2 = 225, ICON_MLAYERS = 226, ICON_MAPS = 227, - ICON_228 = 228, + ICON_HOT = 228, ICON_229 = 229, ICON_230 = 230, ICON_231 = 231, @@ -1045,6 +1045,7 @@ typedef enum { #if defined(RAYGUI_IMPLEMENTATION) +#include // required for: isspace() [GuiTextBox()] #include // Required for: FILE, fopen(), fclose(), fprintf(), feof(), fscanf(), vsprintf() [GuiLoadStyle(), GuiLoadIcons()] #include // Required for: malloc(), calloc(), free() [GuiLoadStyle(), GuiLoadIcons()] #include // Required for: strlen() [GuiTextBox(), GuiValueBox()], memset(), memcpy() @@ -1316,7 +1317,7 @@ static unsigned int guiIcons[RAYGUI_ICON_MAX_ICONS*RAYGUI_ICON_DATA_ELEMENTS] = 0x07fe0000, 0x1c020402, 0x74021402, 0x54025402, 0x54025402, 0x500857fe, 0x40205ff8, 0x00007fe0, // ICON_LAYERS2 0x0ffe0000, 0x3ffa0802, 0x7fea200a, 0x402a402a, 0x422a422a, 0x422e422a, 0x40384e28, 0x00007fe0, // ICON_MLAYERS 0x0ffe0000, 0x3ffa0802, 0x7fea200a, 0x402a402a, 0x5b2a512a, 0x512e552a, 0x40385128, 0x00007fe0, // ICON_MAPS - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_228 + 0x04200000, 0x1cf00c60, 0x11f019f0, 0x0f3807b8, 0x1e3c0f3c, 0x1c1c1e1c, 0x1e3c1c1c, 0x00000f70, // ICON_HOT 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_229 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_230 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_231 @@ -1639,9 +1640,9 @@ int GuiGroupBox(Rectangle bounds, const char *text) // Draw control //-------------------------------------------------------------------- - GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, RAYGUI_GROUPBOX_LINE_THICK, bounds.height }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BORDER_COLOR_DISABLED : LINE_COLOR))); - GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, bounds.width, RAYGUI_GROUPBOX_LINE_THICK }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BORDER_COLOR_DISABLED : LINE_COLOR))); - GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - 1, bounds.y, RAYGUI_GROUPBOX_LINE_THICK, bounds.height }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BORDER_COLOR_DISABLED : LINE_COLOR))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, RAYGUI_GROUPBOX_LINE_THICK, bounds.height }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, bounds.width, RAYGUI_GROUPBOX_LINE_THICK }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - 1, bounds.y, RAYGUI_GROUPBOX_LINE_THICK, bounds.height }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR))); GuiLine(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y - GuiGetStyle(DEFAULT, TEXT_SIZE)/2, bounds.width, (float)GuiGetStyle(DEFAULT, TEXT_SIZE) }, text); //-------------------------------------------------------------------- @@ -1662,7 +1663,7 @@ int GuiLine(Rectangle bounds, const char *text) int result = 0; GuiState state = guiState; - Color color = GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BORDER_COLOR_DISABLED : LINE_COLOR)); + Color color = GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR)); // Draw control //-------------------------------------------------------------------- @@ -1710,7 +1711,7 @@ int GuiPanel(Rectangle bounds, const char *text) //-------------------------------------------------------------------- if (text != NULL) GuiStatusBar(statusBar, text); // Draw panel header as status bar - GuiDrawRectangle(bounds, RAYGUI_PANEL_BORDER_WIDTH, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BORDER_COLOR_DISABLED: LINE_COLOR)), + GuiDrawRectangle(bounds, RAYGUI_PANEL_BORDER_WIDTH, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED: (int)LINE_COLOR)), GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BASE_COLOR_DISABLED : BACKGROUND_COLOR))); //-------------------------------------------------------------------- @@ -2603,24 +2604,59 @@ int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode) } } - // Delete codepoint from text, before current cursor position - if ((textLength > 0) && (IsKeyPressed(KEY_BACKSPACE) || (IsKeyDown(KEY_BACKSPACE) && (autoCursorCooldownCounter >= RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN)))) + // Delete related codepoints from text, before current cursor position + if ((textLength > 0) && IsKeyPressed(KEY_BACKSPACE) && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL))) + { + int i = textBoxCursorIndex - 1; + int accCodepointSize = 0; + + // Move cursor to the end of word if on space already + while ((i > 0) && isspace(text[i])) + { + int prevCodepointSize = 0; + GetCodepointPrevious(text + i, &prevCodepointSize); + i -= prevCodepointSize; + accCodepointSize += prevCodepointSize; + } + + // Move cursor to the start of the word + while ((i > 0) && !isspace(text[i])) + { + int prevCodepointSize = 0; + GetCodepointPrevious(text + i, &prevCodepointSize); + i -= prevCodepointSize; + accCodepointSize += prevCodepointSize; + } + + // Move forward text from cursor position + for (int j = (textBoxCursorIndex - accCodepointSize); j < textLength; j++) text[j] = text[j + accCodepointSize]; + + // Prevent cursor index from decrementing past 0 + if (textBoxCursorIndex > 0) + { + textBoxCursorIndex -= accCodepointSize; + textLength -= accCodepointSize; + } + + // Make sure text last character is EOL + text[textLength] = '\0'; + } + else if ((textLength > 0) && (IsKeyPressed(KEY_BACKSPACE) || (IsKeyDown(KEY_BACKSPACE) && (autoCursorCooldownCounter >= RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN)))) { autoCursorDelayCounter++; if (IsKeyPressed(KEY_BACKSPACE) || (autoCursorDelayCounter%RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) == 0) // Delay every movement some frames { int prevCodepointSize = 0; - GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize); - - // Move backward text from cursor position - for (int i = (textBoxCursorIndex - prevCodepointSize); i < textLength; i++) text[i] = text[i + prevCodepointSize]; - - // TODO Check: >= cursor+codepointsize and <= length-codepointsize // Prevent cursor index from decrementing past 0 if (textBoxCursorIndex > 0) { + GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize); + + // Move backward text from cursor position + for (int i = (textBoxCursorIndex - prevCodepointSize); i < textLength; i++) text[i] = text[i + prevCodepointSize]; + textBoxCursorIndex -= codepointSize; textLength -= codepointSize; } @@ -2638,7 +2674,7 @@ int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode) if (IsKeyPressed(KEY_LEFT) || (autoCursorDelayCounter%RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) == 0) // Delay every movement some frames { int prevCodepointSize = 0; - GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize); + if (textBoxCursorIndex > 0) GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize); if (textBoxCursorIndex >= prevCodepointSize) textBoxCursorIndex -= prevCodepointSize; } @@ -3426,7 +3462,7 @@ int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollInd // Draw control //-------------------------------------------------------------------- - GuiDrawRectangle(bounds, GuiGetStyle(DEFAULT, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); // Draw background + GuiDrawRectangle(bounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); // Draw background // Draw visible items for (int i = 0; ((i < visibleItems) && (text != NULL)); i++) @@ -3881,7 +3917,7 @@ int GuiMessageBox(Rectangle bounds, const char *title, const char *message, cons buttonBounds.width = (bounds.width - RAYGUI_MESSAGEBOX_BUTTON_PADDING*(buttonCount + 1))/buttonCount; buttonBounds.height = RAYGUI_MESSAGEBOX_BUTTON_HEIGHT; - int textWidth = GetTextWidth(message) + 2; + //int textWidth = GetTextWidth(message) + 2; Rectangle textBounds = { 0 }; textBounds.x = bounds.x + RAYGUI_MESSAGEBOX_BUTTON_PADDING; @@ -4485,7 +4521,7 @@ static void GuiLoadStyleFromMemory(const unsigned char *fileData, int dataSize) // NOTE: All DEFAULT properties should be defined first in the file GuiSetStyle(0, (int)propertyId, propertyValue); - if (propertyId < RAYGUI_MAX_PROPS_BASE) for (int i = 1; i < RAYGUI_MAX_CONTROLS; i++) GuiSetStyle(i, (int)propertyId, propertyValue); + if (propertyId < RAYGUI_MAX_PROPS_BASE) for (int j = 1; j < RAYGUI_MAX_CONTROLS; j++) GuiSetStyle(j, (int)propertyId, propertyValue); } else GuiSetStyle((int)controlId, (int)propertyId, propertyValue); } @@ -5718,4 +5754,4 @@ static int GetCodepointNext(const char *text, int *codepointSize) } #endif // RAYGUI_STANDALONE -#endif // RAYGUI_IMPLEMENTATION \ No newline at end of file +#endif // RAYGUI_IMPLEMENTATION diff --git a/examples/shapes/shapes_basic_shapes.c b/examples/shapes/shapes_basic_shapes.c index 9c0fff7d0..78297e37f 100644 --- a/examples/shapes/shapes_basic_shapes.c +++ b/examples/shapes/shapes_basic_shapes.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - Draw basic shapes 2d (rectangle, circle, line...) * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.0, last time updated with raylib 4.2 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/shapes/shapes_bouncing_ball.c b/examples/shapes/shapes_bouncing_ball.c index df0c37c1c..394e54886 100644 --- a/examples/shapes/shapes_bouncing_ball.c +++ b/examples/shapes/shapes_bouncing_ball.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - bouncing ball * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 2.5, last time updated with raylib 2.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/shapes/shapes_collision_area.c b/examples/shapes/shapes_collision_area.c index c2e2c1e1d..ddb156831 100644 --- a/examples/shapes/shapes_collision_area.c +++ b/examples/shapes/shapes_collision_area.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - collision area * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 2.5, last time updated with raylib 2.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/shapes/shapes_colors_palette.c b/examples/shapes/shapes_colors_palette.c index 60a6dd6a2..f94be8161 100644 --- a/examples/shapes/shapes_colors_palette.c +++ b/examples/shapes/shapes_colors_palette.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - Colors palette * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 1.0, last time updated with raylib 2.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/shapes/shapes_draw_circle_sector.c b/examples/shapes/shapes_draw_circle_sector.c index cb9ab859b..8be6b045f 100644 --- a/examples/shapes/shapes_draw_circle_sector.c +++ b/examples/shapes/shapes_draw_circle_sector.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - draw circle sector (with gui options) * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 2.5, last time updated with raylib 2.5 * * Example contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/shapes/shapes_draw_rectangle_rounded.c b/examples/shapes/shapes_draw_rectangle_rounded.c index 58991884c..1dbfd5282 100644 --- a/examples/shapes/shapes_draw_rectangle_rounded.c +++ b/examples/shapes/shapes_draw_rectangle_rounded.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - draw rectangle rounded (with gui options) * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 2.5, last time updated with raylib 2.5 * * Example contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/shapes/shapes_draw_ring.c b/examples/shapes/shapes_draw_ring.c index 8bccdf729..91c563dbe 100644 --- a/examples/shapes/shapes_draw_ring.c +++ b/examples/shapes/shapes_draw_ring.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - draw ring (with gui options) * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 2.5, last time updated with raylib 2.5 * * Example contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/shapes/shapes_easings_ball_anim.c b/examples/shapes/shapes_easings_ball_anim.c index d54f24a1d..654ed8cd5 100644 --- a/examples/shapes/shapes_easings_ball_anim.c +++ b/examples/shapes/shapes_easings_ball_anim.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - easings ball anim * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 2.5, last time updated with raylib 2.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/shapes/shapes_easings_box_anim.c b/examples/shapes/shapes_easings_box_anim.c index c82beac05..8407dfc2f 100644 --- a/examples/shapes/shapes_easings_box_anim.c +++ b/examples/shapes/shapes_easings_box_anim.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - easings box anim * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 2.5, last time updated with raylib 2.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/shapes/shapes_easings_rectangle_array.c b/examples/shapes/shapes_easings_rectangle_array.c index ed13e93c1..e250007f8 100644 --- a/examples/shapes/shapes_easings_rectangle_array.c +++ b/examples/shapes/shapes_easings_rectangle_array.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - easings rectangle array * +* Example complexity rating: [★★★☆] 3/4 +* * NOTE: This example requires 'easings.h' library, provided on raylib/src. Just copy * the library to same directory as example or make sure it's available on include path. * diff --git a/examples/shapes/shapes_following_eyes.c b/examples/shapes/shapes_following_eyes.c index 7e428f2c3..97f5b2981 100644 --- a/examples/shapes/shapes_following_eyes.c +++ b/examples/shapes/shapes_following_eyes.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - following eyes * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 2.5, last time updated with raylib 2.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/shapes/shapes_lines_bezier.c b/examples/shapes/shapes_lines_bezier.c index 1293e16e4..08559888d 100644 --- a/examples/shapes/shapes_lines_bezier.c +++ b/examples/shapes/shapes_lines_bezier.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - Cubic-bezier lines * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.7, last time updated with raylib 1.7 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/shapes/shapes_logo_raylib.c b/examples/shapes/shapes_logo_raylib.c index f637df2c9..f7408bf78 100644 --- a/examples/shapes/shapes_logo_raylib.c +++ b/examples/shapes/shapes_logo_raylib.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - Draw raylib logo using basic shapes * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.0, last time updated with raylib 1.0 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/shapes/shapes_logo_raylib_anim.c b/examples/shapes/shapes_logo_raylib_anim.c index ace9c8d02..80fcbba1a 100644 --- a/examples/shapes/shapes_logo_raylib_anim.c +++ b/examples/shapes/shapes_logo_raylib_anim.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - raylib logo animation * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 2.5, last time updated with raylib 4.0 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/shapes/shapes_rectangle_advanced.c b/examples/shapes/shapes_rectangle_advanced.c index a103e82a1..6dd7d2e7e 100644 --- a/examples/shapes/shapes_rectangle_advanced.c +++ b/examples/shapes/shapes_rectangle_advanced.c @@ -1,10 +1,87 @@ +/******************************************************************************************* +* +* raylib [shapes] example - Rectangle advanced +* +* Example originally created with raylib 5.5, last time updated with raylib 5.5 +* +* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, +* BSD-like license that allows static linking with closed source software +* +* Copyright (c) 2024-2025 raylib contributors and Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + #include "raylib.h" + #include "rlgl.h" + #include // Draw rectangle with rounded edges and horizontal gradient, with options to choose side of roundness -// Adapted from both `DrawRectangleRounded` and `DrawRectangleGradientH` -void DrawRectangleRoundedGradientH(Rectangle rec, float roundnessLeft, float roundnessRight, int segments, Color left, Color right) +static void DrawRectangleRoundedGradientH(Rectangle rec, float roundnessLeft, float roundnessRight, int segments, Color left, Color right); + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [shapes] example - rectangle avanced"); + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update rectangle bounds + //---------------------------------------------------------------------------------- + float width = GetScreenWidth()/2.0f, height = GetScreenHeight()/6.0f; + Rectangle rec = { + GetScreenWidth() / 2.0f - width/2, + GetScreenHeight() / 2.0f - 5*(height/2), + width, height + }; + //-------------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + ClearBackground(RAYWHITE); + + // Draw All Rectangles with different roundess for each side and different gradients + DrawRectangleRoundedGradientH(rec, 0.8f, 0.8f, 36, BLUE, RED); + + rec.y += rec.height + 1; + DrawRectangleRoundedGradientH(rec, 0.5f, 1.0f, 36, RED, PINK); + + rec.y += rec.height + 1; + DrawRectangleRoundedGradientH(rec, 1.0f, 0.5f, 36, RED, BLUE); + + rec.y += rec.height + 1; + DrawRectangleRoundedGradientH(rec, 0.0f, 1.0f, 36, BLUE, BLACK); + + rec.y += rec.height + 1; + DrawRectangleRoundedGradientH(rec, 1.0f, 0.0f, 36, BLUE, PINK); + EndDrawing(); + //-------------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +// Draw rectangle with rounded edges and horizontal gradient, with options to choose side of roundness +// NOTE: Adapted from both 'DrawRectangleRounded()' and 'DrawRectangleGradientH()' raylib [rshapes] implementations +static void DrawRectangleRoundedGradientH(Rectangle rec, float roundnessLeft, float roundnessRight, int segments, Color left, Color right) { // Neither side is rounded if ((roundnessLeft <= 0.0f && roundnessRight <= 0.0f) || (rec.width < 1) || (rec.height < 1 )) @@ -29,7 +106,7 @@ void DrawRectangleRoundedGradientH(Rectangle rec, float roundnessLeft, float rou float stepLength = 90.0f/(float)segments; /* - Diagram Copied here for reference, original at `DrawRectangleRounded` source code + Diagram Copied here for reference, original at 'DrawRectangleRounded()' source code P0____________________P1 /| |\ @@ -113,12 +190,9 @@ void DrawRectangleRoundedGradientH(Rectangle rec, float roundnessLeft, float rou } } - // - // Here we use the `Diagram` to guide ourselves to which point receives what color. - // + // Here we use the 'Diagram' to guide ourselves to which point receives what color // By choosing the color correctly associated with a pointe the gradient effect - // will naturally come from OpenGL interpolation. - // + // will naturally come from OpenGL interpolation // [2] Upper Rectangle rlColor4ub(left.r, left.g, left.b, left.a); @@ -187,27 +261,25 @@ void DrawRectangleRoundedGradientH(Rectangle rec, float roundnessLeft, float rou rlSetTexture(0); #else - // - // Here we use the `Diagram` to guide ourselves to which point receives what color. - // + // Here we use the 'Diagram' to guide ourselves to which point receives what color. // By choosing the color correctly associated with a pointe the gradient effect // will naturally come from OpenGL interpolation. // But this time instead of Quad, we think in triangles. - // rlBegin(RL_TRIANGLES); - // Draw all of the 4 corners: [1] Upper Left Corner, [3] Upper Right Corner, [5] Lower Right Corner, [7] Lower Left Corner for (int k = 0; k < 4; ++k) { - Color color; - float radius; + Color color = { 0 }; + float radius = 0.0f; if (k == 0) color = left, radius = radiusLeft; // [1] Upper Left Corner if (k == 1) color = right, radius = radiusRight; // [3] Upper Right Corner if (k == 2) color = right, radius = radiusRight; // [5] Lower Right Corner if (k == 3) color = left, radius = radiusLeft; // [7] Lower Left Corner + float angle = angles[k]; const Vector2 center = centers[k]; + for (int i = 0; i < segments; i++) { rlColor4ub(color.r, color.g, color.b, color.a); @@ -274,57 +346,3 @@ void DrawRectangleRoundedGradientH(Rectangle rec, float roundnessLeft, float rou rlEnd(); #endif } - -int main(int argc, char *argv[]) -{ - // Initialization - //-------------------------------------------------------------------------------------- - const int screenWidth = 800; - const int screenHeight = 450; - InitWindow(screenWidth, screenHeight, "raylib [shapes] example - rectangle avanced"); - SetTargetFPS(60); - //-------------------------------------------------------------------------------------- - - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update rectangle bounds - //---------------------------------------------------------------------------------- - double width = GetScreenWidth()/2.0, height = GetScreenHeight()/6.0; - Rectangle rec = { - GetScreenWidth() / 2.0 - width/2, - GetScreenHeight() / 2.0 - (5)*(height/2), - width, height - }; - //-------------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - ClearBackground(RAYWHITE); - - // Draw All Rectangles with different roundess for each side and different gradients - DrawRectangleRoundedGradientH(rec, 0.8, 0.8, 36, BLUE, RED); - - rec.y += rec.height + 1; - DrawRectangleRoundedGradientH(rec, 0.5, 1.0, 36, RED, PINK); - - rec.y += rec.height + 1; - DrawRectangleRoundedGradientH(rec, 1.0, 0.5, 36, RED, BLUE); - - rec.y += rec.height + 1; - DrawRectangleRoundedGradientH(rec, 0.0, 1.0, 36, BLUE, BLACK); - - rec.y += rec.height + 1; - DrawRectangleRoundedGradientH(rec, 1.0, 0.0, 36, BLUE, PINK); - EndDrawing(); - //-------------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - return 0; -} - diff --git a/examples/shapes/shapes_rectangle_scaling.c b/examples/shapes/shapes_rectangle_scaling.c index dcafab9da..416b02c0d 100644 --- a/examples/shapes/shapes_rectangle_scaling.c +++ b/examples/shapes/shapes_rectangle_scaling.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - rectangle scaling by mouse * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 2.5, last time updated with raylib 2.5 * * Example contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/shapes/shapes_splines_drawing.c b/examples/shapes/shapes_splines_drawing.c index 536b558e1..9b3a14926 100644 --- a/examples/shapes/shapes_splines_drawing.c +++ b/examples/shapes/shapes_splines_drawing.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - splines drawing * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 5.0, last time updated with raylib 5.0 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/shapes/shapes_top_down_lights.c b/examples/shapes/shapes_top_down_lights.c index abe845f8c..39de6ccf7 100644 --- a/examples/shapes/shapes_top_down_lights.c +++ b/examples/shapes/shapes_top_down_lights.c @@ -2,6 +2,8 @@ * * raylib [shapes] example - top down lights * +* Example complexity rating: [★★★★] 4/4 +* * Example originally created with raylib 4.2, last time updated with raylib 4.2 * * Example contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/text/text_codepoints_loading.c b/examples/text/text_codepoints_loading.c index 95a81dfc3..df3b76894 100644 --- a/examples/text/text_codepoints_loading.c +++ b/examples/text/text_codepoints_loading.c @@ -2,6 +2,8 @@ * * raylib [text] example - Codepoints loading * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 4.2, last time updated with raylib 2.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/text/text_draw_3d.c b/examples/text/text_draw_3d.c index ed4e6ce67..8d93db439 100644 --- a/examples/text/text_draw_3d.c +++ b/examples/text/text_draw_3d.c @@ -2,6 +2,8 @@ * * raylib [text] example - Draw 3d * +* Example complexity rating: [★★★★] 4/4 +* * NOTE: Draw a 2D text in 3D space, each letter is drawn in a quad (or 2 quads if backface is set) * where the texture coodinates of each quad map to the texture coordinates of the glyphs * inside the font texture. @@ -286,7 +288,7 @@ int main(void) DrawGrid(10, 2.0f); // Use a shader to handle the depth buffer issue with transparent textures - // NOTE: more info at https://bedroomcoders.co.uk/raylib-billboards-advanced-use/ + // NOTE: more info at https://bedroomcoders.co.uk/posts/198 BeginShaderMode(alphaDiscard); // Draw the 3D text above the red cube diff --git a/examples/text/text_font_filters.c b/examples/text/text_font_filters.c index b12f26055..7893e01f2 100644 --- a/examples/text/text_font_filters.c +++ b/examples/text/text_font_filters.c @@ -2,6 +2,8 @@ * * raylib [text] example - Font filters * +* Example complexity rating: [★★☆☆] 2/4 +* * NOTE: After font loading, font texture atlas filter could be configured for a softer * display of the font when scaling it to different sizes, that way, it's not required * to generate multiple fonts at multiple sizes (as long as the scaling is not very different) diff --git a/examples/text/text_font_loading.c b/examples/text/text_font_loading.c index 6b98a4e8a..17c06abac 100644 --- a/examples/text/text_font_loading.c +++ b/examples/text/text_font_loading.c @@ -2,6 +2,8 @@ * * raylib [text] example - Font loading * +* Example complexity rating: [★☆☆☆] 1/4 +* * NOTE: raylib can load fonts from multiple input file formats: * * - TTF/OTF > Sprite font atlas is generated on loading, user can configure diff --git a/examples/text/text_font_sdf.c b/examples/text/text_font_sdf.c index 95245741e..d3b3098ad 100644 --- a/examples/text/text_font_sdf.c +++ b/examples/text/text_font_sdf.c @@ -2,6 +2,8 @@ * * raylib [text] example - Font SDF loading * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 1.3, last time updated with raylib 4.0 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/text/text_font_spritefont.c b/examples/text/text_font_spritefont.c index 1b2695c71..7655a0c2c 100644 --- a/examples/text/text_font_spritefont.c +++ b/examples/text/text_font_spritefont.c @@ -2,6 +2,8 @@ * * raylib [text] example - Sprite font loading * +* Example complexity rating: [★☆☆☆] 1/4 +* * NOTE: Sprite fonts should be generated following this conventions: * * - Characters must be ordered starting with character 32 (Space) diff --git a/examples/text/text_format_text.c b/examples/text/text_format_text.c index 0f53f35dc..d9dc32d04 100644 --- a/examples/text/text_format_text.c +++ b/examples/text/text_format_text.c @@ -2,6 +2,8 @@ * * raylib [text] example - Text formatting * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.1, last time updated with raylib 3.0 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/text/text_input_box.c b/examples/text/text_input_box.c index c53057711..14bedf27a 100644 --- a/examples/text/text_input_box.c +++ b/examples/text/text_input_box.c @@ -2,6 +2,8 @@ * * raylib [text] example - Input Box * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 1.7, last time updated with raylib 3.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/text/text_raylib_fonts.c b/examples/text/text_raylib_fonts.c index acd18d94c..45314c9a0 100644 --- a/examples/text/text_raylib_fonts.c +++ b/examples/text/text_raylib_fonts.c @@ -2,6 +2,8 @@ * * raylib [text] example - raylib fonts loading * +* Example complexity rating: [★☆☆☆] 1/4 +* * NOTE: raylib is distributed with some free to use fonts (even for commercial pourposes!) * To view details and credits for those fonts, check raylib license file * diff --git a/examples/text/text_rectangle_bounds.c b/examples/text/text_rectangle_bounds.c index 173d3f93d..6da91a6a3 100644 --- a/examples/text/text_rectangle_bounds.c +++ b/examples/text/text_rectangle_bounds.c @@ -2,6 +2,8 @@ * * raylib [text] example - Rectangle bounds * +* Example complexity rating: [★★★★] 4/4 +* * Example originally created with raylib 2.5, last time updated with raylib 4.0 * * Example contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/text/text_unicode.c b/examples/text/text_unicode.c index 2b5245be9..ba37416fa 100644 --- a/examples/text/text_unicode.c +++ b/examples/text/text_unicode.c @@ -2,6 +2,8 @@ * * raylib [text] example - Unicode * +* Example complexity rating: [★★★★] 4/4 +* * Example originally created with raylib 2.5, last time updated with raylib 4.0 * * Example contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/text/text_writing_anim.c b/examples/text/text_writing_anim.c index 8e2820fc9..0f91668ba 100644 --- a/examples/text/text_writing_anim.c +++ b/examples/text/text_writing_anim.c @@ -2,6 +2,8 @@ * * raylib [text] example - Text Writing Animation * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 1.4, last time updated with raylib 1.4 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/textures/textures_background_scrolling.c b/examples/textures/textures_background_scrolling.c index 0df159cae..9dfa8d50a 100644 --- a/examples/textures/textures_background_scrolling.c +++ b/examples/textures/textures_background_scrolling.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Background scrolling * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 2.0, last time updated with raylib 2.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/textures/textures_blend_modes.c b/examples/textures/textures_blend_modes.c index d97432cb2..4cb5b801c 100644 --- a/examples/textures/textures_blend_modes.c +++ b/examples/textures/textures_blend_modes.c @@ -2,6 +2,8 @@ * * raylib [textures] example - blend modes * +* Example complexity rating: [★☆☆☆] 1/4 +* * NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) * * Example originally created with raylib 3.5, last time updated with raylib 3.5 diff --git a/examples/textures/textures_bunnymark.c b/examples/textures/textures_bunnymark.c index f3ef694a2..18b9cda3b 100644 --- a/examples/textures/textures_bunnymark.c +++ b/examples/textures/textures_bunnymark.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Bunnymark * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 1.6, last time updated with raylib 2.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/textures/textures_draw_tiled.c b/examples/textures/textures_draw_tiled.c index 699836555..c0d827feb 100644 --- a/examples/textures/textures_draw_tiled.c +++ b/examples/textures/textures_draw_tiled.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Draw part of the texture tiled * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 3.0, last time updated with raylib 4.2 * * Example contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/textures/textures_fog_of_war.c b/examples/textures/textures_fog_of_war.c index 2f72c0d6d..fba8c2204 100644 --- a/examples/textures/textures_fog_of_war.c +++ b/examples/textures/textures_fog_of_war.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Fog of war * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 4.2, last time updated with raylib 4.2 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/textures/textures_gif_player.c b/examples/textures/textures_gif_player.c index cf8492e0d..7eb4c5703 100644 --- a/examples/textures/textures_gif_player.c +++ b/examples/textures/textures_gif_player.c @@ -2,6 +2,8 @@ * * raylib [textures] example - gif playing * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 4.2, last time updated with raylib 4.2 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/textures/textures_image_channel.c b/examples/textures/textures_image_channel.c index 39618c5f4..9afcda638 100644 --- a/examples/textures/textures_image_channel.c +++ b/examples/textures/textures_image_channel.c @@ -24,7 +24,6 @@ int main(void) { // Initialization //-------------------------------------------------------------------------------------- - const int screenWidth = 800; const int screenHeight = 450; @@ -60,8 +59,6 @@ int main(void) UnloadImage(imageBlue); UnloadImage(backgroundImage); - SetTargetFPS(60); // Set our game to run at 60 frames-per-second - Rectangle fudesumiRec = {0, 0, fudesumiImage.width, fudesumiImage.height}; Rectangle fudesumiPos = {50, 10, fudesumiImage.width*0.8f, fudesumiImage.height*0.8f}; @@ -70,11 +67,17 @@ int main(void) Rectangle bluePos = { 410, 230, fudesumiPos.width / 2, fudesumiPos.height / 2 }; Rectangle alphaPos = { 600, 230, fudesumiPos.width / 2, fudesumiPos.height / 2 }; + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { + // Draw + //---------------------------------------------------------------------------------- + // TODO... + //---------------------------------------------------------------------------------- + // Draw //---------------------------------------------------------------------------------- BeginDrawing(); diff --git a/examples/textures/textures_image_drawing.c b/examples/textures/textures_image_drawing.c index d0eee999d..4d73a2224 100644 --- a/examples/textures/textures_image_drawing.c +++ b/examples/textures/textures_image_drawing.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Image loading and drawing on it * +* Example complexity rating: [★★☆☆] 2/4 +* * NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) * * Example originally created with raylib 1.4, last time updated with raylib 1.4 diff --git a/examples/textures/textures_image_generation.c b/examples/textures/textures_image_generation.c index 97e43f007..0a3610ab6 100644 --- a/examples/textures/textures_image_generation.c +++ b/examples/textures/textures_image_generation.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Procedural images generation * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 1.8, last time updated with raylib 1.8 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, @@ -88,7 +90,7 @@ int main(void) DrawRectangleLines(30, 400, 325, 30, Fade(WHITE, 0.5f)); DrawText("MOUSE LEFT BUTTON to CYCLE PROCEDURAL TEXTURES", 40, 410, 10, WHITE); - switch(currentTexture) + switch (currentTexture) { case 0: DrawText("VERTICAL GRADIENT", 560, 10, 20, RAYWHITE); break; case 1: DrawText("HORIZONTAL GRADIENT", 540, 10, 20, RAYWHITE); break; diff --git a/examples/textures/textures_image_loading.c b/examples/textures/textures_image_loading.c index 95175e079..e26ccb645 100644 --- a/examples/textures/textures_image_loading.c +++ b/examples/textures/textures_image_loading.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Image loading and texture creation * +* Example complexity rating: [★☆☆☆] 1/4 +* * NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) * * Example originally created with raylib 1.3, last time updated with raylib 1.3 diff --git a/examples/textures/textures_image_processing.c b/examples/textures/textures_image_processing.c index 269273546..7a61cd024 100644 --- a/examples/textures/textures_image_processing.c +++ b/examples/textures/textures_image_processing.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Image processing * +* Example complexity rating: [★★★☆] 3/4 +* * NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) * * Example originally created with raylib 1.4, last time updated with raylib 3.5 diff --git a/examples/textures/textures_image_text.c b/examples/textures/textures_image_text.c index 856b64ed0..4d5c281f7 100644 --- a/examples/textures/textures_image_text.c +++ b/examples/textures/textures_image_text.c @@ -1,6 +1,8 @@ /******************************************************************************************* * -* raylib [texture] example - Image text drawing using TTF generated font +* raylib [textures] example - Image text drawing using TTF generated font +* +* Example complexity rating: [★★☆☆] 2/4 * * Example originally created with raylib 1.8, last time updated with raylib 4.0 * diff --git a/examples/textures/textures_logo_raylib.c b/examples/textures/textures_logo_raylib.c index 35baa1223..4456fef02 100644 --- a/examples/textures/textures_logo_raylib.c +++ b/examples/textures/textures_logo_raylib.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Texture loading and drawing * +* Example complexity rating: [★☆☆☆] 1/4 +* * Example originally created with raylib 1.0, last time updated with raylib 1.0 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/textures/textures_mouse_painting.c b/examples/textures/textures_mouse_painting.c index 27bbc74e9..324f88fa1 100644 --- a/examples/textures/textures_mouse_painting.c +++ b/examples/textures/textures_mouse_painting.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Mouse painting * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 3.0, last time updated with raylib 3.0 * * Example contributed by Chris Dill (@MysteriousSpace) and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/textures/textures_npatch_drawing.c b/examples/textures/textures_npatch_drawing.c index 5fb39996b..5e23a0fb6 100644 --- a/examples/textures/textures_npatch_drawing.c +++ b/examples/textures/textures_npatch_drawing.c @@ -2,6 +2,8 @@ * * raylib [textures] example - N-patch drawing * +* Example complexity rating: [★★★☆] 3/4 +* * NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) * * Example originally created with raylib 2.0, last time updated with raylib 2.5 diff --git a/examples/textures/textures_particles_blending.c b/examples/textures/textures_particles_blending.c index 113b2b068..6781668e9 100644 --- a/examples/textures/textures_particles_blending.c +++ b/examples/textures/textures_particles_blending.c @@ -1,6 +1,8 @@ /******************************************************************************************* * -* raylib example - particles blending +* raylib [textures] example - particles blending +* +* Example complexity rating: [★☆☆☆] 1/4 * * Example originally created with raylib 1.7, last time updated with raylib 3.5 * diff --git a/examples/textures/textures_polygon.c b/examples/textures/textures_polygon.c index 2491e1bc2..82ccd1cf1 100644 --- a/examples/textures/textures_polygon.c +++ b/examples/textures/textures_polygon.c @@ -1,6 +1,8 @@ /******************************************************************************************* * -* raylib [shapes] example - Draw Textured Polygon +* raylib [textures] example - Draw Textured Polygon +* +* Example complexity rating: [★☆☆☆] 1/4 * * Example originally created with raylib 3.7, last time updated with raylib 3.7 * diff --git a/examples/textures/textures_raw_data.c b/examples/textures/textures_raw_data.c index 6fb41b143..51a50069f 100644 --- a/examples/textures/textures_raw_data.c +++ b/examples/textures/textures_raw_data.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Load textures from raw data * +* Example complexity rating: [★★★☆] 3/4 +* * NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) * * Example originally created with raylib 1.3, last time updated with raylib 3.5 diff --git a/examples/textures/textures_sprite_anim.c b/examples/textures/textures_sprite_anim.c index deb68216a..8b0378958 100644 --- a/examples/textures/textures_sprite_anim.c +++ b/examples/textures/textures_sprite_anim.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Sprite animation * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 1.3, last time updated with raylib 1.3 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/textures/textures_sprite_button.c b/examples/textures/textures_sprite_button.c index 5d0153b57..0f5a6940d 100644 --- a/examples/textures/textures_sprite_button.c +++ b/examples/textures/textures_sprite_button.c @@ -2,6 +2,8 @@ * * raylib [textures] example - sprite button * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 2.5, last time updated with raylib 2.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/textures/textures_sprite_explosion.c b/examples/textures/textures_sprite_explosion.c index a65426cb6..09839f8fa 100644 --- a/examples/textures/textures_sprite_explosion.c +++ b/examples/textures/textures_sprite_explosion.c @@ -2,6 +2,8 @@ * * raylib [textures] example - sprite explosion * +* Example complexity rating: [★★☆☆] 2/4 +* * Example originally created with raylib 2.5, last time updated with raylib 3.5 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/textures/textures_srcrec_dstrec.c b/examples/textures/textures_srcrec_dstrec.c index 035e30371..a3bd29af2 100644 --- a/examples/textures/textures_srcrec_dstrec.c +++ b/examples/textures/textures_srcrec_dstrec.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Texture source and destination rectangles * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 1.3, last time updated with raylib 1.3 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, diff --git a/examples/textures/textures_textured_curve.c b/examples/textures/textures_textured_curve.c index 6e4c53cff..86df6957a 100644 --- a/examples/textures/textures_textured_curve.c +++ b/examples/textures/textures_textured_curve.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Draw a texture along a segmented curve * +* Example complexity rating: [★★★☆] 3/4 +* * Example originally created with raylib 4.5, last time updated with raylib 4.5 * * Example contributed by Jeffery Myers and reviewed by Ramon Santamaria (@raysan5) diff --git a/examples/textures/textures_to_image.c b/examples/textures/textures_to_image.c index e1d88c4cd..39907103e 100644 --- a/examples/textures/textures_to_image.c +++ b/examples/textures/textures_to_image.c @@ -2,6 +2,8 @@ * * raylib [textures] example - Retrieve image data from texture: LoadImageFromTexture() * +* Example complexity rating: [★☆☆☆] 1/4 +* * NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) * * Example originally created with raylib 1.3, last time updated with raylib 4.0 diff --git a/logo/raylib.ico b/logo/raylib.ico index 0cedcc55c..8dd7bb7ad 100644 Binary files a/logo/raylib.ico and b/logo/raylib.ico differ diff --git a/logo/raylib_1024x1024.png b/logo/raylib_1024x1024.png index b855a6bf6..3930aeb79 100644 Binary files a/logo/raylib_1024x1024.png and b/logo/raylib_1024x1024.png differ diff --git a/logo/raylib_144x144.png b/logo/raylib_144x144.png index 7c533d2de..f89d90b23 100644 Binary files a/logo/raylib_144x144.png and b/logo/raylib_144x144.png differ diff --git a/parser/LICENSE b/parser/LICENSE index 7fc2d13b0..7ed4b8722 100644 --- a/parser/LICENSE +++ b/parser/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2021-2024 Ramon Santamaria (@raysan5) +Copyright (c) 2021-2025 Ramon Santamaria (@raysan5) This software is provided "as-is", without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. diff --git a/parser/README.md b/parser/README.md index 6616cdc51..86cdfdd5b 100644 --- a/parser/README.md +++ b/parser/README.md @@ -19,7 +19,7 @@ Check `raylib_parser.c` for details about those structs. // // // more info and bugs-report: github.com/raysan5/raylib/parser // // // -// Copyright (c) 2021-2024 Ramon Santamaria (@raysan5) // +// Copyright (c) 2021-2025 Ramon Santamaria (@raysan5) // // // ////////////////////////////////////////////////////////////////////////////////// diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json index 37b0a16a6..0044de007 100644 --- a/parser/output/raylib_api.json +++ b/parser/output/raylib_api.json @@ -15,7 +15,7 @@ { "name": "RAYLIB_VERSION_MINOR", "type": "INT", - "value": 5, + "value": 6, "description": "" }, { @@ -27,7 +27,7 @@ { "name": "RAYLIB_VERSION", "type": "STRING", - "value": "5.5", + "value": "5.6-dev", "description": "" }, { @@ -2543,6 +2543,11 @@ "name": "SHADER_LOC_BONE_MATRICES", "value": 28, "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)" }, { - "name": "SHADER_UNIFORM_SAMPLER2D", + "name": "SHADER_UNIFORM_UINT", "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" } ] @@ -3520,6 +3545,11 @@ "description": "Get clipboard text content", "returnType": "const char *" }, + { + "name": "GetClipboardImage", + "description": "Get clipboard image content", + "returnType": "Image" + }, { "name": "EnableEventWaiting", "description": "Enable waiting for events on EndDrawing(), no automatic event polling", @@ -4876,6 +4906,17 @@ "description": "Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty", "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", "description": "Set a custom key to exit program (default is ESC)", @@ -9634,10 +9675,10 @@ { "name": "TextJoin", "description": "Join text strings with delimiter", - "returnType": "const char *", + "returnType": "char *", "params": [ { - "type": "const char **", + "type": "char **", "name": "textList" }, { @@ -9653,7 +9694,7 @@ { "name": "TextSplit", "description": "Split text into multiple strings", - "returnType": "const char **", + "returnType": "char **", "params": [ { "type": "const char *", @@ -9706,7 +9747,7 @@ { "name": "TextToUpper", "description": "Get upper case version of provided string", - "returnType": "const char *", + "returnType": "char *", "params": [ { "type": "const char *", @@ -9717,7 +9758,7 @@ { "name": "TextToLower", "description": "Get lower case version of provided string", - "returnType": "const char *", + "returnType": "char *", "params": [ { "type": "const char *", @@ -9728,7 +9769,7 @@ { "name": "TextToPascal", "description": "Get Pascal case notation version of provided string", - "returnType": "const char *", + "returnType": "char *", "params": [ { "type": "const char *", @@ -9739,7 +9780,7 @@ { "name": "TextToSnake", "description": "Get Snake case notation version of provided string", - "returnType": "const char *", + "returnType": "char *", "params": [ { "type": "const char *", @@ -9750,7 +9791,7 @@ { "name": "TextToCamel", "description": "Get Camel case notation version of provided string", - "returnType": "const char *", + "returnType": "char *", "params": [ { "type": "const char *", @@ -9760,7 +9801,7 @@ }, { "name": "TextToInteger", - "description": "Get integer value from text (negative values not supported)", + "description": "Get integer value from text", "returnType": "int", "params": [ { @@ -9771,7 +9812,7 @@ }, { "name": "TextToFloat", - "description": "Get float value from text (negative values not supported)", + "description": "Get float value from text", "returnType": "float", "params": [ { @@ -11087,7 +11128,7 @@ ] }, { - "name": "UpdateModelAnimationBoneMatrices", + "name": "UpdateModelAnimationBones", "description": "Update model animation mesh bone matrices (GPU skinning)", "returnType": "void", "params": [ diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua index 934c08eb7..ccf61cb0b 100644 --- a/parser/output/raylib_api.lua +++ b/parser/output/raylib_api.lua @@ -15,7 +15,7 @@ return { { name = "RAYLIB_VERSION_MINOR", type = "INT", - value = 5, + value = 6, description = "" }, { @@ -27,7 +27,7 @@ return { { name = "RAYLIB_VERSION", type = "STRING", - value = "5.5", + value = "5.6-dev", description = "" }, { @@ -2543,6 +2543,11 @@ return { name = "SHADER_LOC_BONE_MATRICES", value = 28, 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)" }, { - name = "SHADER_UNIFORM_SAMPLER2D", + name = "SHADER_UNIFORM_UINT", 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" } } @@ -3397,6 +3422,11 @@ return { description = "Get clipboard text content", returnType = "const char *" }, + { + name = "GetClipboardImage", + description = "Get clipboard image content", + returnType = "Image" + }, { name = "EnableEventWaiting", description = "Enable waiting for events on EndDrawing(), no automatic event polling", @@ -4321,6 +4351,14 @@ return { description = "Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty", 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", description = "Set a custom key to exit program (default is ESC)", @@ -6853,9 +6891,9 @@ return { { name = "TextJoin", description = "Join text strings with delimiter", - returnType = "const char *", + returnType = "char *", params = { - {type = "const char **", name = "textList"}, + {type = "char **", name = "textList"}, {type = "int", name = "count"}, {type = "const char *", name = "delimiter"} } @@ -6863,7 +6901,7 @@ return { { name = "TextSplit", description = "Split text into multiple strings", - returnType = "const char **", + returnType = "char **", params = { {type = "const char *", name = "text"}, {type = "char", name = "delimiter"}, @@ -6892,7 +6930,7 @@ return { { name = "TextToUpper", description = "Get upper case version of provided string", - returnType = "const char *", + returnType = "char *", params = { {type = "const char *", name = "text"} } @@ -6900,7 +6938,7 @@ return { { name = "TextToLower", description = "Get lower case version of provided string", - returnType = "const char *", + returnType = "char *", params = { {type = "const char *", name = "text"} } @@ -6908,7 +6946,7 @@ return { { name = "TextToPascal", description = "Get Pascal case notation version of provided string", - returnType = "const char *", + returnType = "char *", params = { {type = "const char *", name = "text"} } @@ -6916,7 +6954,7 @@ return { { name = "TextToSnake", description = "Get Snake case notation version of provided string", - returnType = "const char *", + returnType = "char *", params = { {type = "const char *", name = "text"} } @@ -6924,14 +6962,14 @@ return { { name = "TextToCamel", description = "Get Camel case notation version of provided string", - returnType = "const char *", + returnType = "char *", params = { {type = "const char *", name = "text"} } }, { name = "TextToInteger", - description = "Get integer value from text (negative values not supported)", + description = "Get integer value from text", returnType = "int", params = { {type = "const char *", name = "text"} @@ -6939,7 +6977,7 @@ return { }, { name = "TextToFloat", - description = "Get float value from text (negative values not supported)", + description = "Get float value from text", returnType = "float", params = { {type = "const char *", name = "text"} @@ -7607,7 +7645,7 @@ return { } }, { - name = "UpdateModelAnimationBoneMatrices", + name = "UpdateModelAnimationBones", description = "Update model animation mesh bone matrices (GPU skinning)", returnType = "void", params = { diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt index 541b5caf3..896efbaff 100644 --- a/parser/output/raylib_api.txt +++ b/parser/output/raylib_api.txt @@ -14,7 +14,7 @@ Define 002: RAYLIB_VERSION_MAJOR Define 003: RAYLIB_VERSION_MINOR Name: RAYLIB_VERSION_MINOR Type: INT - Value: 5 + Value: 6 Description: Define 004: RAYLIB_VERSION_PATCH Name: RAYLIB_VERSION_PATCH @@ -24,7 +24,7 @@ Define 004: RAYLIB_VERSION_PATCH Define 005: RAYLIB_VERSION Name: RAYLIB_VERSION Type: STRING - Value: "5.5" + Value: "5.6-dev" Description: Define 006: __declspec(x) Name: __declspec(x) @@ -795,7 +795,7 @@ Enum 08: MaterialMapIndex (11 values) Value[MATERIAL_MAP_IRRADIANCE]: 8 Value[MATERIAL_MAP_PREFILTER]: 9 Value[MATERIAL_MAP_BRDF]: 10 -Enum 09: ShaderLocationIndex (29 values) +Enum 09: ShaderLocationIndex (30 values) Name: ShaderLocationIndex Description: Shader location index Value[SHADER_LOC_VERTEX_POSITION]: 0 @@ -827,7 +827,8 @@ Enum 09: ShaderLocationIndex (29 values) Value[SHADER_LOC_VERTEX_BONEIDS]: 26 Value[SHADER_LOC_VERTEX_BONEWEIGHTS]: 27 Value[SHADER_LOC_BONE_MATRICES]: 28 -Enum 10: ShaderUniformDataType (9 values) + Value[SHADER_LOC_VERTEX_INSTANCE_TX]: 29 +Enum 10: ShaderUniformDataType (13 values) Name: ShaderUniformDataType Description: Shader uniform data type Value[SHADER_UNIFORM_FLOAT]: 0 @@ -838,7 +839,11 @@ Enum 10: ShaderUniformDataType (9 values) Value[SHADER_UNIFORM_IVEC2]: 5 Value[SHADER_UNIFORM_IVEC3]: 6 Value[SHADER_UNIFORM_IVEC4]: 7 - Value[SHADER_UNIFORM_SAMPLER2D]: 8 + Value[SHADER_UNIFORM_UINT]: 8 + Value[SHADER_UNIFORM_UIVEC2]: 9 + Value[SHADER_UNIFORM_UIVEC3]: 10 + Value[SHADER_UNIFORM_UIVEC4]: 11 + Value[SHADER_UNIFORM_SAMPLER2D]: 12 Enum 11: ShaderAttributeDataType (4 values) Name: ShaderAttributeDataType Description: Shader attribute data types @@ -988,7 +993,7 @@ Callback 006: AudioCallback() (2 input parameters) Param[1]: bufferData (type: void *) Param[2]: frames (type: unsigned int) -Functions found: 580 +Functions found: 582 Function 001: InitWindow() (3 input parameters) Name: InitWindow @@ -1227,112 +1232,117 @@ Function 046: GetClipboardText() (0 input parameters) Return type: const char * Description: Get clipboard text content No input parameters -Function 047: EnableEventWaiting() (0 input parameters) +Function 047: GetClipboardImage() (0 input parameters) + Name: GetClipboardImage + Return type: Image + Description: Get clipboard image content + No input parameters +Function 048: EnableEventWaiting() (0 input parameters) Name: EnableEventWaiting Return type: void Description: Enable waiting for events on EndDrawing(), no automatic event polling No input parameters -Function 048: DisableEventWaiting() (0 input parameters) +Function 049: DisableEventWaiting() (0 input parameters) Name: DisableEventWaiting Return type: void Description: Disable waiting for events on EndDrawing(), automatic events polling No input parameters -Function 049: ShowCursor() (0 input parameters) +Function 050: ShowCursor() (0 input parameters) Name: ShowCursor Return type: void Description: Shows cursor No input parameters -Function 050: HideCursor() (0 input parameters) +Function 051: HideCursor() (0 input parameters) Name: HideCursor Return type: void Description: Hides cursor No input parameters -Function 051: IsCursorHidden() (0 input parameters) +Function 052: IsCursorHidden() (0 input parameters) Name: IsCursorHidden Return type: bool Description: Check if cursor is not visible No input parameters -Function 052: EnableCursor() (0 input parameters) +Function 053: EnableCursor() (0 input parameters) Name: EnableCursor Return type: void Description: Enables cursor (unlock cursor) No input parameters -Function 053: DisableCursor() (0 input parameters) +Function 054: DisableCursor() (0 input parameters) Name: DisableCursor Return type: void Description: Disables cursor (lock cursor) No input parameters -Function 054: IsCursorOnScreen() (0 input parameters) +Function 055: IsCursorOnScreen() (0 input parameters) Name: IsCursorOnScreen Return type: bool Description: Check if cursor is on the screen No input parameters -Function 055: ClearBackground() (1 input parameters) +Function 056: ClearBackground() (1 input parameters) Name: ClearBackground Return type: void Description: Set background color (framebuffer clear color) Param[1]: color (type: Color) -Function 056: BeginDrawing() (0 input parameters) +Function 057: BeginDrawing() (0 input parameters) Name: BeginDrawing Return type: void Description: Setup canvas (framebuffer) to start drawing No input parameters -Function 057: EndDrawing() (0 input parameters) +Function 058: EndDrawing() (0 input parameters) Name: EndDrawing Return type: void Description: End canvas drawing and swap buffers (double buffering) No input parameters -Function 058: BeginMode2D() (1 input parameters) +Function 059: BeginMode2D() (1 input parameters) Name: BeginMode2D Return type: void Description: Begin 2D mode with custom camera (2D) Param[1]: camera (type: Camera2D) -Function 059: EndMode2D() (0 input parameters) +Function 060: EndMode2D() (0 input parameters) Name: EndMode2D Return type: void Description: Ends 2D mode with custom camera No input parameters -Function 060: BeginMode3D() (1 input parameters) +Function 061: BeginMode3D() (1 input parameters) Name: BeginMode3D Return type: void Description: Begin 3D mode with custom camera (3D) Param[1]: camera (type: Camera3D) -Function 061: EndMode3D() (0 input parameters) +Function 062: EndMode3D() (0 input parameters) Name: EndMode3D Return type: void Description: Ends 3D mode and returns to default 2D orthographic mode No input parameters -Function 062: BeginTextureMode() (1 input parameters) +Function 063: BeginTextureMode() (1 input parameters) Name: BeginTextureMode Return type: void Description: Begin drawing to render texture Param[1]: target (type: RenderTexture2D) -Function 063: EndTextureMode() (0 input parameters) +Function 064: EndTextureMode() (0 input parameters) Name: EndTextureMode Return type: void Description: Ends drawing to render texture No input parameters -Function 064: BeginShaderMode() (1 input parameters) +Function 065: BeginShaderMode() (1 input parameters) Name: BeginShaderMode Return type: void Description: Begin custom shader drawing Param[1]: shader (type: Shader) -Function 065: EndShaderMode() (0 input parameters) +Function 066: EndShaderMode() (0 input parameters) Name: EndShaderMode Return type: void Description: End custom shader drawing (use default shader) No input parameters -Function 066: BeginBlendMode() (1 input parameters) +Function 067: BeginBlendMode() (1 input parameters) Name: BeginBlendMode Return type: void Description: Begin blending mode (alpha, additive, multiplied, subtract, custom) Param[1]: mode (type: int) -Function 067: EndBlendMode() (0 input parameters) +Function 068: EndBlendMode() (0 input parameters) Name: EndBlendMode Return type: void Description: End blending mode (reset to default: alpha blending) No input parameters -Function 068: BeginScissorMode() (4 input parameters) +Function 069: BeginScissorMode() (4 input parameters) Name: BeginScissorMode Return type: void Description: Begin scissor mode (define screen area for following drawing) @@ -1340,61 +1350,61 @@ Function 068: BeginScissorMode() (4 input parameters) Param[2]: y (type: int) Param[3]: width (type: int) Param[4]: height (type: int) -Function 069: EndScissorMode() (0 input parameters) +Function 070: EndScissorMode() (0 input parameters) Name: EndScissorMode Return type: void Description: End scissor mode No input parameters -Function 070: BeginVrStereoMode() (1 input parameters) +Function 071: BeginVrStereoMode() (1 input parameters) Name: BeginVrStereoMode Return type: void Description: Begin stereo rendering (requires VR simulator) Param[1]: config (type: VrStereoConfig) -Function 071: EndVrStereoMode() (0 input parameters) +Function 072: EndVrStereoMode() (0 input parameters) Name: EndVrStereoMode Return type: void Description: End stereo rendering (requires VR simulator) No input parameters -Function 072: LoadVrStereoConfig() (1 input parameters) +Function 073: LoadVrStereoConfig() (1 input parameters) Name: LoadVrStereoConfig Return type: VrStereoConfig Description: Load VR stereo config for VR simulator device parameters Param[1]: device (type: VrDeviceInfo) -Function 073: UnloadVrStereoConfig() (1 input parameters) +Function 074: UnloadVrStereoConfig() (1 input parameters) Name: UnloadVrStereoConfig Return type: void Description: Unload VR stereo config Param[1]: config (type: VrStereoConfig) -Function 074: LoadShader() (2 input parameters) +Function 075: LoadShader() (2 input parameters) Name: LoadShader Return type: Shader Description: Load shader from files and bind default locations Param[1]: vsFileName (type: const char *) Param[2]: fsFileName (type: const char *) -Function 075: LoadShaderFromMemory() (2 input parameters) +Function 076: LoadShaderFromMemory() (2 input parameters) Name: LoadShaderFromMemory Return type: Shader Description: Load shader from code strings and bind default locations Param[1]: vsCode (type: const char *) Param[2]: fsCode (type: const char *) -Function 076: IsShaderValid() (1 input parameters) +Function 077: IsShaderValid() (1 input parameters) Name: IsShaderValid Return type: bool Description: Check if a shader is valid (loaded on GPU) Param[1]: shader (type: Shader) -Function 077: GetShaderLocation() (2 input parameters) +Function 078: GetShaderLocation() (2 input parameters) Name: GetShaderLocation Return type: int Description: Get shader uniform location Param[1]: shader (type: Shader) Param[2]: uniformName (type: const char *) -Function 078: GetShaderLocationAttrib() (2 input parameters) +Function 079: GetShaderLocationAttrib() (2 input parameters) Name: GetShaderLocationAttrib Return type: int Description: Get shader attribute location Param[1]: shader (type: Shader) Param[2]: attribName (type: const char *) -Function 079: SetShaderValue() (4 input parameters) +Function 080: SetShaderValue() (4 input parameters) Name: SetShaderValue Return type: void Description: Set shader uniform value @@ -1402,7 +1412,7 @@ Function 079: SetShaderValue() (4 input parameters) Param[2]: locIndex (type: int) Param[3]: value (type: const void *) Param[4]: uniformType (type: int) -Function 080: SetShaderValueV() (5 input parameters) +Function 081: SetShaderValueV() (5 input parameters) Name: SetShaderValueV Return type: void Description: Set shader uniform value vector @@ -1411,32 +1421,32 @@ Function 080: SetShaderValueV() (5 input parameters) Param[3]: value (type: const void *) Param[4]: uniformType (type: int) Param[5]: count (type: int) -Function 081: SetShaderValueMatrix() (3 input parameters) +Function 082: SetShaderValueMatrix() (3 input parameters) Name: SetShaderValueMatrix Return type: void Description: Set shader uniform value (matrix 4x4) Param[1]: shader (type: Shader) Param[2]: locIndex (type: int) Param[3]: mat (type: Matrix) -Function 082: SetShaderValueTexture() (3 input parameters) +Function 083: SetShaderValueTexture() (3 input parameters) Name: SetShaderValueTexture Return type: void Description: Set shader uniform value for texture (sampler2d) Param[1]: shader (type: Shader) Param[2]: locIndex (type: int) Param[3]: texture (type: Texture2D) -Function 083: UnloadShader() (1 input parameters) +Function 084: UnloadShader() (1 input parameters) Name: UnloadShader Return type: void Description: Unload shader from GPU memory (VRAM) Param[1]: shader (type: Shader) -Function 084: GetScreenToWorldRay() (2 input parameters) +Function 085: GetScreenToWorldRay() (2 input parameters) Name: GetScreenToWorldRay Return type: Ray Description: Get a ray trace from screen position (i.e mouse) Param[1]: position (type: Vector2) Param[2]: camera (type: Camera) -Function 085: GetScreenToWorldRayEx() (4 input parameters) +Function 086: GetScreenToWorldRayEx() (4 input parameters) Name: GetScreenToWorldRayEx Return type: Ray Description: Get a ray trace from screen position (i.e mouse) in a viewport @@ -1444,13 +1454,13 @@ Function 085: GetScreenToWorldRayEx() (4 input parameters) Param[2]: camera (type: Camera) Param[3]: width (type: int) Param[4]: height (type: int) -Function 086: GetWorldToScreen() (2 input parameters) +Function 087: GetWorldToScreen() (2 input parameters) Name: GetWorldToScreen Return type: Vector2 Description: Get the screen space position for a 3d world space position Param[1]: position (type: Vector3) Param[2]: camera (type: Camera) -Function 087: GetWorldToScreenEx() (4 input parameters) +Function 088: GetWorldToScreenEx() (4 input parameters) Name: GetWorldToScreenEx Return type: Vector2 Description: Get size position for a 3d world space position @@ -1458,490 +1468,495 @@ Function 087: GetWorldToScreenEx() (4 input parameters) Param[2]: camera (type: Camera) Param[3]: width (type: int) Param[4]: height (type: int) -Function 088: GetWorldToScreen2D() (2 input parameters) +Function 089: GetWorldToScreen2D() (2 input parameters) Name: GetWorldToScreen2D Return type: Vector2 Description: Get the screen space position for a 2d camera world space position Param[1]: position (type: Vector2) Param[2]: camera (type: Camera2D) -Function 089: GetScreenToWorld2D() (2 input parameters) +Function 090: GetScreenToWorld2D() (2 input parameters) Name: GetScreenToWorld2D Return type: Vector2 Description: Get the world space position for a 2d camera screen space position Param[1]: position (type: Vector2) Param[2]: camera (type: Camera2D) -Function 090: GetCameraMatrix() (1 input parameters) +Function 091: GetCameraMatrix() (1 input parameters) Name: GetCameraMatrix Return type: Matrix Description: Get camera transform matrix (view matrix) Param[1]: camera (type: Camera) -Function 091: GetCameraMatrix2D() (1 input parameters) +Function 092: GetCameraMatrix2D() (1 input parameters) Name: GetCameraMatrix2D Return type: Matrix Description: Get camera 2d transform matrix Param[1]: camera (type: Camera2D) -Function 092: SetTargetFPS() (1 input parameters) +Function 093: SetTargetFPS() (1 input parameters) Name: SetTargetFPS Return type: void Description: Set target FPS (maximum) Param[1]: fps (type: int) -Function 093: GetFrameTime() (0 input parameters) +Function 094: GetFrameTime() (0 input parameters) Name: GetFrameTime Return type: float Description: Get time in seconds for last frame drawn (delta time) No input parameters -Function 094: GetTime() (0 input parameters) +Function 095: GetTime() (0 input parameters) Name: GetTime Return type: double Description: Get elapsed time in seconds since InitWindow() No input parameters -Function 095: GetFPS() (0 input parameters) +Function 096: GetFPS() (0 input parameters) Name: GetFPS Return type: int Description: Get current FPS No input parameters -Function 096: SwapScreenBuffer() (0 input parameters) +Function 097: SwapScreenBuffer() (0 input parameters) Name: SwapScreenBuffer Return type: void Description: Swap back buffer with front buffer (screen drawing) No input parameters -Function 097: PollInputEvents() (0 input parameters) +Function 098: PollInputEvents() (0 input parameters) Name: PollInputEvents Return type: void Description: Register all input events No input parameters -Function 098: WaitTime() (1 input parameters) +Function 099: WaitTime() (1 input parameters) Name: WaitTime Return type: void Description: Wait for some time (halt program execution) Param[1]: seconds (type: double) -Function 099: SetRandomSeed() (1 input parameters) +Function 100: SetRandomSeed() (1 input parameters) Name: SetRandomSeed Return type: void Description: Set the seed for the random number generator Param[1]: seed (type: unsigned int) -Function 100: GetRandomValue() (2 input parameters) +Function 101: GetRandomValue() (2 input parameters) Name: GetRandomValue Return type: int Description: Get a random value between min and max (both included) Param[1]: min (type: int) Param[2]: max (type: int) -Function 101: LoadRandomSequence() (3 input parameters) +Function 102: LoadRandomSequence() (3 input parameters) Name: LoadRandomSequence Return type: int * Description: Load random values sequence, no values repeated Param[1]: count (type: unsigned int) Param[2]: min (type: int) Param[3]: max (type: int) -Function 102: UnloadRandomSequence() (1 input parameters) +Function 103: UnloadRandomSequence() (1 input parameters) Name: UnloadRandomSequence Return type: void Description: Unload random values sequence Param[1]: sequence (type: int *) -Function 103: TakeScreenshot() (1 input parameters) +Function 104: TakeScreenshot() (1 input parameters) Name: TakeScreenshot Return type: void Description: Takes a screenshot of current screen (filename extension defines format) Param[1]: fileName (type: const char *) -Function 104: SetConfigFlags() (1 input parameters) +Function 105: SetConfigFlags() (1 input parameters) Name: SetConfigFlags Return type: void Description: Setup init configuration flags (view FLAGS) Param[1]: flags (type: unsigned int) -Function 105: OpenURL() (1 input parameters) +Function 106: OpenURL() (1 input parameters) Name: OpenURL Return type: void Description: Open URL with default system browser (if available) Param[1]: url (type: const char *) -Function 106: TraceLog() (3 input parameters) +Function 107: TraceLog() (3 input parameters) Name: TraceLog Return type: void Description: Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...) Param[1]: logLevel (type: int) Param[2]: text (type: const char *) Param[3]: args (type: ...) -Function 107: SetTraceLogLevel() (1 input parameters) +Function 108: SetTraceLogLevel() (1 input parameters) Name: SetTraceLogLevel Return type: void Description: Set the current threshold (minimum) log level Param[1]: logLevel (type: int) -Function 108: MemAlloc() (1 input parameters) +Function 109: MemAlloc() (1 input parameters) Name: MemAlloc Return type: void * Description: Internal memory allocator Param[1]: size (type: unsigned int) -Function 109: MemRealloc() (2 input parameters) +Function 110: MemRealloc() (2 input parameters) Name: MemRealloc Return type: void * Description: Internal memory reallocator Param[1]: ptr (type: void *) Param[2]: size (type: unsigned int) -Function 110: MemFree() (1 input parameters) +Function 111: MemFree() (1 input parameters) Name: MemFree Return type: void Description: Internal memory free Param[1]: ptr (type: void *) -Function 111: SetTraceLogCallback() (1 input parameters) +Function 112: SetTraceLogCallback() (1 input parameters) Name: SetTraceLogCallback Return type: void Description: Set custom trace log Param[1]: callback (type: TraceLogCallback) -Function 112: SetLoadFileDataCallback() (1 input parameters) +Function 113: SetLoadFileDataCallback() (1 input parameters) Name: SetLoadFileDataCallback Return type: void Description: Set custom file binary data loader Param[1]: callback (type: LoadFileDataCallback) -Function 113: SetSaveFileDataCallback() (1 input parameters) +Function 114: SetSaveFileDataCallback() (1 input parameters) Name: SetSaveFileDataCallback Return type: void Description: Set custom file binary data saver Param[1]: callback (type: SaveFileDataCallback) -Function 114: SetLoadFileTextCallback() (1 input parameters) +Function 115: SetLoadFileTextCallback() (1 input parameters) Name: SetLoadFileTextCallback Return type: void Description: Set custom file text data loader Param[1]: callback (type: LoadFileTextCallback) -Function 115: SetSaveFileTextCallback() (1 input parameters) +Function 116: SetSaveFileTextCallback() (1 input parameters) Name: SetSaveFileTextCallback Return type: void Description: Set custom file text data saver Param[1]: callback (type: SaveFileTextCallback) -Function 116: LoadFileData() (2 input parameters) +Function 117: LoadFileData() (2 input parameters) Name: LoadFileData Return type: unsigned char * Description: Load file data as byte array (read) Param[1]: fileName (type: const char *) Param[2]: dataSize (type: int *) -Function 117: UnloadFileData() (1 input parameters) +Function 118: UnloadFileData() (1 input parameters) Name: UnloadFileData Return type: void Description: Unload file data allocated by LoadFileData() Param[1]: data (type: unsigned char *) -Function 118: SaveFileData() (3 input parameters) +Function 119: SaveFileData() (3 input parameters) Name: SaveFileData Return type: bool Description: Save data to file from byte array (write), returns true on success Param[1]: fileName (type: const char *) Param[2]: data (type: void *) Param[3]: dataSize (type: int) -Function 119: ExportDataAsCode() (3 input parameters) +Function 120: ExportDataAsCode() (3 input parameters) Name: ExportDataAsCode Return type: bool Description: Export data to code (.h), returns true on success Param[1]: data (type: const unsigned char *) Param[2]: dataSize (type: int) Param[3]: fileName (type: const char *) -Function 120: LoadFileText() (1 input parameters) +Function 121: LoadFileText() (1 input parameters) Name: LoadFileText Return type: char * Description: Load text data from file (read), returns a '\0' terminated string Param[1]: fileName (type: const char *) -Function 121: UnloadFileText() (1 input parameters) +Function 122: UnloadFileText() (1 input parameters) Name: UnloadFileText Return type: void Description: Unload file text data allocated by LoadFileText() Param[1]: text (type: char *) -Function 122: SaveFileText() (2 input parameters) +Function 123: SaveFileText() (2 input parameters) Name: SaveFileText Return type: bool Description: Save text data to file (write), string must be '\0' terminated, returns true on success Param[1]: fileName (type: const char *) Param[2]: text (type: char *) -Function 123: FileExists() (1 input parameters) +Function 124: FileExists() (1 input parameters) Name: FileExists Return type: bool Description: Check if file exists Param[1]: fileName (type: const char *) -Function 124: DirectoryExists() (1 input parameters) +Function 125: DirectoryExists() (1 input parameters) Name: DirectoryExists Return type: bool Description: Check if a directory path exists Param[1]: dirPath (type: const char *) -Function 125: IsFileExtension() (2 input parameters) +Function 126: IsFileExtension() (2 input parameters) Name: IsFileExtension Return type: bool Description: Check file extension (including point: .png, .wav) Param[1]: fileName (type: const char *) Param[2]: ext (type: const char *) -Function 126: GetFileLength() (1 input parameters) +Function 127: GetFileLength() (1 input parameters) Name: GetFileLength Return type: int Description: Get file length in bytes (NOTE: GetFileSize() conflicts with windows.h) Param[1]: fileName (type: const char *) -Function 127: GetFileExtension() (1 input parameters) +Function 128: GetFileExtension() (1 input parameters) Name: GetFileExtension Return type: const char * Description: Get pointer to extension for a filename string (includes dot: '.png') Param[1]: fileName (type: const char *) -Function 128: GetFileName() (1 input parameters) +Function 129: GetFileName() (1 input parameters) Name: GetFileName Return type: const char * Description: Get pointer to filename for a path string Param[1]: filePath (type: const char *) -Function 129: GetFileNameWithoutExt() (1 input parameters) +Function 130: GetFileNameWithoutExt() (1 input parameters) Name: GetFileNameWithoutExt Return type: const char * Description: Get filename string without extension (uses static string) Param[1]: filePath (type: const char *) -Function 130: GetDirectoryPath() (1 input parameters) +Function 131: GetDirectoryPath() (1 input parameters) Name: GetDirectoryPath Return type: const char * Description: Get full path for a given fileName with path (uses static string) Param[1]: filePath (type: const char *) -Function 131: GetPrevDirectoryPath() (1 input parameters) +Function 132: GetPrevDirectoryPath() (1 input parameters) Name: GetPrevDirectoryPath Return type: const char * Description: Get previous directory path for a given path (uses static string) Param[1]: dirPath (type: const char *) -Function 132: GetWorkingDirectory() (0 input parameters) +Function 133: GetWorkingDirectory() (0 input parameters) Name: GetWorkingDirectory Return type: const char * Description: Get current working directory (uses static string) No input parameters -Function 133: GetApplicationDirectory() (0 input parameters) +Function 134: GetApplicationDirectory() (0 input parameters) Name: GetApplicationDirectory Return type: const char * Description: Get the directory of the running application (uses static string) No input parameters -Function 134: MakeDirectory() (1 input parameters) +Function 135: MakeDirectory() (1 input parameters) Name: MakeDirectory Return type: int Description: Create directories (including full path requested), returns 0 on success Param[1]: dirPath (type: const char *) -Function 135: ChangeDirectory() (1 input parameters) +Function 136: ChangeDirectory() (1 input parameters) Name: ChangeDirectory Return type: bool Description: Change working directory, return true on success Param[1]: dir (type: const char *) -Function 136: IsPathFile() (1 input parameters) +Function 137: IsPathFile() (1 input parameters) Name: IsPathFile Return type: bool Description: Check if a given path is a file or a directory Param[1]: path (type: const char *) -Function 137: IsFileNameValid() (1 input parameters) +Function 138: IsFileNameValid() (1 input parameters) Name: IsFileNameValid Return type: bool Description: Check if fileName is valid for the platform/OS Param[1]: fileName (type: const char *) -Function 138: LoadDirectoryFiles() (1 input parameters) +Function 139: LoadDirectoryFiles() (1 input parameters) Name: LoadDirectoryFiles Return type: FilePathList Description: Load directory filepaths Param[1]: dirPath (type: const char *) -Function 139: LoadDirectoryFilesEx() (3 input parameters) +Function 140: LoadDirectoryFilesEx() (3 input parameters) Name: LoadDirectoryFilesEx Return type: FilePathList Description: Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result Param[1]: basePath (type: const char *) Param[2]: filter (type: const char *) Param[3]: scanSubdirs (type: bool) -Function 140: UnloadDirectoryFiles() (1 input parameters) +Function 141: UnloadDirectoryFiles() (1 input parameters) Name: UnloadDirectoryFiles Return type: void Description: Unload filepaths Param[1]: files (type: FilePathList) -Function 141: IsFileDropped() (0 input parameters) +Function 142: IsFileDropped() (0 input parameters) Name: IsFileDropped Return type: bool Description: Check if a file has been dropped into window No input parameters -Function 142: LoadDroppedFiles() (0 input parameters) +Function 143: LoadDroppedFiles() (0 input parameters) Name: LoadDroppedFiles Return type: FilePathList Description: Load dropped filepaths No input parameters -Function 143: UnloadDroppedFiles() (1 input parameters) +Function 144: UnloadDroppedFiles() (1 input parameters) Name: UnloadDroppedFiles Return type: void Description: Unload dropped filepaths Param[1]: files (type: FilePathList) -Function 144: GetFileModTime() (1 input parameters) +Function 145: GetFileModTime() (1 input parameters) Name: GetFileModTime Return type: long Description: Get file modification time (last write time) Param[1]: fileName (type: const char *) -Function 145: CompressData() (3 input parameters) +Function 146: CompressData() (3 input parameters) Name: CompressData Return type: unsigned char * Description: Compress data (DEFLATE algorithm), memory must be MemFree() Param[1]: data (type: const unsigned char *) Param[2]: dataSize (type: int) Param[3]: compDataSize (type: int *) -Function 146: DecompressData() (3 input parameters) +Function 147: DecompressData() (3 input parameters) Name: DecompressData Return type: unsigned char * Description: Decompress data (DEFLATE algorithm), memory must be MemFree() Param[1]: compData (type: const unsigned char *) Param[2]: compDataSize (type: int) Param[3]: dataSize (type: int *) -Function 147: EncodeDataBase64() (3 input parameters) +Function 148: EncodeDataBase64() (3 input parameters) Name: EncodeDataBase64 Return type: char * Description: Encode data to Base64 string, memory must be MemFree() Param[1]: data (type: const unsigned char *) Param[2]: dataSize (type: int) Param[3]: outputSize (type: int *) -Function 148: DecodeDataBase64() (2 input parameters) +Function 149: DecodeDataBase64() (2 input parameters) Name: DecodeDataBase64 Return type: unsigned char * Description: Decode Base64 string data, memory must be MemFree() Param[1]: data (type: const unsigned char *) Param[2]: outputSize (type: int *) -Function 149: ComputeCRC32() (2 input parameters) +Function 150: ComputeCRC32() (2 input parameters) Name: ComputeCRC32 Return type: unsigned int Description: Compute CRC32 hash code Param[1]: data (type: unsigned char *) Param[2]: dataSize (type: int) -Function 150: ComputeMD5() (2 input parameters) +Function 151: ComputeMD5() (2 input parameters) Name: ComputeMD5 Return type: unsigned int * Description: Compute MD5 hash code, returns static int[4] (16 bytes) Param[1]: data (type: unsigned char *) Param[2]: dataSize (type: int) -Function 151: ComputeSHA1() (2 input parameters) +Function 152: ComputeSHA1() (2 input parameters) Name: ComputeSHA1 Return type: unsigned int * Description: Compute SHA1 hash code, returns static int[5] (20 bytes) Param[1]: data (type: unsigned char *) Param[2]: dataSize (type: int) -Function 152: LoadAutomationEventList() (1 input parameters) +Function 153: LoadAutomationEventList() (1 input parameters) Name: LoadAutomationEventList Return type: AutomationEventList Description: Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS Param[1]: fileName (type: const char *) -Function 153: UnloadAutomationEventList() (1 input parameters) +Function 154: UnloadAutomationEventList() (1 input parameters) Name: UnloadAutomationEventList Return type: void Description: Unload automation events list from file Param[1]: list (type: AutomationEventList) -Function 154: ExportAutomationEventList() (2 input parameters) +Function 155: ExportAutomationEventList() (2 input parameters) Name: ExportAutomationEventList Return type: bool Description: Export automation events list as text file Param[1]: list (type: AutomationEventList) Param[2]: fileName (type: const char *) -Function 155: SetAutomationEventList() (1 input parameters) +Function 156: SetAutomationEventList() (1 input parameters) Name: SetAutomationEventList Return type: void Description: Set automation event list to record to Param[1]: list (type: AutomationEventList *) -Function 156: SetAutomationEventBaseFrame() (1 input parameters) +Function 157: SetAutomationEventBaseFrame() (1 input parameters) Name: SetAutomationEventBaseFrame Return type: void Description: Set automation event internal base frame to start recording Param[1]: frame (type: int) -Function 157: StartAutomationEventRecording() (0 input parameters) +Function 158: StartAutomationEventRecording() (0 input parameters) Name: StartAutomationEventRecording Return type: void Description: Start recording automation events (AutomationEventList must be set) No input parameters -Function 158: StopAutomationEventRecording() (0 input parameters) +Function 159: StopAutomationEventRecording() (0 input parameters) Name: StopAutomationEventRecording Return type: void Description: Stop recording automation events No input parameters -Function 159: PlayAutomationEvent() (1 input parameters) +Function 160: PlayAutomationEvent() (1 input parameters) Name: PlayAutomationEvent Return type: void Description: Play a recorded automation event Param[1]: event (type: AutomationEvent) -Function 160: IsKeyPressed() (1 input parameters) +Function 161: IsKeyPressed() (1 input parameters) Name: IsKeyPressed Return type: bool Description: Check if a key has been pressed once Param[1]: key (type: int) -Function 161: IsKeyPressedRepeat() (1 input parameters) +Function 162: IsKeyPressedRepeat() (1 input parameters) Name: IsKeyPressedRepeat Return type: bool Description: Check if a key has been pressed again Param[1]: key (type: int) -Function 162: IsKeyDown() (1 input parameters) +Function 163: IsKeyDown() (1 input parameters) Name: IsKeyDown Return type: bool Description: Check if a key is being pressed Param[1]: key (type: int) -Function 163: IsKeyReleased() (1 input parameters) +Function 164: IsKeyReleased() (1 input parameters) Name: IsKeyReleased Return type: bool Description: Check if a key has been released once Param[1]: key (type: int) -Function 164: IsKeyUp() (1 input parameters) +Function 165: IsKeyUp() (1 input parameters) Name: IsKeyUp Return type: bool Description: Check if a key is NOT being pressed Param[1]: key (type: int) -Function 165: GetKeyPressed() (0 input parameters) +Function 166: GetKeyPressed() (0 input parameters) Name: GetKeyPressed Return type: int Description: Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty No input parameters -Function 166: GetCharPressed() (0 input parameters) +Function 167: GetCharPressed() (0 input parameters) Name: GetCharPressed Return type: int Description: Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty No input parameters -Function 167: SetExitKey() (1 input parameters) +Function 168: GetKeyName() (1 input parameters) + Name: GetKeyName + Return type: const char * + Description: Get name of a QWERTY key on the current keyboard layout (eg returns string 'q' for KEY_A on an AZERTY keyboard) + Param[1]: key (type: int) +Function 169: SetExitKey() (1 input parameters) Name: SetExitKey Return type: void Description: Set a custom key to exit program (default is ESC) Param[1]: key (type: int) -Function 168: IsGamepadAvailable() (1 input parameters) +Function 170: IsGamepadAvailable() (1 input parameters) Name: IsGamepadAvailable Return type: bool Description: Check if a gamepad is available Param[1]: gamepad (type: int) -Function 169: GetGamepadName() (1 input parameters) +Function 171: GetGamepadName() (1 input parameters) Name: GetGamepadName Return type: const char * Description: Get gamepad internal name id Param[1]: gamepad (type: int) -Function 170: IsGamepadButtonPressed() (2 input parameters) +Function 172: IsGamepadButtonPressed() (2 input parameters) Name: IsGamepadButtonPressed Return type: bool Description: Check if a gamepad button has been pressed once Param[1]: gamepad (type: int) Param[2]: button (type: int) -Function 171: IsGamepadButtonDown() (2 input parameters) +Function 173: IsGamepadButtonDown() (2 input parameters) Name: IsGamepadButtonDown Return type: bool Description: Check if a gamepad button is being pressed Param[1]: gamepad (type: int) Param[2]: button (type: int) -Function 172: IsGamepadButtonReleased() (2 input parameters) +Function 174: IsGamepadButtonReleased() (2 input parameters) Name: IsGamepadButtonReleased Return type: bool Description: Check if a gamepad button has been released once Param[1]: gamepad (type: int) Param[2]: button (type: int) -Function 173: IsGamepadButtonUp() (2 input parameters) +Function 175: IsGamepadButtonUp() (2 input parameters) Name: IsGamepadButtonUp Return type: bool Description: Check if a gamepad button is NOT being pressed Param[1]: gamepad (type: int) Param[2]: button (type: int) -Function 174: GetGamepadButtonPressed() (0 input parameters) +Function 176: GetGamepadButtonPressed() (0 input parameters) Name: GetGamepadButtonPressed Return type: int Description: Get the last gamepad button pressed No input parameters -Function 175: GetGamepadAxisCount() (1 input parameters) +Function 177: GetGamepadAxisCount() (1 input parameters) Name: GetGamepadAxisCount Return type: int Description: Get gamepad axis count for a gamepad Param[1]: gamepad (type: int) -Function 176: GetGamepadAxisMovement() (2 input parameters) +Function 178: GetGamepadAxisMovement() (2 input parameters) Name: GetGamepadAxisMovement Return type: float Description: Get axis movement value for a gamepad axis Param[1]: gamepad (type: int) Param[2]: axis (type: int) -Function 177: SetGamepadMappings() (1 input parameters) +Function 179: SetGamepadMappings() (1 input parameters) Name: SetGamepadMappings Return type: int Description: Set internal gamepad mappings (SDL_GameControllerDB) Param[1]: mappings (type: const char *) -Function 178: SetGamepadVibration() (4 input parameters) +Function 180: SetGamepadVibration() (4 input parameters) Name: SetGamepadVibration Return type: void Description: Set gamepad vibration for both motors (duration in seconds) @@ -1949,151 +1964,151 @@ Function 178: SetGamepadVibration() (4 input parameters) Param[2]: leftMotor (type: float) Param[3]: rightMotor (type: float) Param[4]: duration (type: float) -Function 179: IsMouseButtonPressed() (1 input parameters) +Function 181: IsMouseButtonPressed() (1 input parameters) Name: IsMouseButtonPressed Return type: bool Description: Check if a mouse button has been pressed once Param[1]: button (type: int) -Function 180: IsMouseButtonDown() (1 input parameters) +Function 182: IsMouseButtonDown() (1 input parameters) Name: IsMouseButtonDown Return type: bool Description: Check if a mouse button is being pressed Param[1]: button (type: int) -Function 181: IsMouseButtonReleased() (1 input parameters) +Function 183: IsMouseButtonReleased() (1 input parameters) Name: IsMouseButtonReleased Return type: bool Description: Check if a mouse button has been released once Param[1]: button (type: int) -Function 182: IsMouseButtonUp() (1 input parameters) +Function 184: IsMouseButtonUp() (1 input parameters) Name: IsMouseButtonUp Return type: bool Description: Check if a mouse button is NOT being pressed Param[1]: button (type: int) -Function 183: GetMouseX() (0 input parameters) +Function 185: GetMouseX() (0 input parameters) Name: GetMouseX Return type: int Description: Get mouse position X No input parameters -Function 184: GetMouseY() (0 input parameters) +Function 186: GetMouseY() (0 input parameters) Name: GetMouseY Return type: int Description: Get mouse position Y No input parameters -Function 185: GetMousePosition() (0 input parameters) +Function 187: GetMousePosition() (0 input parameters) Name: GetMousePosition Return type: Vector2 Description: Get mouse position XY No input parameters -Function 186: GetMouseDelta() (0 input parameters) +Function 188: GetMouseDelta() (0 input parameters) Name: GetMouseDelta Return type: Vector2 Description: Get mouse delta between frames No input parameters -Function 187: SetMousePosition() (2 input parameters) +Function 189: SetMousePosition() (2 input parameters) Name: SetMousePosition Return type: void Description: Set mouse position XY Param[1]: x (type: int) Param[2]: y (type: int) -Function 188: SetMouseOffset() (2 input parameters) +Function 190: SetMouseOffset() (2 input parameters) Name: SetMouseOffset Return type: void Description: Set mouse offset Param[1]: offsetX (type: int) Param[2]: offsetY (type: int) -Function 189: SetMouseScale() (2 input parameters) +Function 191: SetMouseScale() (2 input parameters) Name: SetMouseScale Return type: void Description: Set mouse scaling Param[1]: scaleX (type: float) Param[2]: scaleY (type: float) -Function 190: GetMouseWheelMove() (0 input parameters) +Function 192: GetMouseWheelMove() (0 input parameters) Name: GetMouseWheelMove Return type: float Description: Get mouse wheel movement for X or Y, whichever is larger No input parameters -Function 191: GetMouseWheelMoveV() (0 input parameters) +Function 193: GetMouseWheelMoveV() (0 input parameters) Name: GetMouseWheelMoveV Return type: Vector2 Description: Get mouse wheel movement for both X and Y No input parameters -Function 192: SetMouseCursor() (1 input parameters) +Function 194: SetMouseCursor() (1 input parameters) Name: SetMouseCursor Return type: void Description: Set mouse cursor Param[1]: cursor (type: int) -Function 193: GetTouchX() (0 input parameters) +Function 195: GetTouchX() (0 input parameters) Name: GetTouchX Return type: int Description: Get touch position X for touch point 0 (relative to screen size) No input parameters -Function 194: GetTouchY() (0 input parameters) +Function 196: GetTouchY() (0 input parameters) Name: GetTouchY Return type: int Description: Get touch position Y for touch point 0 (relative to screen size) No input parameters -Function 195: GetTouchPosition() (1 input parameters) +Function 197: GetTouchPosition() (1 input parameters) Name: GetTouchPosition Return type: Vector2 Description: Get touch position XY for a touch point index (relative to screen size) Param[1]: index (type: int) -Function 196: GetTouchPointId() (1 input parameters) +Function 198: GetTouchPointId() (1 input parameters) Name: GetTouchPointId Return type: int Description: Get touch point identifier for given index Param[1]: index (type: int) -Function 197: GetTouchPointCount() (0 input parameters) +Function 199: GetTouchPointCount() (0 input parameters) Name: GetTouchPointCount Return type: int Description: Get number of touch points No input parameters -Function 198: SetGesturesEnabled() (1 input parameters) +Function 200: SetGesturesEnabled() (1 input parameters) Name: SetGesturesEnabled Return type: void Description: Enable a set of gestures using flags Param[1]: flags (type: unsigned int) -Function 199: IsGestureDetected() (1 input parameters) +Function 201: IsGestureDetected() (1 input parameters) Name: IsGestureDetected Return type: bool Description: Check if a gesture have been detected Param[1]: gesture (type: unsigned int) -Function 200: GetGestureDetected() (0 input parameters) +Function 202: GetGestureDetected() (0 input parameters) Name: GetGestureDetected Return type: int Description: Get latest detected gesture No input parameters -Function 201: GetGestureHoldDuration() (0 input parameters) +Function 203: GetGestureHoldDuration() (0 input parameters) Name: GetGestureHoldDuration Return type: float Description: Get gesture hold time in seconds No input parameters -Function 202: GetGestureDragVector() (0 input parameters) +Function 204: GetGestureDragVector() (0 input parameters) Name: GetGestureDragVector Return type: Vector2 Description: Get gesture drag vector No input parameters -Function 203: GetGestureDragAngle() (0 input parameters) +Function 205: GetGestureDragAngle() (0 input parameters) Name: GetGestureDragAngle Return type: float Description: Get gesture drag angle No input parameters -Function 204: GetGesturePinchVector() (0 input parameters) +Function 206: GetGesturePinchVector() (0 input parameters) Name: GetGesturePinchVector Return type: Vector2 Description: Get gesture pinch delta No input parameters -Function 205: GetGesturePinchAngle() (0 input parameters) +Function 207: GetGesturePinchAngle() (0 input parameters) Name: GetGesturePinchAngle Return type: float Description: Get gesture pinch angle No input parameters -Function 206: UpdateCamera() (2 input parameters) +Function 208: UpdateCamera() (2 input parameters) Name: UpdateCamera Return type: void Description: Update camera position for selected mode Param[1]: camera (type: Camera *) Param[2]: mode (type: int) -Function 207: UpdateCameraPro() (4 input parameters) +Function 209: UpdateCameraPro() (4 input parameters) Name: UpdateCameraPro Return type: void Description: Update camera movement/rotation @@ -2101,36 +2116,36 @@ Function 207: UpdateCameraPro() (4 input parameters) Param[2]: movement (type: Vector3) Param[3]: rotation (type: Vector3) Param[4]: zoom (type: float) -Function 208: SetShapesTexture() (2 input parameters) +Function 210: SetShapesTexture() (2 input parameters) Name: SetShapesTexture Return type: void Description: Set texture and rectangle to be used on shapes drawing Param[1]: texture (type: Texture2D) Param[2]: source (type: Rectangle) -Function 209: GetShapesTexture() (0 input parameters) +Function 211: GetShapesTexture() (0 input parameters) Name: GetShapesTexture Return type: Texture2D Description: Get texture that is used for shapes drawing No input parameters -Function 210: GetShapesTextureRectangle() (0 input parameters) +Function 212: GetShapesTextureRectangle() (0 input parameters) Name: GetShapesTextureRectangle Return type: Rectangle Description: Get texture source rectangle that is used for shapes drawing No input parameters -Function 211: DrawPixel() (3 input parameters) +Function 213: DrawPixel() (3 input parameters) Name: DrawPixel Return type: void Description: Draw a pixel using geometry [Can be slow, use with care] Param[1]: posX (type: int) Param[2]: posY (type: int) Param[3]: color (type: Color) -Function 212: DrawPixelV() (2 input parameters) +Function 214: DrawPixelV() (2 input parameters) Name: DrawPixelV Return type: void Description: Draw a pixel using geometry (Vector version) [Can be slow, use with care] Param[1]: position (type: Vector2) Param[2]: color (type: Color) -Function 213: DrawLine() (5 input parameters) +Function 215: DrawLine() (5 input parameters) Name: DrawLine Return type: void Description: Draw a line @@ -2139,14 +2154,14 @@ Function 213: DrawLine() (5 input parameters) Param[3]: endPosX (type: int) Param[4]: endPosY (type: int) Param[5]: color (type: Color) -Function 214: DrawLineV() (3 input parameters) +Function 216: DrawLineV() (3 input parameters) Name: DrawLineV Return type: void Description: Draw a line (using gl lines) Param[1]: startPos (type: Vector2) Param[2]: endPos (type: Vector2) Param[3]: color (type: Color) -Function 215: DrawLineEx() (4 input parameters) +Function 217: DrawLineEx() (4 input parameters) Name: DrawLineEx Return type: void Description: Draw a line (using triangles/quads) @@ -2154,14 +2169,14 @@ Function 215: DrawLineEx() (4 input parameters) Param[2]: endPos (type: Vector2) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 216: DrawLineStrip() (3 input parameters) +Function 218: DrawLineStrip() (3 input parameters) Name: DrawLineStrip Return type: void Description: Draw lines sequence (using gl lines) Param[1]: points (type: const Vector2 *) Param[2]: pointCount (type: int) Param[3]: color (type: Color) -Function 217: DrawLineBezier() (4 input parameters) +Function 219: DrawLineBezier() (4 input parameters) Name: DrawLineBezier Return type: void Description: Draw line segment cubic-bezier in-out interpolation @@ -2169,7 +2184,7 @@ Function 217: DrawLineBezier() (4 input parameters) Param[2]: endPos (type: Vector2) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 218: DrawCircle() (4 input parameters) +Function 220: DrawCircle() (4 input parameters) Name: DrawCircle Return type: void Description: Draw a color-filled circle @@ -2177,7 +2192,7 @@ Function 218: DrawCircle() (4 input parameters) Param[2]: centerY (type: int) Param[3]: radius (type: float) Param[4]: color (type: Color) -Function 219: DrawCircleSector() (6 input parameters) +Function 221: DrawCircleSector() (6 input parameters) Name: DrawCircleSector Return type: void Description: Draw a piece of a circle @@ -2187,7 +2202,7 @@ Function 219: DrawCircleSector() (6 input parameters) Param[4]: endAngle (type: float) Param[5]: segments (type: int) Param[6]: color (type: Color) -Function 220: DrawCircleSectorLines() (6 input parameters) +Function 222: DrawCircleSectorLines() (6 input parameters) Name: DrawCircleSectorLines Return type: void Description: Draw circle sector outline @@ -2197,7 +2212,7 @@ Function 220: DrawCircleSectorLines() (6 input parameters) Param[4]: endAngle (type: float) Param[5]: segments (type: int) Param[6]: color (type: Color) -Function 221: DrawCircleGradient() (5 input parameters) +Function 223: DrawCircleGradient() (5 input parameters) Name: DrawCircleGradient Return type: void Description: Draw a gradient-filled circle @@ -2206,14 +2221,14 @@ Function 221: DrawCircleGradient() (5 input parameters) Param[3]: radius (type: float) Param[4]: inner (type: Color) Param[5]: outer (type: Color) -Function 222: DrawCircleV() (3 input parameters) +Function 224: DrawCircleV() (3 input parameters) Name: DrawCircleV Return type: void Description: Draw a color-filled circle (Vector version) Param[1]: center (type: Vector2) Param[2]: radius (type: float) Param[3]: color (type: Color) -Function 223: DrawCircleLines() (4 input parameters) +Function 225: DrawCircleLines() (4 input parameters) Name: DrawCircleLines Return type: void Description: Draw circle outline @@ -2221,14 +2236,14 @@ Function 223: DrawCircleLines() (4 input parameters) Param[2]: centerY (type: int) Param[3]: radius (type: float) Param[4]: color (type: Color) -Function 224: DrawCircleLinesV() (3 input parameters) +Function 226: DrawCircleLinesV() (3 input parameters) Name: DrawCircleLinesV Return type: void Description: Draw circle outline (Vector version) Param[1]: center (type: Vector2) Param[2]: radius (type: float) Param[3]: color (type: Color) -Function 225: DrawEllipse() (5 input parameters) +Function 227: DrawEllipse() (5 input parameters) Name: DrawEllipse Return type: void Description: Draw ellipse @@ -2237,7 +2252,7 @@ Function 225: DrawEllipse() (5 input parameters) Param[3]: radiusH (type: float) Param[4]: radiusV (type: float) Param[5]: color (type: Color) -Function 226: DrawEllipseLines() (5 input parameters) +Function 228: DrawEllipseLines() (5 input parameters) Name: DrawEllipseLines Return type: void Description: Draw ellipse outline @@ -2246,7 +2261,7 @@ Function 226: DrawEllipseLines() (5 input parameters) Param[3]: radiusH (type: float) Param[4]: radiusV (type: float) Param[5]: color (type: Color) -Function 227: DrawRing() (7 input parameters) +Function 229: DrawRing() (7 input parameters) Name: DrawRing Return type: void Description: Draw ring @@ -2257,7 +2272,7 @@ Function 227: DrawRing() (7 input parameters) Param[5]: endAngle (type: float) Param[6]: segments (type: int) Param[7]: color (type: Color) -Function 228: DrawRingLines() (7 input parameters) +Function 230: DrawRingLines() (7 input parameters) Name: DrawRingLines Return type: void Description: Draw ring outline @@ -2268,7 +2283,7 @@ Function 228: DrawRingLines() (7 input parameters) Param[5]: endAngle (type: float) Param[6]: segments (type: int) Param[7]: color (type: Color) -Function 229: DrawRectangle() (5 input parameters) +Function 231: DrawRectangle() (5 input parameters) Name: DrawRectangle Return type: void Description: Draw a color-filled rectangle @@ -2277,20 +2292,20 @@ Function 229: DrawRectangle() (5 input parameters) Param[3]: width (type: int) Param[4]: height (type: int) Param[5]: color (type: Color) -Function 230: DrawRectangleV() (3 input parameters) +Function 232: DrawRectangleV() (3 input parameters) Name: DrawRectangleV Return type: void Description: Draw a color-filled rectangle (Vector version) Param[1]: position (type: Vector2) Param[2]: size (type: Vector2) Param[3]: color (type: Color) -Function 231: DrawRectangleRec() (2 input parameters) +Function 233: DrawRectangleRec() (2 input parameters) Name: DrawRectangleRec Return type: void Description: Draw a color-filled rectangle Param[1]: rec (type: Rectangle) Param[2]: color (type: Color) -Function 232: DrawRectanglePro() (4 input parameters) +Function 234: DrawRectanglePro() (4 input parameters) Name: DrawRectanglePro Return type: void Description: Draw a color-filled rectangle with pro parameters @@ -2298,7 +2313,7 @@ Function 232: DrawRectanglePro() (4 input parameters) Param[2]: origin (type: Vector2) Param[3]: rotation (type: float) Param[4]: color (type: Color) -Function 233: DrawRectangleGradientV() (6 input parameters) +Function 235: DrawRectangleGradientV() (6 input parameters) Name: DrawRectangleGradientV Return type: void Description: Draw a vertical-gradient-filled rectangle @@ -2308,7 +2323,7 @@ Function 233: DrawRectangleGradientV() (6 input parameters) Param[4]: height (type: int) Param[5]: top (type: Color) Param[6]: bottom (type: Color) -Function 234: DrawRectangleGradientH() (6 input parameters) +Function 236: DrawRectangleGradientH() (6 input parameters) Name: DrawRectangleGradientH Return type: void Description: Draw a horizontal-gradient-filled rectangle @@ -2318,7 +2333,7 @@ Function 234: DrawRectangleGradientH() (6 input parameters) Param[4]: height (type: int) Param[5]: left (type: Color) Param[6]: right (type: Color) -Function 235: DrawRectangleGradientEx() (5 input parameters) +Function 237: DrawRectangleGradientEx() (5 input parameters) Name: DrawRectangleGradientEx Return type: void Description: Draw a gradient-filled rectangle with custom vertex colors @@ -2327,7 +2342,7 @@ Function 235: DrawRectangleGradientEx() (5 input parameters) Param[3]: bottomLeft (type: Color) Param[4]: topRight (type: Color) Param[5]: bottomRight (type: Color) -Function 236: DrawRectangleLines() (5 input parameters) +Function 238: DrawRectangleLines() (5 input parameters) Name: DrawRectangleLines Return type: void Description: Draw rectangle outline @@ -2336,14 +2351,14 @@ Function 236: DrawRectangleLines() (5 input parameters) Param[3]: width (type: int) Param[4]: height (type: int) Param[5]: color (type: Color) -Function 237: DrawRectangleLinesEx() (3 input parameters) +Function 239: DrawRectangleLinesEx() (3 input parameters) Name: DrawRectangleLinesEx Return type: void Description: Draw rectangle outline with extended parameters Param[1]: rec (type: Rectangle) Param[2]: lineThick (type: float) Param[3]: color (type: Color) -Function 238: DrawRectangleRounded() (4 input parameters) +Function 240: DrawRectangleRounded() (4 input parameters) Name: DrawRectangleRounded Return type: void Description: Draw rectangle with rounded edges @@ -2351,7 +2366,7 @@ Function 238: DrawRectangleRounded() (4 input parameters) Param[2]: roundness (type: float) Param[3]: segments (type: int) Param[4]: color (type: Color) -Function 239: DrawRectangleRoundedLines() (4 input parameters) +Function 241: DrawRectangleRoundedLines() (4 input parameters) Name: DrawRectangleRoundedLines Return type: void Description: Draw rectangle lines with rounded edges @@ -2359,7 +2374,7 @@ Function 239: DrawRectangleRoundedLines() (4 input parameters) Param[2]: roundness (type: float) Param[3]: segments (type: int) Param[4]: color (type: Color) -Function 240: DrawRectangleRoundedLinesEx() (5 input parameters) +Function 242: DrawRectangleRoundedLinesEx() (5 input parameters) Name: DrawRectangleRoundedLinesEx Return type: void Description: Draw rectangle with rounded edges outline @@ -2368,7 +2383,7 @@ Function 240: DrawRectangleRoundedLinesEx() (5 input parameters) Param[3]: segments (type: int) Param[4]: lineThick (type: float) Param[5]: color (type: Color) -Function 241: DrawTriangle() (4 input parameters) +Function 243: DrawTriangle() (4 input parameters) Name: DrawTriangle Return type: void Description: Draw a color-filled triangle (vertex in counter-clockwise order!) @@ -2376,7 +2391,7 @@ Function 241: DrawTriangle() (4 input parameters) Param[2]: v2 (type: Vector2) Param[3]: v3 (type: Vector2) Param[4]: color (type: Color) -Function 242: DrawTriangleLines() (4 input parameters) +Function 244: DrawTriangleLines() (4 input parameters) Name: DrawTriangleLines Return type: void Description: Draw triangle outline (vertex in counter-clockwise order!) @@ -2384,21 +2399,21 @@ Function 242: DrawTriangleLines() (4 input parameters) Param[2]: v2 (type: Vector2) Param[3]: v3 (type: Vector2) Param[4]: color (type: Color) -Function 243: DrawTriangleFan() (3 input parameters) +Function 245: DrawTriangleFan() (3 input parameters) Name: DrawTriangleFan Return type: void Description: Draw a triangle fan defined by points (first vertex is the center) Param[1]: points (type: const Vector2 *) Param[2]: pointCount (type: int) Param[3]: color (type: Color) -Function 244: DrawTriangleStrip() (3 input parameters) +Function 246: DrawTriangleStrip() (3 input parameters) Name: DrawTriangleStrip Return type: void Description: Draw a triangle strip defined by points Param[1]: points (type: const Vector2 *) Param[2]: pointCount (type: int) Param[3]: color (type: Color) -Function 245: DrawPoly() (5 input parameters) +Function 247: DrawPoly() (5 input parameters) Name: DrawPoly Return type: void Description: Draw a regular polygon (Vector version) @@ -2407,7 +2422,7 @@ Function 245: DrawPoly() (5 input parameters) Param[3]: radius (type: float) Param[4]: rotation (type: float) Param[5]: color (type: Color) -Function 246: DrawPolyLines() (5 input parameters) +Function 248: DrawPolyLines() (5 input parameters) Name: DrawPolyLines Return type: void Description: Draw a polygon outline of n sides @@ -2416,7 +2431,7 @@ Function 246: DrawPolyLines() (5 input parameters) Param[3]: radius (type: float) Param[4]: rotation (type: float) Param[5]: color (type: Color) -Function 247: DrawPolyLinesEx() (6 input parameters) +Function 249: DrawPolyLinesEx() (6 input parameters) Name: DrawPolyLinesEx Return type: void Description: Draw a polygon outline of n sides with extended parameters @@ -2426,7 +2441,7 @@ Function 247: DrawPolyLinesEx() (6 input parameters) Param[4]: rotation (type: float) Param[5]: lineThick (type: float) Param[6]: color (type: Color) -Function 248: DrawSplineLinear() (4 input parameters) +Function 250: DrawSplineLinear() (4 input parameters) Name: DrawSplineLinear Return type: void Description: Draw spline: Linear, minimum 2 points @@ -2434,7 +2449,7 @@ Function 248: DrawSplineLinear() (4 input parameters) Param[2]: pointCount (type: int) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 249: DrawSplineBasis() (4 input parameters) +Function 251: DrawSplineBasis() (4 input parameters) Name: DrawSplineBasis Return type: void Description: Draw spline: B-Spline, minimum 4 points @@ -2442,7 +2457,7 @@ Function 249: DrawSplineBasis() (4 input parameters) Param[2]: pointCount (type: int) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 250: DrawSplineCatmullRom() (4 input parameters) +Function 252: DrawSplineCatmullRom() (4 input parameters) Name: DrawSplineCatmullRom Return type: void Description: Draw spline: Catmull-Rom, minimum 4 points @@ -2450,7 +2465,7 @@ Function 250: DrawSplineCatmullRom() (4 input parameters) Param[2]: pointCount (type: int) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 251: DrawSplineBezierQuadratic() (4 input parameters) +Function 253: DrawSplineBezierQuadratic() (4 input parameters) Name: DrawSplineBezierQuadratic Return type: void Description: Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...] @@ -2458,7 +2473,7 @@ Function 251: DrawSplineBezierQuadratic() (4 input parameters) Param[2]: pointCount (type: int) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 252: DrawSplineBezierCubic() (4 input parameters) +Function 254: DrawSplineBezierCubic() (4 input parameters) Name: DrawSplineBezierCubic Return type: void Description: Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...] @@ -2466,7 +2481,7 @@ Function 252: DrawSplineBezierCubic() (4 input parameters) Param[2]: pointCount (type: int) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 253: DrawSplineSegmentLinear() (4 input parameters) +Function 255: DrawSplineSegmentLinear() (4 input parameters) Name: DrawSplineSegmentLinear Return type: void Description: Draw spline segment: Linear, 2 points @@ -2474,7 +2489,7 @@ Function 253: DrawSplineSegmentLinear() (4 input parameters) Param[2]: p2 (type: Vector2) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 254: DrawSplineSegmentBasis() (6 input parameters) +Function 256: DrawSplineSegmentBasis() (6 input parameters) Name: DrawSplineSegmentBasis Return type: void Description: Draw spline segment: B-Spline, 4 points @@ -2484,7 +2499,7 @@ Function 254: DrawSplineSegmentBasis() (6 input parameters) Param[4]: p4 (type: Vector2) Param[5]: thick (type: float) Param[6]: color (type: Color) -Function 255: DrawSplineSegmentCatmullRom() (6 input parameters) +Function 257: DrawSplineSegmentCatmullRom() (6 input parameters) Name: DrawSplineSegmentCatmullRom Return type: void Description: Draw spline segment: Catmull-Rom, 4 points @@ -2494,7 +2509,7 @@ Function 255: DrawSplineSegmentCatmullRom() (6 input parameters) Param[4]: p4 (type: Vector2) Param[5]: thick (type: float) Param[6]: color (type: Color) -Function 256: DrawSplineSegmentBezierQuadratic() (5 input parameters) +Function 258: DrawSplineSegmentBezierQuadratic() (5 input parameters) Name: DrawSplineSegmentBezierQuadratic Return type: void Description: Draw spline segment: Quadratic Bezier, 2 points, 1 control point @@ -2503,7 +2518,7 @@ Function 256: DrawSplineSegmentBezierQuadratic() (5 input parameters) Param[3]: p3 (type: Vector2) Param[4]: thick (type: float) Param[5]: color (type: Color) -Function 257: DrawSplineSegmentBezierCubic() (6 input parameters) +Function 259: DrawSplineSegmentBezierCubic() (6 input parameters) Name: DrawSplineSegmentBezierCubic Return type: void Description: Draw spline segment: Cubic Bezier, 2 points, 2 control points @@ -2513,14 +2528,14 @@ Function 257: DrawSplineSegmentBezierCubic() (6 input parameters) Param[4]: p4 (type: Vector2) Param[5]: thick (type: float) Param[6]: color (type: Color) -Function 258: GetSplinePointLinear() (3 input parameters) +Function 260: GetSplinePointLinear() (3 input parameters) Name: GetSplinePointLinear Return type: Vector2 Description: Get (evaluate) spline point: Linear Param[1]: startPos (type: Vector2) Param[2]: endPos (type: Vector2) Param[3]: t (type: float) -Function 259: GetSplinePointBasis() (5 input parameters) +Function 261: GetSplinePointBasis() (5 input parameters) Name: GetSplinePointBasis Return type: Vector2 Description: Get (evaluate) spline point: B-Spline @@ -2529,7 +2544,7 @@ Function 259: GetSplinePointBasis() (5 input parameters) Param[3]: p3 (type: Vector2) Param[4]: p4 (type: Vector2) Param[5]: t (type: float) -Function 260: GetSplinePointCatmullRom() (5 input parameters) +Function 262: GetSplinePointCatmullRom() (5 input parameters) Name: GetSplinePointCatmullRom Return type: Vector2 Description: Get (evaluate) spline point: Catmull-Rom @@ -2538,7 +2553,7 @@ Function 260: GetSplinePointCatmullRom() (5 input parameters) Param[3]: p3 (type: Vector2) Param[4]: p4 (type: Vector2) Param[5]: t (type: float) -Function 261: GetSplinePointBezierQuad() (4 input parameters) +Function 263: GetSplinePointBezierQuad() (4 input parameters) Name: GetSplinePointBezierQuad Return type: Vector2 Description: Get (evaluate) spline point: Quadratic Bezier @@ -2546,7 +2561,7 @@ Function 261: GetSplinePointBezierQuad() (4 input parameters) Param[2]: c2 (type: Vector2) Param[3]: p3 (type: Vector2) Param[4]: t (type: float) -Function 262: GetSplinePointBezierCubic() (5 input parameters) +Function 264: GetSplinePointBezierCubic() (5 input parameters) Name: GetSplinePointBezierCubic Return type: Vector2 Description: Get (evaluate) spline point: Cubic Bezier @@ -2555,13 +2570,13 @@ Function 262: GetSplinePointBezierCubic() (5 input parameters) Param[3]: c3 (type: Vector2) Param[4]: p4 (type: Vector2) Param[5]: t (type: float) -Function 263: CheckCollisionRecs() (2 input parameters) +Function 265: CheckCollisionRecs() (2 input parameters) Name: CheckCollisionRecs Return type: bool Description: Check collision between two rectangles Param[1]: rec1 (type: Rectangle) Param[2]: rec2 (type: Rectangle) -Function 264: CheckCollisionCircles() (4 input parameters) +Function 266: CheckCollisionCircles() (4 input parameters) Name: CheckCollisionCircles Return type: bool Description: Check collision between two circles @@ -2569,14 +2584,14 @@ Function 264: CheckCollisionCircles() (4 input parameters) Param[2]: radius1 (type: float) Param[3]: center2 (type: Vector2) Param[4]: radius2 (type: float) -Function 265: CheckCollisionCircleRec() (3 input parameters) +Function 267: CheckCollisionCircleRec() (3 input parameters) Name: CheckCollisionCircleRec Return type: bool Description: Check collision between circle and rectangle Param[1]: center (type: Vector2) Param[2]: radius (type: float) Param[3]: rec (type: Rectangle) -Function 266: CheckCollisionCircleLine() (4 input parameters) +Function 268: CheckCollisionCircleLine() (4 input parameters) Name: CheckCollisionCircleLine Return type: bool Description: Check if circle collides with a line created betweeen two points [p1] and [p2] @@ -2584,20 +2599,20 @@ Function 266: CheckCollisionCircleLine() (4 input parameters) Param[2]: radius (type: float) Param[3]: p1 (type: Vector2) Param[4]: p2 (type: Vector2) -Function 267: CheckCollisionPointRec() (2 input parameters) +Function 269: CheckCollisionPointRec() (2 input parameters) Name: CheckCollisionPointRec Return type: bool Description: Check if point is inside rectangle Param[1]: point (type: Vector2) Param[2]: rec (type: Rectangle) -Function 268: CheckCollisionPointCircle() (3 input parameters) +Function 270: CheckCollisionPointCircle() (3 input parameters) Name: CheckCollisionPointCircle Return type: bool Description: Check if point is inside circle Param[1]: point (type: Vector2) Param[2]: center (type: Vector2) Param[3]: radius (type: float) -Function 269: CheckCollisionPointTriangle() (4 input parameters) +Function 271: CheckCollisionPointTriangle() (4 input parameters) Name: CheckCollisionPointTriangle Return type: bool Description: Check if point is inside a triangle @@ -2605,7 +2620,7 @@ Function 269: CheckCollisionPointTriangle() (4 input parameters) Param[2]: p1 (type: Vector2) Param[3]: p2 (type: Vector2) Param[4]: p3 (type: Vector2) -Function 270: CheckCollisionPointLine() (4 input parameters) +Function 272: CheckCollisionPointLine() (4 input parameters) Name: CheckCollisionPointLine Return type: bool Description: Check if point belongs to line created between two points [p1] and [p2] with defined margin in pixels [threshold] @@ -2613,14 +2628,14 @@ Function 270: CheckCollisionPointLine() (4 input parameters) Param[2]: p1 (type: Vector2) Param[3]: p2 (type: Vector2) Param[4]: threshold (type: int) -Function 271: CheckCollisionPointPoly() (3 input parameters) +Function 273: CheckCollisionPointPoly() (3 input parameters) Name: CheckCollisionPointPoly Return type: bool Description: Check if point is within a polygon described by array of vertices Param[1]: point (type: Vector2) Param[2]: points (type: const Vector2 *) Param[3]: pointCount (type: int) -Function 272: CheckCollisionLines() (5 input parameters) +Function 274: CheckCollisionLines() (5 input parameters) Name: CheckCollisionLines Return type: bool Description: Check the collision between two lines defined by two points each, returns collision point by reference @@ -2629,18 +2644,18 @@ Function 272: CheckCollisionLines() (5 input parameters) Param[3]: startPos2 (type: Vector2) Param[4]: endPos2 (type: Vector2) Param[5]: collisionPoint (type: Vector2 *) -Function 273: GetCollisionRec() (2 input parameters) +Function 275: GetCollisionRec() (2 input parameters) Name: GetCollisionRec Return type: Rectangle Description: Get collision rectangle for two rectangles collision Param[1]: rec1 (type: Rectangle) Param[2]: rec2 (type: Rectangle) -Function 274: LoadImage() (1 input parameters) +Function 276: LoadImage() (1 input parameters) Name: LoadImage Return type: Image Description: Load image from file into CPU memory (RAM) Param[1]: fileName (type: const char *) -Function 275: LoadImageRaw() (5 input parameters) +Function 277: LoadImageRaw() (5 input parameters) Name: LoadImageRaw Return type: Image Description: Load image from RAW file data @@ -2649,13 +2664,13 @@ Function 275: LoadImageRaw() (5 input parameters) Param[3]: height (type: int) Param[4]: format (type: int) Param[5]: headerSize (type: int) -Function 276: LoadImageAnim() (2 input parameters) +Function 278: LoadImageAnim() (2 input parameters) Name: LoadImageAnim Return type: Image Description: Load image sequence from file (frames appended to image.data) Param[1]: fileName (type: const char *) Param[2]: frames (type: int *) -Function 277: LoadImageAnimFromMemory() (4 input parameters) +Function 279: LoadImageAnimFromMemory() (4 input parameters) Name: LoadImageAnimFromMemory Return type: Image Description: Load image sequence from memory buffer @@ -2663,60 +2678,60 @@ Function 277: LoadImageAnimFromMemory() (4 input parameters) Param[2]: fileData (type: const unsigned char *) Param[3]: dataSize (type: int) Param[4]: frames (type: int *) -Function 278: LoadImageFromMemory() (3 input parameters) +Function 280: LoadImageFromMemory() (3 input parameters) Name: LoadImageFromMemory Return type: Image Description: Load image from memory buffer, fileType refers to extension: i.e. '.png' Param[1]: fileType (type: const char *) Param[2]: fileData (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 279: LoadImageFromTexture() (1 input parameters) +Function 281: LoadImageFromTexture() (1 input parameters) Name: LoadImageFromTexture Return type: Image Description: Load image from GPU texture data Param[1]: texture (type: Texture2D) -Function 280: LoadImageFromScreen() (0 input parameters) +Function 282: LoadImageFromScreen() (0 input parameters) Name: LoadImageFromScreen Return type: Image Description: Load image from screen buffer and (screenshot) No input parameters -Function 281: IsImageValid() (1 input parameters) +Function 283: IsImageValid() (1 input parameters) Name: IsImageValid Return type: bool Description: Check if an image is valid (data and parameters) Param[1]: image (type: Image) -Function 282: UnloadImage() (1 input parameters) +Function 284: UnloadImage() (1 input parameters) Name: UnloadImage Return type: void Description: Unload image from CPU memory (RAM) Param[1]: image (type: Image) -Function 283: ExportImage() (2 input parameters) +Function 285: ExportImage() (2 input parameters) Name: ExportImage Return type: bool Description: Export image data to file, returns true on success Param[1]: image (type: Image) Param[2]: fileName (type: const char *) -Function 284: ExportImageToMemory() (3 input parameters) +Function 286: ExportImageToMemory() (3 input parameters) Name: ExportImageToMemory Return type: unsigned char * Description: Export image to memory buffer Param[1]: image (type: Image) Param[2]: fileType (type: const char *) Param[3]: fileSize (type: int *) -Function 285: ExportImageAsCode() (2 input parameters) +Function 287: ExportImageAsCode() (2 input parameters) Name: ExportImageAsCode Return type: bool Description: Export image as code file defining an array of bytes, returns true on success Param[1]: image (type: Image) Param[2]: fileName (type: const char *) -Function 286: GenImageColor() (3 input parameters) +Function 288: GenImageColor() (3 input parameters) Name: GenImageColor Return type: Image Description: Generate image: plain color Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: color (type: Color) -Function 287: GenImageGradientLinear() (5 input parameters) +Function 289: GenImageGradientLinear() (5 input parameters) Name: GenImageGradientLinear Return type: Image Description: Generate image: linear gradient, direction in degrees [0..360], 0=Vertical gradient @@ -2725,7 +2740,7 @@ Function 287: GenImageGradientLinear() (5 input parameters) Param[3]: direction (type: int) Param[4]: start (type: Color) Param[5]: end (type: Color) -Function 288: GenImageGradientRadial() (5 input parameters) +Function 290: GenImageGradientRadial() (5 input parameters) Name: GenImageGradientRadial Return type: Image Description: Generate image: radial gradient @@ -2734,7 +2749,7 @@ Function 288: GenImageGradientRadial() (5 input parameters) Param[3]: density (type: float) Param[4]: inner (type: Color) Param[5]: outer (type: Color) -Function 289: GenImageGradientSquare() (5 input parameters) +Function 291: GenImageGradientSquare() (5 input parameters) Name: GenImageGradientSquare Return type: Image Description: Generate image: square gradient @@ -2743,7 +2758,7 @@ Function 289: GenImageGradientSquare() (5 input parameters) Param[3]: density (type: float) Param[4]: inner (type: Color) Param[5]: outer (type: Color) -Function 290: GenImageChecked() (6 input parameters) +Function 292: GenImageChecked() (6 input parameters) Name: GenImageChecked Return type: Image Description: Generate image: checked @@ -2753,14 +2768,14 @@ Function 290: GenImageChecked() (6 input parameters) Param[4]: checksY (type: int) Param[5]: col1 (type: Color) Param[6]: col2 (type: Color) -Function 291: GenImageWhiteNoise() (3 input parameters) +Function 293: GenImageWhiteNoise() (3 input parameters) Name: GenImageWhiteNoise Return type: Image Description: Generate image: white noise Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: factor (type: float) -Function 292: GenImagePerlinNoise() (5 input parameters) +Function 294: GenImagePerlinNoise() (5 input parameters) Name: GenImagePerlinNoise Return type: Image Description: Generate image: perlin noise @@ -2769,45 +2784,45 @@ Function 292: GenImagePerlinNoise() (5 input parameters) Param[3]: offsetX (type: int) Param[4]: offsetY (type: int) Param[5]: scale (type: float) -Function 293: GenImageCellular() (3 input parameters) +Function 295: GenImageCellular() (3 input parameters) Name: GenImageCellular Return type: Image Description: Generate image: cellular algorithm, bigger tileSize means bigger cells Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: tileSize (type: int) -Function 294: GenImageText() (3 input parameters) +Function 296: GenImageText() (3 input parameters) Name: GenImageText Return type: Image Description: Generate image: grayscale image from text data Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: text (type: const char *) -Function 295: ImageCopy() (1 input parameters) +Function 297: ImageCopy() (1 input parameters) Name: ImageCopy Return type: Image Description: Create an image duplicate (useful for transformations) Param[1]: image (type: Image) -Function 296: ImageFromImage() (2 input parameters) +Function 298: ImageFromImage() (2 input parameters) Name: ImageFromImage Return type: Image Description: Create an image from another image piece Param[1]: image (type: Image) Param[2]: rec (type: Rectangle) -Function 297: ImageFromChannel() (2 input parameters) +Function 299: ImageFromChannel() (2 input parameters) Name: ImageFromChannel Return type: Image Description: Create an image from a selected channel of another image (GRAYSCALE) Param[1]: image (type: Image) Param[2]: selectedChannel (type: int) -Function 298: ImageText() (3 input parameters) +Function 300: ImageText() (3 input parameters) Name: ImageText Return type: Image Description: Create an image from text (default font) Param[1]: text (type: const char *) Param[2]: fontSize (type: int) Param[3]: color (type: Color) -Function 299: ImageTextEx() (5 input parameters) +Function 301: ImageTextEx() (5 input parameters) Name: ImageTextEx Return type: Image Description: Create an image from text (custom sprite font) @@ -2816,76 +2831,76 @@ Function 299: ImageTextEx() (5 input parameters) Param[3]: fontSize (type: float) Param[4]: spacing (type: float) Param[5]: tint (type: Color) -Function 300: ImageFormat() (2 input parameters) +Function 302: ImageFormat() (2 input parameters) Name: ImageFormat Return type: void Description: Convert image data to desired format Param[1]: image (type: Image *) Param[2]: newFormat (type: int) -Function 301: ImageToPOT() (2 input parameters) +Function 303: ImageToPOT() (2 input parameters) Name: ImageToPOT Return type: void Description: Convert image to POT (power-of-two) Param[1]: image (type: Image *) Param[2]: fill (type: Color) -Function 302: ImageCrop() (2 input parameters) +Function 304: ImageCrop() (2 input parameters) Name: ImageCrop Return type: void Description: Crop an image to a defined rectangle Param[1]: image (type: Image *) Param[2]: crop (type: Rectangle) -Function 303: ImageAlphaCrop() (2 input parameters) +Function 305: ImageAlphaCrop() (2 input parameters) Name: ImageAlphaCrop Return type: void Description: Crop image depending on alpha value Param[1]: image (type: Image *) Param[2]: threshold (type: float) -Function 304: ImageAlphaClear() (3 input parameters) +Function 306: ImageAlphaClear() (3 input parameters) Name: ImageAlphaClear Return type: void Description: Clear alpha channel to desired color Param[1]: image (type: Image *) Param[2]: color (type: Color) Param[3]: threshold (type: float) -Function 305: ImageAlphaMask() (2 input parameters) +Function 307: ImageAlphaMask() (2 input parameters) Name: ImageAlphaMask Return type: void Description: Apply alpha mask to image Param[1]: image (type: Image *) Param[2]: alphaMask (type: Image) -Function 306: ImageAlphaPremultiply() (1 input parameters) +Function 308: ImageAlphaPremultiply() (1 input parameters) Name: ImageAlphaPremultiply Return type: void Description: Premultiply alpha channel Param[1]: image (type: Image *) -Function 307: ImageBlurGaussian() (2 input parameters) +Function 309: ImageBlurGaussian() (2 input parameters) Name: ImageBlurGaussian Return type: void Description: Apply Gaussian blur using a box blur approximation Param[1]: image (type: Image *) Param[2]: blurSize (type: int) -Function 308: ImageKernelConvolution() (3 input parameters) +Function 310: ImageKernelConvolution() (3 input parameters) Name: ImageKernelConvolution Return type: void Description: Apply custom square convolution kernel to image Param[1]: image (type: Image *) Param[2]: kernel (type: const float *) Param[3]: kernelSize (type: int) -Function 309: ImageResize() (3 input parameters) +Function 311: ImageResize() (3 input parameters) Name: ImageResize Return type: void Description: Resize image (Bicubic scaling algorithm) Param[1]: image (type: Image *) Param[2]: newWidth (type: int) Param[3]: newHeight (type: int) -Function 310: ImageResizeNN() (3 input parameters) +Function 312: ImageResizeNN() (3 input parameters) Name: ImageResizeNN Return type: void Description: Resize image (Nearest-Neighbor scaling algorithm) Param[1]: image (type: Image *) Param[2]: newWidth (type: int) Param[3]: newHeight (type: int) -Function 311: ImageResizeCanvas() (6 input parameters) +Function 313: ImageResizeCanvas() (6 input parameters) Name: ImageResizeCanvas Return type: void Description: Resize canvas and fill with color @@ -2895,12 +2910,12 @@ Function 311: ImageResizeCanvas() (6 input parameters) Param[4]: offsetX (type: int) Param[5]: offsetY (type: int) Param[6]: fill (type: Color) -Function 312: ImageMipmaps() (1 input parameters) +Function 314: ImageMipmaps() (1 input parameters) Name: ImageMipmaps Return type: void Description: Compute all mipmap levels for a provided image Param[1]: image (type: Image *) -Function 313: ImageDither() (5 input parameters) +Function 315: ImageDither() (5 input parameters) Name: ImageDither Return type: void Description: Dither image data to 16bpp or lower (Floyd-Steinberg dithering) @@ -2909,109 +2924,109 @@ Function 313: ImageDither() (5 input parameters) Param[3]: gBpp (type: int) Param[4]: bBpp (type: int) Param[5]: aBpp (type: int) -Function 314: ImageFlipVertical() (1 input parameters) +Function 316: ImageFlipVertical() (1 input parameters) Name: ImageFlipVertical Return type: void Description: Flip image vertically Param[1]: image (type: Image *) -Function 315: ImageFlipHorizontal() (1 input parameters) +Function 317: ImageFlipHorizontal() (1 input parameters) Name: ImageFlipHorizontal Return type: void Description: Flip image horizontally Param[1]: image (type: Image *) -Function 316: ImageRotate() (2 input parameters) +Function 318: ImageRotate() (2 input parameters) Name: ImageRotate Return type: void Description: Rotate image by input angle in degrees (-359 to 359) Param[1]: image (type: Image *) Param[2]: degrees (type: int) -Function 317: ImageRotateCW() (1 input parameters) +Function 319: ImageRotateCW() (1 input parameters) Name: ImageRotateCW Return type: void Description: Rotate image clockwise 90deg Param[1]: image (type: Image *) -Function 318: ImageRotateCCW() (1 input parameters) +Function 320: ImageRotateCCW() (1 input parameters) Name: ImageRotateCCW Return type: void Description: Rotate image counter-clockwise 90deg Param[1]: image (type: Image *) -Function 319: ImageColorTint() (2 input parameters) +Function 321: ImageColorTint() (2 input parameters) Name: ImageColorTint Return type: void Description: Modify image color: tint Param[1]: image (type: Image *) Param[2]: color (type: Color) -Function 320: ImageColorInvert() (1 input parameters) +Function 322: ImageColorInvert() (1 input parameters) Name: ImageColorInvert Return type: void Description: Modify image color: invert Param[1]: image (type: Image *) -Function 321: ImageColorGrayscale() (1 input parameters) +Function 323: ImageColorGrayscale() (1 input parameters) Name: ImageColorGrayscale Return type: void Description: Modify image color: grayscale Param[1]: image (type: Image *) -Function 322: ImageColorContrast() (2 input parameters) +Function 324: ImageColorContrast() (2 input parameters) Name: ImageColorContrast Return type: void Description: Modify image color: contrast (-100 to 100) Param[1]: image (type: Image *) Param[2]: contrast (type: float) -Function 323: ImageColorBrightness() (2 input parameters) +Function 325: ImageColorBrightness() (2 input parameters) Name: ImageColorBrightness Return type: void Description: Modify image color: brightness (-255 to 255) Param[1]: image (type: Image *) Param[2]: brightness (type: int) -Function 324: ImageColorReplace() (3 input parameters) +Function 326: ImageColorReplace() (3 input parameters) Name: ImageColorReplace Return type: void Description: Modify image color: replace color Param[1]: image (type: Image *) Param[2]: color (type: Color) Param[3]: replace (type: Color) -Function 325: LoadImageColors() (1 input parameters) +Function 327: LoadImageColors() (1 input parameters) Name: LoadImageColors Return type: Color * Description: Load color data from image as a Color array (RGBA - 32bit) Param[1]: image (type: Image) -Function 326: LoadImagePalette() (3 input parameters) +Function 328: LoadImagePalette() (3 input parameters) Name: LoadImagePalette Return type: Color * Description: Load colors palette from image as a Color array (RGBA - 32bit) Param[1]: image (type: Image) Param[2]: maxPaletteSize (type: int) Param[3]: colorCount (type: int *) -Function 327: UnloadImageColors() (1 input parameters) +Function 329: UnloadImageColors() (1 input parameters) Name: UnloadImageColors Return type: void Description: Unload color data loaded with LoadImageColors() Param[1]: colors (type: Color *) -Function 328: UnloadImagePalette() (1 input parameters) +Function 330: UnloadImagePalette() (1 input parameters) Name: UnloadImagePalette Return type: void Description: Unload colors palette loaded with LoadImagePalette() Param[1]: colors (type: Color *) -Function 329: GetImageAlphaBorder() (2 input parameters) +Function 331: GetImageAlphaBorder() (2 input parameters) Name: GetImageAlphaBorder Return type: Rectangle Description: Get image alpha border rectangle Param[1]: image (type: Image) Param[2]: threshold (type: float) -Function 330: GetImageColor() (3 input parameters) +Function 332: GetImageColor() (3 input parameters) Name: GetImageColor Return type: Color Description: Get image pixel color at (x, y) position Param[1]: image (type: Image) Param[2]: x (type: int) Param[3]: y (type: int) -Function 331: ImageClearBackground() (2 input parameters) +Function 333: ImageClearBackground() (2 input parameters) Name: ImageClearBackground Return type: void Description: Clear image background with given color Param[1]: dst (type: Image *) Param[2]: color (type: Color) -Function 332: ImageDrawPixel() (4 input parameters) +Function 334: ImageDrawPixel() (4 input parameters) Name: ImageDrawPixel Return type: void Description: Draw pixel within an image @@ -3019,14 +3034,14 @@ Function 332: ImageDrawPixel() (4 input parameters) Param[2]: posX (type: int) Param[3]: posY (type: int) Param[4]: color (type: Color) -Function 333: ImageDrawPixelV() (3 input parameters) +Function 335: ImageDrawPixelV() (3 input parameters) Name: ImageDrawPixelV Return type: void Description: Draw pixel within an image (Vector version) Param[1]: dst (type: Image *) Param[2]: position (type: Vector2) Param[3]: color (type: Color) -Function 334: ImageDrawLine() (6 input parameters) +Function 336: ImageDrawLine() (6 input parameters) Name: ImageDrawLine Return type: void Description: Draw line within an image @@ -3036,7 +3051,7 @@ Function 334: ImageDrawLine() (6 input parameters) Param[4]: endPosX (type: int) Param[5]: endPosY (type: int) Param[6]: color (type: Color) -Function 335: ImageDrawLineV() (4 input parameters) +Function 337: ImageDrawLineV() (4 input parameters) Name: ImageDrawLineV Return type: void Description: Draw line within an image (Vector version) @@ -3044,7 +3059,7 @@ Function 335: ImageDrawLineV() (4 input parameters) Param[2]: start (type: Vector2) Param[3]: end (type: Vector2) Param[4]: color (type: Color) -Function 336: ImageDrawLineEx() (5 input parameters) +Function 338: ImageDrawLineEx() (5 input parameters) Name: ImageDrawLineEx Return type: void Description: Draw a line defining thickness within an image @@ -3053,7 +3068,7 @@ Function 336: ImageDrawLineEx() (5 input parameters) Param[3]: end (type: Vector2) Param[4]: thick (type: int) Param[5]: color (type: Color) -Function 337: ImageDrawCircle() (5 input parameters) +Function 339: ImageDrawCircle() (5 input parameters) Name: ImageDrawCircle Return type: void Description: Draw a filled circle within an image @@ -3062,7 +3077,7 @@ Function 337: ImageDrawCircle() (5 input parameters) Param[3]: centerY (type: int) Param[4]: radius (type: int) Param[5]: color (type: Color) -Function 338: ImageDrawCircleV() (4 input parameters) +Function 340: ImageDrawCircleV() (4 input parameters) Name: ImageDrawCircleV Return type: void Description: Draw a filled circle within an image (Vector version) @@ -3070,7 +3085,7 @@ Function 338: ImageDrawCircleV() (4 input parameters) Param[2]: center (type: Vector2) Param[3]: radius (type: int) Param[4]: color (type: Color) -Function 339: ImageDrawCircleLines() (5 input parameters) +Function 341: ImageDrawCircleLines() (5 input parameters) Name: ImageDrawCircleLines Return type: void Description: Draw circle outline within an image @@ -3079,7 +3094,7 @@ Function 339: ImageDrawCircleLines() (5 input parameters) Param[3]: centerY (type: int) Param[4]: radius (type: int) Param[5]: color (type: Color) -Function 340: ImageDrawCircleLinesV() (4 input parameters) +Function 342: ImageDrawCircleLinesV() (4 input parameters) Name: ImageDrawCircleLinesV Return type: void Description: Draw circle outline within an image (Vector version) @@ -3087,7 +3102,7 @@ Function 340: ImageDrawCircleLinesV() (4 input parameters) Param[2]: center (type: Vector2) Param[3]: radius (type: int) Param[4]: color (type: Color) -Function 341: ImageDrawRectangle() (6 input parameters) +Function 343: ImageDrawRectangle() (6 input parameters) Name: ImageDrawRectangle Return type: void Description: Draw rectangle within an image @@ -3097,7 +3112,7 @@ Function 341: ImageDrawRectangle() (6 input parameters) Param[4]: width (type: int) Param[5]: height (type: int) Param[6]: color (type: Color) -Function 342: ImageDrawRectangleV() (4 input parameters) +Function 344: ImageDrawRectangleV() (4 input parameters) Name: ImageDrawRectangleV Return type: void Description: Draw rectangle within an image (Vector version) @@ -3105,14 +3120,14 @@ Function 342: ImageDrawRectangleV() (4 input parameters) Param[2]: position (type: Vector2) Param[3]: size (type: Vector2) Param[4]: color (type: Color) -Function 343: ImageDrawRectangleRec() (3 input parameters) +Function 345: ImageDrawRectangleRec() (3 input parameters) Name: ImageDrawRectangleRec Return type: void Description: Draw rectangle within an image Param[1]: dst (type: Image *) Param[2]: rec (type: Rectangle) Param[3]: color (type: Color) -Function 344: ImageDrawRectangleLines() (4 input parameters) +Function 346: ImageDrawRectangleLines() (4 input parameters) Name: ImageDrawRectangleLines Return type: void Description: Draw rectangle lines within an image @@ -3120,7 +3135,7 @@ Function 344: ImageDrawRectangleLines() (4 input parameters) Param[2]: rec (type: Rectangle) Param[3]: thick (type: int) Param[4]: color (type: Color) -Function 345: ImageDrawTriangle() (5 input parameters) +Function 347: ImageDrawTriangle() (5 input parameters) Name: ImageDrawTriangle Return type: void Description: Draw triangle within an image @@ -3129,7 +3144,7 @@ Function 345: ImageDrawTriangle() (5 input parameters) Param[3]: v2 (type: Vector2) Param[4]: v3 (type: Vector2) Param[5]: color (type: Color) -Function 346: ImageDrawTriangleEx() (7 input parameters) +Function 348: ImageDrawTriangleEx() (7 input parameters) Name: ImageDrawTriangleEx Return type: void Description: Draw triangle with interpolated colors within an image @@ -3140,7 +3155,7 @@ Function 346: ImageDrawTriangleEx() (7 input parameters) Param[5]: c1 (type: Color) Param[6]: c2 (type: Color) Param[7]: c3 (type: Color) -Function 347: ImageDrawTriangleLines() (5 input parameters) +Function 349: ImageDrawTriangleLines() (5 input parameters) Name: ImageDrawTriangleLines Return type: void Description: Draw triangle outline within an image @@ -3149,7 +3164,7 @@ Function 347: ImageDrawTriangleLines() (5 input parameters) Param[3]: v2 (type: Vector2) Param[4]: v3 (type: Vector2) Param[5]: color (type: Color) -Function 348: ImageDrawTriangleFan() (4 input parameters) +Function 350: ImageDrawTriangleFan() (4 input parameters) Name: ImageDrawTriangleFan Return type: void Description: Draw a triangle fan defined by points within an image (first vertex is the center) @@ -3157,7 +3172,7 @@ Function 348: ImageDrawTriangleFan() (4 input parameters) Param[2]: points (type: Vector2 *) Param[3]: pointCount (type: int) Param[4]: color (type: Color) -Function 349: ImageDrawTriangleStrip() (4 input parameters) +Function 351: ImageDrawTriangleStrip() (4 input parameters) Name: ImageDrawTriangleStrip Return type: void Description: Draw a triangle strip defined by points within an image @@ -3165,7 +3180,7 @@ Function 349: ImageDrawTriangleStrip() (4 input parameters) Param[2]: points (type: Vector2 *) Param[3]: pointCount (type: int) Param[4]: color (type: Color) -Function 350: ImageDraw() (5 input parameters) +Function 352: ImageDraw() (5 input parameters) Name: ImageDraw Return type: void Description: Draw a source image within a destination image (tint applied to source) @@ -3174,7 +3189,7 @@ Function 350: ImageDraw() (5 input parameters) Param[3]: srcRec (type: Rectangle) Param[4]: dstRec (type: Rectangle) Param[5]: tint (type: Color) -Function 351: ImageDrawText() (6 input parameters) +Function 353: ImageDrawText() (6 input parameters) Name: ImageDrawText Return type: void Description: Draw text (using default font) within an image (destination) @@ -3184,7 +3199,7 @@ Function 351: ImageDrawText() (6 input parameters) Param[4]: posY (type: int) Param[5]: fontSize (type: int) Param[6]: color (type: Color) -Function 352: ImageDrawTextEx() (7 input parameters) +Function 354: ImageDrawTextEx() (7 input parameters) Name: ImageDrawTextEx Return type: void Description: Draw text (custom sprite font) within an image (destination) @@ -3195,79 +3210,79 @@ Function 352: ImageDrawTextEx() (7 input parameters) Param[5]: fontSize (type: float) Param[6]: spacing (type: float) Param[7]: tint (type: Color) -Function 353: LoadTexture() (1 input parameters) +Function 355: LoadTexture() (1 input parameters) Name: LoadTexture Return type: Texture2D Description: Load texture from file into GPU memory (VRAM) Param[1]: fileName (type: const char *) -Function 354: LoadTextureFromImage() (1 input parameters) +Function 356: LoadTextureFromImage() (1 input parameters) Name: LoadTextureFromImage Return type: Texture2D Description: Load texture from image data Param[1]: image (type: Image) -Function 355: LoadTextureCubemap() (2 input parameters) +Function 357: LoadTextureCubemap() (2 input parameters) Name: LoadTextureCubemap Return type: TextureCubemap Description: Load cubemap from image, multiple image cubemap layouts supported Param[1]: image (type: Image) Param[2]: layout (type: int) -Function 356: LoadRenderTexture() (2 input parameters) +Function 358: LoadRenderTexture() (2 input parameters) Name: LoadRenderTexture Return type: RenderTexture2D Description: Load texture for rendering (framebuffer) Param[1]: width (type: int) Param[2]: height (type: int) -Function 357: IsTextureValid() (1 input parameters) +Function 359: IsTextureValid() (1 input parameters) Name: IsTextureValid Return type: bool Description: Check if a texture is valid (loaded in GPU) Param[1]: texture (type: Texture2D) -Function 358: UnloadTexture() (1 input parameters) +Function 360: UnloadTexture() (1 input parameters) Name: UnloadTexture Return type: void Description: Unload texture from GPU memory (VRAM) Param[1]: texture (type: Texture2D) -Function 359: IsRenderTextureValid() (1 input parameters) +Function 361: IsRenderTextureValid() (1 input parameters) Name: IsRenderTextureValid Return type: bool Description: Check if a render texture is valid (loaded in GPU) Param[1]: target (type: RenderTexture2D) -Function 360: UnloadRenderTexture() (1 input parameters) +Function 362: UnloadRenderTexture() (1 input parameters) Name: UnloadRenderTexture Return type: void Description: Unload render texture from GPU memory (VRAM) Param[1]: target (type: RenderTexture2D) -Function 361: UpdateTexture() (2 input parameters) +Function 363: UpdateTexture() (2 input parameters) Name: UpdateTexture Return type: void Description: Update GPU texture with new data Param[1]: texture (type: Texture2D) Param[2]: pixels (type: const void *) -Function 362: UpdateTextureRec() (3 input parameters) +Function 364: UpdateTextureRec() (3 input parameters) Name: UpdateTextureRec Return type: void Description: Update GPU texture rectangle with new data Param[1]: texture (type: Texture2D) Param[2]: rec (type: Rectangle) Param[3]: pixels (type: const void *) -Function 363: GenTextureMipmaps() (1 input parameters) +Function 365: GenTextureMipmaps() (1 input parameters) Name: GenTextureMipmaps Return type: void Description: Generate GPU mipmaps for a texture Param[1]: texture (type: Texture2D *) -Function 364: SetTextureFilter() (2 input parameters) +Function 366: SetTextureFilter() (2 input parameters) Name: SetTextureFilter Return type: void Description: Set texture scaling filter mode Param[1]: texture (type: Texture2D) Param[2]: filter (type: int) -Function 365: SetTextureWrap() (2 input parameters) +Function 367: SetTextureWrap() (2 input parameters) Name: SetTextureWrap Return type: void Description: Set texture wrapping mode Param[1]: texture (type: Texture2D) Param[2]: wrap (type: int) -Function 366: DrawTexture() (4 input parameters) +Function 368: DrawTexture() (4 input parameters) Name: DrawTexture Return type: void Description: Draw a Texture2D @@ -3275,14 +3290,14 @@ Function 366: DrawTexture() (4 input parameters) Param[2]: posX (type: int) Param[3]: posY (type: int) Param[4]: tint (type: Color) -Function 367: DrawTextureV() (3 input parameters) +Function 369: DrawTextureV() (3 input parameters) Name: DrawTextureV Return type: void Description: Draw a Texture2D with position defined as Vector2 Param[1]: texture (type: Texture2D) Param[2]: position (type: Vector2) Param[3]: tint (type: Color) -Function 368: DrawTextureEx() (5 input parameters) +Function 370: DrawTextureEx() (5 input parameters) Name: DrawTextureEx Return type: void Description: Draw a Texture2D with extended parameters @@ -3291,7 +3306,7 @@ Function 368: DrawTextureEx() (5 input parameters) Param[3]: rotation (type: float) Param[4]: scale (type: float) Param[5]: tint (type: Color) -Function 369: DrawTextureRec() (4 input parameters) +Function 371: DrawTextureRec() (4 input parameters) Name: DrawTextureRec Return type: void Description: Draw a part of a texture defined by a rectangle @@ -3299,7 +3314,7 @@ Function 369: DrawTextureRec() (4 input parameters) Param[2]: source (type: Rectangle) Param[3]: position (type: Vector2) Param[4]: tint (type: Color) -Function 370: DrawTexturePro() (6 input parameters) +Function 372: DrawTexturePro() (6 input parameters) Name: DrawTexturePro Return type: void Description: Draw a part of a texture defined by a rectangle with 'pro' parameters @@ -3309,7 +3324,7 @@ Function 370: DrawTexturePro() (6 input parameters) Param[4]: origin (type: Vector2) Param[5]: rotation (type: float) Param[6]: tint (type: Color) -Function 371: DrawTextureNPatch() (6 input parameters) +Function 373: DrawTextureNPatch() (6 input parameters) Name: DrawTextureNPatch Return type: void Description: Draws a texture (or part of it) that stretches or shrinks nicely @@ -3319,119 +3334,119 @@ Function 371: DrawTextureNPatch() (6 input parameters) Param[4]: origin (type: Vector2) Param[5]: rotation (type: float) Param[6]: tint (type: Color) -Function 372: ColorIsEqual() (2 input parameters) +Function 374: ColorIsEqual() (2 input parameters) Name: ColorIsEqual Return type: bool Description: Check if two colors are equal Param[1]: col1 (type: Color) Param[2]: col2 (type: Color) -Function 373: Fade() (2 input parameters) +Function 375: Fade() (2 input parameters) Name: Fade Return type: Color Description: Get color with alpha applied, alpha goes from 0.0f to 1.0f Param[1]: color (type: Color) Param[2]: alpha (type: float) -Function 374: ColorToInt() (1 input parameters) +Function 376: ColorToInt() (1 input parameters) Name: ColorToInt Return type: int Description: Get hexadecimal value for a Color (0xRRGGBBAA) Param[1]: color (type: Color) -Function 375: ColorNormalize() (1 input parameters) +Function 377: ColorNormalize() (1 input parameters) Name: ColorNormalize Return type: Vector4 Description: Get Color normalized as float [0..1] Param[1]: color (type: Color) -Function 376: ColorFromNormalized() (1 input parameters) +Function 378: ColorFromNormalized() (1 input parameters) Name: ColorFromNormalized Return type: Color Description: Get Color from normalized values [0..1] Param[1]: normalized (type: Vector4) -Function 377: ColorToHSV() (1 input parameters) +Function 379: ColorToHSV() (1 input parameters) Name: ColorToHSV Return type: Vector3 Description: Get HSV values for a Color, hue [0..360], saturation/value [0..1] Param[1]: color (type: Color) -Function 378: ColorFromHSV() (3 input parameters) +Function 380: ColorFromHSV() (3 input parameters) Name: ColorFromHSV Return type: Color Description: Get a Color from HSV values, hue [0..360], saturation/value [0..1] Param[1]: hue (type: float) Param[2]: saturation (type: float) Param[3]: value (type: float) -Function 379: ColorTint() (2 input parameters) +Function 381: ColorTint() (2 input parameters) Name: ColorTint Return type: Color Description: Get color multiplied with another color Param[1]: color (type: Color) Param[2]: tint (type: Color) -Function 380: ColorBrightness() (2 input parameters) +Function 382: ColorBrightness() (2 input parameters) Name: ColorBrightness Return type: Color Description: Get color with brightness correction, brightness factor goes from -1.0f to 1.0f Param[1]: color (type: Color) Param[2]: factor (type: float) -Function 381: ColorContrast() (2 input parameters) +Function 383: ColorContrast() (2 input parameters) Name: ColorContrast Return type: Color Description: Get color with contrast correction, contrast values between -1.0f and 1.0f Param[1]: color (type: Color) Param[2]: contrast (type: float) -Function 382: ColorAlpha() (2 input parameters) +Function 384: ColorAlpha() (2 input parameters) Name: ColorAlpha Return type: Color Description: Get color with alpha applied, alpha goes from 0.0f to 1.0f Param[1]: color (type: Color) Param[2]: alpha (type: float) -Function 383: ColorAlphaBlend() (3 input parameters) +Function 385: ColorAlphaBlend() (3 input parameters) Name: ColorAlphaBlend Return type: Color Description: Get src alpha-blended into dst color with tint Param[1]: dst (type: Color) Param[2]: src (type: Color) Param[3]: tint (type: Color) -Function 384: ColorLerp() (3 input parameters) +Function 386: ColorLerp() (3 input parameters) Name: ColorLerp Return type: Color Description: Get color lerp interpolation between two colors, factor [0.0f..1.0f] Param[1]: color1 (type: Color) Param[2]: color2 (type: Color) Param[3]: factor (type: float) -Function 385: GetColor() (1 input parameters) +Function 387: GetColor() (1 input parameters) Name: GetColor Return type: Color Description: Get Color structure from hexadecimal value Param[1]: hexValue (type: unsigned int) -Function 386: GetPixelColor() (2 input parameters) +Function 388: GetPixelColor() (2 input parameters) Name: GetPixelColor Return type: Color Description: Get Color from a source pixel pointer of certain format Param[1]: srcPtr (type: void *) Param[2]: format (type: int) -Function 387: SetPixelColor() (3 input parameters) +Function 389: SetPixelColor() (3 input parameters) Name: SetPixelColor Return type: void Description: Set color formatted into destination pixel pointer Param[1]: dstPtr (type: void *) Param[2]: color (type: Color) Param[3]: format (type: int) -Function 388: GetPixelDataSize() (3 input parameters) +Function 390: GetPixelDataSize() (3 input parameters) Name: GetPixelDataSize Return type: int Description: Get pixel data size in bytes for certain format Param[1]: width (type: int) Param[2]: height (type: int) Param[3]: format (type: int) -Function 389: GetFontDefault() (0 input parameters) +Function 391: GetFontDefault() (0 input parameters) Name: GetFontDefault Return type: Font Description: Get the default Font No input parameters -Function 390: LoadFont() (1 input parameters) +Function 392: LoadFont() (1 input parameters) Name: LoadFont Return type: Font Description: Load font from file into GPU memory (VRAM) Param[1]: fileName (type: const char *) -Function 391: LoadFontEx() (4 input parameters) +Function 393: LoadFontEx() (4 input parameters) Name: LoadFontEx Return type: Font Description: Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height @@ -3439,14 +3454,14 @@ Function 391: LoadFontEx() (4 input parameters) Param[2]: fontSize (type: int) Param[3]: codepoints (type: int *) Param[4]: codepointCount (type: int) -Function 392: LoadFontFromImage() (3 input parameters) +Function 394: LoadFontFromImage() (3 input parameters) Name: LoadFontFromImage Return type: Font Description: Load font from Image (XNA style) Param[1]: image (type: Image) Param[2]: key (type: Color) Param[3]: firstChar (type: int) -Function 393: LoadFontFromMemory() (6 input parameters) +Function 395: LoadFontFromMemory() (6 input parameters) Name: LoadFontFromMemory Return type: Font Description: Load font from memory buffer, fileType refers to extension: i.e. '.ttf' @@ -3456,12 +3471,12 @@ Function 393: LoadFontFromMemory() (6 input parameters) Param[4]: fontSize (type: int) Param[5]: codepoints (type: int *) Param[6]: codepointCount (type: int) -Function 394: IsFontValid() (1 input parameters) +Function 396: IsFontValid() (1 input parameters) Name: IsFontValid Return type: bool Description: Check if a font is valid (font data loaded, WARNING: GPU texture not checked) Param[1]: font (type: Font) -Function 395: LoadFontData() (6 input parameters) +Function 397: LoadFontData() (6 input parameters) Name: LoadFontData Return type: GlyphInfo * Description: Load font data for further use @@ -3471,7 +3486,7 @@ Function 395: LoadFontData() (6 input parameters) Param[4]: codepoints (type: int *) Param[5]: codepointCount (type: int) Param[6]: type (type: int) -Function 396: GenImageFontAtlas() (6 input parameters) +Function 398: GenImageFontAtlas() (6 input parameters) Name: GenImageFontAtlas Return type: Image Description: Generate image font atlas using chars info @@ -3481,30 +3496,30 @@ Function 396: GenImageFontAtlas() (6 input parameters) Param[4]: fontSize (type: int) Param[5]: padding (type: int) Param[6]: packMethod (type: int) -Function 397: UnloadFontData() (2 input parameters) +Function 399: UnloadFontData() (2 input parameters) Name: UnloadFontData Return type: void Description: Unload font chars info data (RAM) Param[1]: glyphs (type: GlyphInfo *) Param[2]: glyphCount (type: int) -Function 398: UnloadFont() (1 input parameters) +Function 400: UnloadFont() (1 input parameters) Name: UnloadFont Return type: void Description: Unload font from GPU memory (VRAM) Param[1]: font (type: Font) -Function 399: ExportFontAsCode() (2 input parameters) +Function 401: ExportFontAsCode() (2 input parameters) Name: ExportFontAsCode Return type: bool Description: Export font as code file, returns true on success Param[1]: font (type: Font) Param[2]: fileName (type: const char *) -Function 400: DrawFPS() (2 input parameters) +Function 402: DrawFPS() (2 input parameters) Name: DrawFPS Return type: void Description: Draw current FPS Param[1]: posX (type: int) Param[2]: posY (type: int) -Function 401: DrawText() (5 input parameters) +Function 403: DrawText() (5 input parameters) Name: DrawText Return type: void Description: Draw text (using default font) @@ -3513,7 +3528,7 @@ Function 401: DrawText() (5 input parameters) Param[3]: posY (type: int) Param[4]: fontSize (type: int) Param[5]: color (type: Color) -Function 402: DrawTextEx() (6 input parameters) +Function 404: DrawTextEx() (6 input parameters) Name: DrawTextEx Return type: void Description: Draw text using font and additional parameters @@ -3523,7 +3538,7 @@ Function 402: DrawTextEx() (6 input parameters) Param[4]: fontSize (type: float) Param[5]: spacing (type: float) Param[6]: tint (type: Color) -Function 403: DrawTextPro() (8 input parameters) +Function 405: DrawTextPro() (8 input parameters) Name: DrawTextPro Return type: void Description: Draw text using Font and pro parameters (rotation) @@ -3535,7 +3550,7 @@ Function 403: DrawTextPro() (8 input parameters) Param[6]: fontSize (type: float) Param[7]: spacing (type: float) Param[8]: tint (type: Color) -Function 404: DrawTextCodepoint() (5 input parameters) +Function 406: DrawTextCodepoint() (5 input parameters) Name: DrawTextCodepoint Return type: void Description: Draw one character (codepoint) @@ -3544,7 +3559,7 @@ Function 404: DrawTextCodepoint() (5 input parameters) Param[3]: position (type: Vector2) Param[4]: fontSize (type: float) Param[5]: tint (type: Color) -Function 405: DrawTextCodepoints() (7 input parameters) +Function 407: DrawTextCodepoints() (7 input parameters) Name: DrawTextCodepoints Return type: void Description: Draw multiple character (codepoint) @@ -3555,18 +3570,18 @@ Function 405: DrawTextCodepoints() (7 input parameters) Param[5]: fontSize (type: float) Param[6]: spacing (type: float) Param[7]: tint (type: Color) -Function 406: SetTextLineSpacing() (1 input parameters) +Function 408: SetTextLineSpacing() (1 input parameters) Name: SetTextLineSpacing Return type: void Description: Set vertical line spacing when drawing with line-breaks Param[1]: spacing (type: int) -Function 407: MeasureText() (2 input parameters) +Function 409: MeasureText() (2 input parameters) Name: MeasureText Return type: int Description: Measure string width for default font Param[1]: text (type: const char *) Param[2]: fontSize (type: int) -Function 408: MeasureTextEx() (4 input parameters) +Function 410: MeasureTextEx() (4 input parameters) Name: MeasureTextEx Return type: Vector2 Description: Measure string size for Font @@ -3574,195 +3589,195 @@ Function 408: MeasureTextEx() (4 input parameters) Param[2]: text (type: const char *) Param[3]: fontSize (type: float) Param[4]: spacing (type: float) -Function 409: GetGlyphIndex() (2 input parameters) +Function 411: GetGlyphIndex() (2 input parameters) Name: GetGlyphIndex Return type: int Description: Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found Param[1]: font (type: Font) Param[2]: codepoint (type: int) -Function 410: GetGlyphInfo() (2 input parameters) +Function 412: GetGlyphInfo() (2 input parameters) Name: GetGlyphInfo Return type: GlyphInfo Description: Get glyph font info data for a codepoint (unicode character), fallback to '?' if not found Param[1]: font (type: Font) Param[2]: codepoint (type: int) -Function 411: GetGlyphAtlasRec() (2 input parameters) +Function 413: GetGlyphAtlasRec() (2 input parameters) Name: GetGlyphAtlasRec Return type: Rectangle Description: Get glyph rectangle in font atlas for a codepoint (unicode character), fallback to '?' if not found Param[1]: font (type: Font) Param[2]: codepoint (type: int) -Function 412: LoadUTF8() (2 input parameters) +Function 414: LoadUTF8() (2 input parameters) Name: LoadUTF8 Return type: char * Description: Load UTF-8 text encoded from codepoints array Param[1]: codepoints (type: const int *) Param[2]: length (type: int) -Function 413: UnloadUTF8() (1 input parameters) +Function 415: UnloadUTF8() (1 input parameters) Name: UnloadUTF8 Return type: void Description: Unload UTF-8 text encoded from codepoints array Param[1]: text (type: char *) -Function 414: LoadCodepoints() (2 input parameters) +Function 416: LoadCodepoints() (2 input parameters) Name: LoadCodepoints Return type: int * Description: Load all codepoints from a UTF-8 text string, codepoints count returned by parameter Param[1]: text (type: const char *) Param[2]: count (type: int *) -Function 415: UnloadCodepoints() (1 input parameters) +Function 417: UnloadCodepoints() (1 input parameters) Name: UnloadCodepoints Return type: void Description: Unload codepoints data from memory Param[1]: codepoints (type: int *) -Function 416: GetCodepointCount() (1 input parameters) +Function 418: GetCodepointCount() (1 input parameters) Name: GetCodepointCount Return type: int Description: Get total number of codepoints in a UTF-8 encoded string Param[1]: text (type: const char *) -Function 417: GetCodepoint() (2 input parameters) +Function 419: GetCodepoint() (2 input parameters) Name: GetCodepoint Return type: int Description: Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure Param[1]: text (type: const char *) Param[2]: codepointSize (type: int *) -Function 418: GetCodepointNext() (2 input parameters) +Function 420: GetCodepointNext() (2 input parameters) Name: GetCodepointNext Return type: int Description: Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure Param[1]: text (type: const char *) Param[2]: codepointSize (type: int *) -Function 419: GetCodepointPrevious() (2 input parameters) +Function 421: GetCodepointPrevious() (2 input parameters) Name: GetCodepointPrevious Return type: int Description: Get previous codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure Param[1]: text (type: const char *) Param[2]: codepointSize (type: int *) -Function 420: CodepointToUTF8() (2 input parameters) +Function 422: CodepointToUTF8() (2 input parameters) Name: CodepointToUTF8 Return type: const char * Description: Encode one codepoint into UTF-8 byte array (array length returned as parameter) Param[1]: codepoint (type: int) Param[2]: utf8Size (type: int *) -Function 421: TextCopy() (2 input parameters) +Function 423: TextCopy() (2 input parameters) Name: TextCopy Return type: int Description: Copy one string to another, returns bytes copied Param[1]: dst (type: char *) Param[2]: src (type: const char *) -Function 422: TextIsEqual() (2 input parameters) +Function 424: TextIsEqual() (2 input parameters) Name: TextIsEqual Return type: bool Description: Check if two text string are equal Param[1]: text1 (type: const char *) Param[2]: text2 (type: const char *) -Function 423: TextLength() (1 input parameters) +Function 425: TextLength() (1 input parameters) Name: TextLength Return type: unsigned int Description: Get text length, checks for '\0' ending Param[1]: text (type: const char *) -Function 424: TextFormat() (2 input parameters) +Function 426: TextFormat() (2 input parameters) Name: TextFormat Return type: const char * Description: Text formatting with variables (sprintf() style) Param[1]: text (type: const char *) Param[2]: args (type: ...) -Function 425: TextSubtext() (3 input parameters) +Function 427: TextSubtext() (3 input parameters) Name: TextSubtext Return type: const char * Description: Get a piece of a text string Param[1]: text (type: const char *) Param[2]: position (type: int) Param[3]: length (type: int) -Function 426: TextReplace() (3 input parameters) +Function 428: TextReplace() (3 input parameters) Name: TextReplace Return type: char * Description: Replace text string (WARNING: memory must be freed!) Param[1]: text (type: const char *) Param[2]: replace (type: const char *) Param[3]: by (type: const char *) -Function 427: TextInsert() (3 input parameters) +Function 429: TextInsert() (3 input parameters) Name: TextInsert Return type: char * Description: Insert text in a position (WARNING: memory must be freed!) Param[1]: text (type: const char *) Param[2]: insert (type: const char *) Param[3]: position (type: int) -Function 428: TextJoin() (3 input parameters) +Function 430: TextJoin() (3 input parameters) Name: TextJoin - Return type: const char * + Return type: char * Description: Join text strings with delimiter - Param[1]: textList (type: const char **) + Param[1]: textList (type: char **) Param[2]: count (type: int) Param[3]: delimiter (type: const char *) -Function 429: TextSplit() (3 input parameters) +Function 431: TextSplit() (3 input parameters) Name: TextSplit - Return type: const char ** + Return type: char ** Description: Split text into multiple strings Param[1]: text (type: const char *) Param[2]: delimiter (type: char) Param[3]: count (type: int *) -Function 430: TextAppend() (3 input parameters) +Function 432: TextAppend() (3 input parameters) Name: TextAppend Return type: void Description: Append text at specific position and move cursor! Param[1]: text (type: char *) Param[2]: append (type: const char *) Param[3]: position (type: int *) -Function 431: TextFindIndex() (2 input parameters) +Function 433: TextFindIndex() (2 input parameters) Name: TextFindIndex Return type: int Description: Find first text occurrence within a string Param[1]: text (type: const char *) Param[2]: find (type: const char *) -Function 432: TextToUpper() (1 input parameters) +Function 434: TextToUpper() (1 input parameters) Name: TextToUpper - Return type: const char * + Return type: char * Description: Get upper case version of provided string Param[1]: text (type: const char *) -Function 433: TextToLower() (1 input parameters) +Function 435: TextToLower() (1 input parameters) Name: TextToLower - Return type: const char * + Return type: char * Description: Get lower case version of provided string Param[1]: text (type: const char *) -Function 434: TextToPascal() (1 input parameters) +Function 436: TextToPascal() (1 input parameters) Name: TextToPascal - Return type: const char * + Return type: char * Description: Get Pascal case notation version of provided string Param[1]: text (type: const char *) -Function 435: TextToSnake() (1 input parameters) +Function 437: TextToSnake() (1 input parameters) Name: TextToSnake - Return type: const char * + Return type: char * Description: Get Snake case notation version of provided string Param[1]: text (type: const char *) -Function 436: TextToCamel() (1 input parameters) +Function 438: TextToCamel() (1 input parameters) Name: TextToCamel - Return type: const char * + Return type: char * Description: Get Camel case notation version of provided string Param[1]: text (type: const char *) -Function 437: TextToInteger() (1 input parameters) +Function 439: TextToInteger() (1 input parameters) Name: TextToInteger Return type: int - Description: Get integer value from text (negative values not supported) + Description: Get integer value from text Param[1]: text (type: const char *) -Function 438: TextToFloat() (1 input parameters) +Function 440: TextToFloat() (1 input parameters) Name: TextToFloat Return type: float - Description: Get float value from text (negative values not supported) + Description: Get float value from text Param[1]: text (type: const char *) -Function 439: DrawLine3D() (3 input parameters) +Function 441: DrawLine3D() (3 input parameters) Name: DrawLine3D Return type: void Description: Draw a line in 3D world space Param[1]: startPos (type: Vector3) Param[2]: endPos (type: Vector3) Param[3]: color (type: Color) -Function 440: DrawPoint3D() (2 input parameters) +Function 442: DrawPoint3D() (2 input parameters) Name: DrawPoint3D Return type: void Description: Draw a point in 3D space, actually a small line Param[1]: position (type: Vector3) Param[2]: color (type: Color) -Function 441: DrawCircle3D() (5 input parameters) +Function 443: DrawCircle3D() (5 input parameters) Name: DrawCircle3D Return type: void Description: Draw a circle in 3D world space @@ -3771,7 +3786,7 @@ Function 441: DrawCircle3D() (5 input parameters) Param[3]: rotationAxis (type: Vector3) Param[4]: rotationAngle (type: float) Param[5]: color (type: Color) -Function 442: DrawTriangle3D() (4 input parameters) +Function 444: DrawTriangle3D() (4 input parameters) Name: DrawTriangle3D Return type: void Description: Draw a color-filled triangle (vertex in counter-clockwise order!) @@ -3779,14 +3794,14 @@ Function 442: DrawTriangle3D() (4 input parameters) Param[2]: v2 (type: Vector3) Param[3]: v3 (type: Vector3) Param[4]: color (type: Color) -Function 443: DrawTriangleStrip3D() (3 input parameters) +Function 445: DrawTriangleStrip3D() (3 input parameters) Name: DrawTriangleStrip3D Return type: void Description: Draw a triangle strip defined by points Param[1]: points (type: const Vector3 *) Param[2]: pointCount (type: int) Param[3]: color (type: Color) -Function 444: DrawCube() (5 input parameters) +Function 446: DrawCube() (5 input parameters) Name: DrawCube Return type: void Description: Draw cube @@ -3795,14 +3810,14 @@ Function 444: DrawCube() (5 input parameters) Param[3]: height (type: float) Param[4]: length (type: float) Param[5]: color (type: Color) -Function 445: DrawCubeV() (3 input parameters) +Function 447: DrawCubeV() (3 input parameters) Name: DrawCubeV Return type: void Description: Draw cube (Vector version) Param[1]: position (type: Vector3) Param[2]: size (type: Vector3) Param[3]: color (type: Color) -Function 446: DrawCubeWires() (5 input parameters) +Function 448: DrawCubeWires() (5 input parameters) Name: DrawCubeWires Return type: void Description: Draw cube wires @@ -3811,21 +3826,21 @@ Function 446: DrawCubeWires() (5 input parameters) Param[3]: height (type: float) Param[4]: length (type: float) Param[5]: color (type: Color) -Function 447: DrawCubeWiresV() (3 input parameters) +Function 449: DrawCubeWiresV() (3 input parameters) Name: DrawCubeWiresV Return type: void Description: Draw cube wires (Vector version) Param[1]: position (type: Vector3) Param[2]: size (type: Vector3) Param[3]: color (type: Color) -Function 448: DrawSphere() (3 input parameters) +Function 450: DrawSphere() (3 input parameters) Name: DrawSphere Return type: void Description: Draw sphere Param[1]: centerPos (type: Vector3) Param[2]: radius (type: float) Param[3]: color (type: Color) -Function 449: DrawSphereEx() (5 input parameters) +Function 451: DrawSphereEx() (5 input parameters) Name: DrawSphereEx Return type: void Description: Draw sphere with extended parameters @@ -3834,7 +3849,7 @@ Function 449: DrawSphereEx() (5 input parameters) Param[3]: rings (type: int) Param[4]: slices (type: int) Param[5]: color (type: Color) -Function 450: DrawSphereWires() (5 input parameters) +Function 452: DrawSphereWires() (5 input parameters) Name: DrawSphereWires Return type: void Description: Draw sphere wires @@ -3843,7 +3858,7 @@ Function 450: DrawSphereWires() (5 input parameters) Param[3]: rings (type: int) Param[4]: slices (type: int) Param[5]: color (type: Color) -Function 451: DrawCylinder() (6 input parameters) +Function 453: DrawCylinder() (6 input parameters) Name: DrawCylinder Return type: void Description: Draw a cylinder/cone @@ -3853,7 +3868,7 @@ Function 451: DrawCylinder() (6 input parameters) Param[4]: height (type: float) Param[5]: slices (type: int) Param[6]: color (type: Color) -Function 452: DrawCylinderEx() (6 input parameters) +Function 454: DrawCylinderEx() (6 input parameters) Name: DrawCylinderEx Return type: void Description: Draw a cylinder with base at startPos and top at endPos @@ -3863,7 +3878,7 @@ Function 452: DrawCylinderEx() (6 input parameters) Param[4]: endRadius (type: float) Param[5]: sides (type: int) Param[6]: color (type: Color) -Function 453: DrawCylinderWires() (6 input parameters) +Function 455: DrawCylinderWires() (6 input parameters) Name: DrawCylinderWires Return type: void Description: Draw a cylinder/cone wires @@ -3873,7 +3888,7 @@ Function 453: DrawCylinderWires() (6 input parameters) Param[4]: height (type: float) Param[5]: slices (type: int) Param[6]: color (type: Color) -Function 454: DrawCylinderWiresEx() (6 input parameters) +Function 456: DrawCylinderWiresEx() (6 input parameters) Name: DrawCylinderWiresEx Return type: void Description: Draw a cylinder wires with base at startPos and top at endPos @@ -3883,7 +3898,7 @@ Function 454: DrawCylinderWiresEx() (6 input parameters) Param[4]: endRadius (type: float) Param[5]: sides (type: int) Param[6]: color (type: Color) -Function 455: DrawCapsule() (6 input parameters) +Function 457: DrawCapsule() (6 input parameters) Name: DrawCapsule Return type: void Description: Draw a capsule with the center of its sphere caps at startPos and endPos @@ -3893,7 +3908,7 @@ Function 455: DrawCapsule() (6 input parameters) Param[4]: slices (type: int) Param[5]: rings (type: int) Param[6]: color (type: Color) -Function 456: DrawCapsuleWires() (6 input parameters) +Function 458: DrawCapsuleWires() (6 input parameters) Name: DrawCapsuleWires Return type: void Description: Draw capsule wireframe with the center of its sphere caps at startPos and endPos @@ -3903,51 +3918,51 @@ Function 456: DrawCapsuleWires() (6 input parameters) Param[4]: slices (type: int) Param[5]: rings (type: int) Param[6]: color (type: Color) -Function 457: DrawPlane() (3 input parameters) +Function 459: DrawPlane() (3 input parameters) Name: DrawPlane Return type: void Description: Draw a plane XZ Param[1]: centerPos (type: Vector3) Param[2]: size (type: Vector2) Param[3]: color (type: Color) -Function 458: DrawRay() (2 input parameters) +Function 460: DrawRay() (2 input parameters) Name: DrawRay Return type: void Description: Draw a ray line Param[1]: ray (type: Ray) Param[2]: color (type: Color) -Function 459: DrawGrid() (2 input parameters) +Function 461: DrawGrid() (2 input parameters) Name: DrawGrid Return type: void Description: Draw a grid (centered at (0, 0, 0)) Param[1]: slices (type: int) Param[2]: spacing (type: float) -Function 460: LoadModel() (1 input parameters) +Function 462: LoadModel() (1 input parameters) Name: LoadModel Return type: Model Description: Load model from files (meshes and materials) Param[1]: fileName (type: const char *) -Function 461: LoadModelFromMesh() (1 input parameters) +Function 463: LoadModelFromMesh() (1 input parameters) Name: LoadModelFromMesh Return type: Model Description: Load model from generated mesh (default material) Param[1]: mesh (type: Mesh) -Function 462: IsModelValid() (1 input parameters) +Function 464: IsModelValid() (1 input parameters) Name: IsModelValid Return type: bool Description: Check if a model is valid (loaded in GPU, VAO/VBOs) Param[1]: model (type: Model) -Function 463: UnloadModel() (1 input parameters) +Function 465: UnloadModel() (1 input parameters) Name: UnloadModel Return type: void Description: Unload model (including meshes) from memory (RAM and/or VRAM) Param[1]: model (type: Model) -Function 464: GetModelBoundingBox() (1 input parameters) +Function 466: GetModelBoundingBox() (1 input parameters) Name: GetModelBoundingBox Return type: BoundingBox Description: Compute model bounding box limits (considers all meshes) Param[1]: model (type: Model) -Function 465: DrawModel() (4 input parameters) +Function 467: DrawModel() (4 input parameters) Name: DrawModel Return type: void Description: Draw a model (with texture if set) @@ -3955,7 +3970,7 @@ Function 465: DrawModel() (4 input parameters) Param[2]: position (type: Vector3) Param[3]: scale (type: float) Param[4]: tint (type: Color) -Function 466: DrawModelEx() (6 input parameters) +Function 468: DrawModelEx() (6 input parameters) Name: DrawModelEx Return type: void Description: Draw a model with extended parameters @@ -3965,7 +3980,7 @@ Function 466: DrawModelEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 467: DrawModelWires() (4 input parameters) +Function 469: DrawModelWires() (4 input parameters) Name: DrawModelWires Return type: void Description: Draw a model wires (with texture if set) @@ -3973,7 +3988,7 @@ Function 467: DrawModelWires() (4 input parameters) Param[2]: position (type: Vector3) Param[3]: scale (type: float) Param[4]: tint (type: Color) -Function 468: DrawModelWiresEx() (6 input parameters) +Function 470: DrawModelWiresEx() (6 input parameters) Name: DrawModelWiresEx Return type: void Description: Draw a model wires (with texture if set) with extended parameters @@ -3983,7 +3998,7 @@ Function 468: DrawModelWiresEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 469: DrawModelPoints() (4 input parameters) +Function 471: DrawModelPoints() (4 input parameters) Name: DrawModelPoints Return type: void Description: Draw a model as points @@ -3991,7 +4006,7 @@ Function 469: DrawModelPoints() (4 input parameters) Param[2]: position (type: Vector3) Param[3]: scale (type: float) Param[4]: tint (type: Color) -Function 470: DrawModelPointsEx() (6 input parameters) +Function 472: DrawModelPointsEx() (6 input parameters) Name: DrawModelPointsEx Return type: void Description: Draw a model as points with extended parameters @@ -4001,13 +4016,13 @@ Function 470: DrawModelPointsEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 471: DrawBoundingBox() (2 input parameters) +Function 473: DrawBoundingBox() (2 input parameters) Name: DrawBoundingBox Return type: void Description: Draw bounding box (wires) Param[1]: box (type: BoundingBox) Param[2]: color (type: Color) -Function 472: DrawBillboard() (5 input parameters) +Function 474: DrawBillboard() (5 input parameters) Name: DrawBillboard Return type: void Description: Draw a billboard texture @@ -4016,7 +4031,7 @@ Function 472: DrawBillboard() (5 input parameters) Param[3]: position (type: Vector3) Param[4]: scale (type: float) Param[5]: tint (type: Color) -Function 473: DrawBillboardRec() (6 input parameters) +Function 475: DrawBillboardRec() (6 input parameters) Name: DrawBillboardRec Return type: void Description: Draw a billboard texture defined by source @@ -4026,7 +4041,7 @@ Function 473: DrawBillboardRec() (6 input parameters) Param[4]: position (type: Vector3) Param[5]: size (type: Vector2) Param[6]: tint (type: Color) -Function 474: DrawBillboardPro() (9 input parameters) +Function 476: DrawBillboardPro() (9 input parameters) Name: DrawBillboardPro Return type: void Description: Draw a billboard texture defined by source and rotation @@ -4039,13 +4054,13 @@ Function 474: DrawBillboardPro() (9 input parameters) Param[7]: origin (type: Vector2) Param[8]: rotation (type: float) Param[9]: tint (type: Color) -Function 475: UploadMesh() (2 input parameters) +Function 477: UploadMesh() (2 input parameters) Name: UploadMesh Return type: void Description: Upload mesh vertex data in GPU and provide VAO/VBO ids Param[1]: mesh (type: Mesh *) Param[2]: dynamic (type: bool) -Function 476: UpdateMeshBuffer() (5 input parameters) +Function 478: UpdateMeshBuffer() (5 input parameters) Name: UpdateMeshBuffer Return type: void Description: Update mesh vertex data in GPU for a specific buffer index @@ -4054,19 +4069,19 @@ Function 476: UpdateMeshBuffer() (5 input parameters) Param[3]: data (type: const void *) Param[4]: dataSize (type: int) Param[5]: offset (type: int) -Function 477: UnloadMesh() (1 input parameters) +Function 479: UnloadMesh() (1 input parameters) Name: UnloadMesh Return type: void Description: Unload mesh data from CPU and GPU Param[1]: mesh (type: Mesh) -Function 478: DrawMesh() (3 input parameters) +Function 480: DrawMesh() (3 input parameters) Name: DrawMesh Return type: void Description: Draw a 3d mesh with material and transform Param[1]: mesh (type: Mesh) Param[2]: material (type: Material) Param[3]: transform (type: Matrix) -Function 479: DrawMeshInstanced() (4 input parameters) +Function 481: DrawMeshInstanced() (4 input parameters) Name: DrawMeshInstanced Return type: void Description: Draw multiple mesh instances with material and different transforms @@ -4074,35 +4089,35 @@ Function 479: DrawMeshInstanced() (4 input parameters) Param[2]: material (type: Material) Param[3]: transforms (type: const Matrix *) Param[4]: instances (type: int) -Function 480: GetMeshBoundingBox() (1 input parameters) +Function 482: GetMeshBoundingBox() (1 input parameters) Name: GetMeshBoundingBox Return type: BoundingBox Description: Compute mesh bounding box limits Param[1]: mesh (type: Mesh) -Function 481: GenMeshTangents() (1 input parameters) +Function 483: GenMeshTangents() (1 input parameters) Name: GenMeshTangents Return type: void Description: Compute mesh tangents Param[1]: mesh (type: Mesh *) -Function 482: ExportMesh() (2 input parameters) +Function 484: ExportMesh() (2 input parameters) Name: ExportMesh Return type: bool Description: Export mesh data to file, returns true on success Param[1]: mesh (type: Mesh) Param[2]: fileName (type: const char *) -Function 483: ExportMeshAsCode() (2 input parameters) +Function 485: ExportMeshAsCode() (2 input parameters) Name: ExportMeshAsCode Return type: bool Description: Export mesh as code file (.h) defining multiple arrays of vertex attributes Param[1]: mesh (type: Mesh) Param[2]: fileName (type: const char *) -Function 484: GenMeshPoly() (2 input parameters) +Function 486: GenMeshPoly() (2 input parameters) Name: GenMeshPoly Return type: Mesh Description: Generate polygonal mesh Param[1]: sides (type: int) Param[2]: radius (type: float) -Function 485: GenMeshPlane() (4 input parameters) +Function 487: GenMeshPlane() (4 input parameters) Name: GenMeshPlane Return type: Mesh Description: Generate plane mesh (with subdivisions) @@ -4110,42 +4125,42 @@ Function 485: GenMeshPlane() (4 input parameters) Param[2]: length (type: float) Param[3]: resX (type: int) Param[4]: resZ (type: int) -Function 486: GenMeshCube() (3 input parameters) +Function 488: GenMeshCube() (3 input parameters) Name: GenMeshCube Return type: Mesh Description: Generate cuboid mesh Param[1]: width (type: float) Param[2]: height (type: float) Param[3]: length (type: float) -Function 487: GenMeshSphere() (3 input parameters) +Function 489: GenMeshSphere() (3 input parameters) Name: GenMeshSphere Return type: Mesh Description: Generate sphere mesh (standard sphere) Param[1]: radius (type: float) Param[2]: rings (type: int) Param[3]: slices (type: int) -Function 488: GenMeshHemiSphere() (3 input parameters) +Function 490: GenMeshHemiSphere() (3 input parameters) Name: GenMeshHemiSphere Return type: Mesh Description: Generate half-sphere mesh (no bottom cap) Param[1]: radius (type: float) Param[2]: rings (type: int) Param[3]: slices (type: int) -Function 489: GenMeshCylinder() (3 input parameters) +Function 491: GenMeshCylinder() (3 input parameters) Name: GenMeshCylinder Return type: Mesh Description: Generate cylinder mesh Param[1]: radius (type: float) Param[2]: height (type: float) Param[3]: slices (type: int) -Function 490: GenMeshCone() (3 input parameters) +Function 492: GenMeshCone() (3 input parameters) Name: GenMeshCone Return type: Mesh Description: Generate cone/pyramid mesh Param[1]: radius (type: float) Param[2]: height (type: float) Param[3]: slices (type: int) -Function 491: GenMeshTorus() (4 input parameters) +Function 493: GenMeshTorus() (4 input parameters) Name: GenMeshTorus Return type: Mesh Description: Generate torus mesh @@ -4153,7 +4168,7 @@ Function 491: GenMeshTorus() (4 input parameters) Param[2]: size (type: float) Param[3]: radSeg (type: int) Param[4]: sides (type: int) -Function 492: GenMeshKnot() (4 input parameters) +Function 494: GenMeshKnot() (4 input parameters) Name: GenMeshKnot Return type: Mesh Description: Generate trefoil knot mesh @@ -4161,91 +4176,91 @@ Function 492: GenMeshKnot() (4 input parameters) Param[2]: size (type: float) Param[3]: radSeg (type: int) Param[4]: sides (type: int) -Function 493: GenMeshHeightmap() (2 input parameters) +Function 495: GenMeshHeightmap() (2 input parameters) Name: GenMeshHeightmap Return type: Mesh Description: Generate heightmap mesh from image data Param[1]: heightmap (type: Image) Param[2]: size (type: Vector3) -Function 494: GenMeshCubicmap() (2 input parameters) +Function 496: GenMeshCubicmap() (2 input parameters) Name: GenMeshCubicmap Return type: Mesh Description: Generate cubes-based map mesh from image data Param[1]: cubicmap (type: Image) Param[2]: cubeSize (type: Vector3) -Function 495: LoadMaterials() (2 input parameters) +Function 497: LoadMaterials() (2 input parameters) Name: LoadMaterials Return type: Material * Description: Load materials from model file Param[1]: fileName (type: const char *) Param[2]: materialCount (type: int *) -Function 496: LoadMaterialDefault() (0 input parameters) +Function 498: LoadMaterialDefault() (0 input parameters) Name: LoadMaterialDefault Return type: Material Description: Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps) No input parameters -Function 497: IsMaterialValid() (1 input parameters) +Function 499: IsMaterialValid() (1 input parameters) Name: IsMaterialValid Return type: bool Description: Check if a material is valid (shader assigned, map textures loaded in GPU) Param[1]: material (type: Material) -Function 498: UnloadMaterial() (1 input parameters) +Function 500: UnloadMaterial() (1 input parameters) Name: UnloadMaterial Return type: void Description: Unload material from GPU memory (VRAM) Param[1]: material (type: Material) -Function 499: SetMaterialTexture() (3 input parameters) +Function 501: SetMaterialTexture() (3 input parameters) Name: SetMaterialTexture Return type: void Description: Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...) Param[1]: material (type: Material *) Param[2]: mapType (type: int) Param[3]: texture (type: Texture2D) -Function 500: SetModelMeshMaterial() (3 input parameters) +Function 502: SetModelMeshMaterial() (3 input parameters) Name: SetModelMeshMaterial Return type: void Description: Set material for a mesh Param[1]: model (type: Model *) Param[2]: meshId (type: int) Param[3]: materialId (type: int) -Function 501: LoadModelAnimations() (2 input parameters) +Function 503: LoadModelAnimations() (2 input parameters) Name: LoadModelAnimations Return type: ModelAnimation * Description: Load model animations from file Param[1]: fileName (type: const char *) Param[2]: animCount (type: int *) -Function 502: UpdateModelAnimation() (3 input parameters) +Function 504: UpdateModelAnimation() (3 input parameters) Name: UpdateModelAnimation Return type: void Description: Update model animation pose (CPU) Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) Param[3]: frame (type: int) -Function 503: UpdateModelAnimationBoneMatrices() (3 input parameters) - Name: UpdateModelAnimationBoneMatrices +Function 505: UpdateModelAnimationBones() (3 input parameters) + Name: UpdateModelAnimationBones Return type: void Description: Update model animation mesh bone matrices (GPU skinning) Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) Param[3]: frame (type: int) -Function 504: UnloadModelAnimation() (1 input parameters) +Function 506: UnloadModelAnimation() (1 input parameters) Name: UnloadModelAnimation Return type: void Description: Unload animation data Param[1]: anim (type: ModelAnimation) -Function 505: UnloadModelAnimations() (2 input parameters) +Function 507: UnloadModelAnimations() (2 input parameters) Name: UnloadModelAnimations Return type: void Description: Unload animation array data Param[1]: animations (type: ModelAnimation *) Param[2]: animCount (type: int) -Function 506: IsModelAnimationValid() (2 input parameters) +Function 508: IsModelAnimationValid() (2 input parameters) Name: IsModelAnimationValid Return type: bool Description: Check model animation skeleton match Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) -Function 507: CheckCollisionSpheres() (4 input parameters) +Function 509: CheckCollisionSpheres() (4 input parameters) Name: CheckCollisionSpheres Return type: bool Description: Check collision between two spheres @@ -4253,40 +4268,40 @@ Function 507: CheckCollisionSpheres() (4 input parameters) Param[2]: radius1 (type: float) Param[3]: center2 (type: Vector3) Param[4]: radius2 (type: float) -Function 508: CheckCollisionBoxes() (2 input parameters) +Function 510: CheckCollisionBoxes() (2 input parameters) Name: CheckCollisionBoxes Return type: bool Description: Check collision between two bounding boxes Param[1]: box1 (type: BoundingBox) Param[2]: box2 (type: BoundingBox) -Function 509: CheckCollisionBoxSphere() (3 input parameters) +Function 511: CheckCollisionBoxSphere() (3 input parameters) Name: CheckCollisionBoxSphere Return type: bool Description: Check collision between box and sphere Param[1]: box (type: BoundingBox) Param[2]: center (type: Vector3) Param[3]: radius (type: float) -Function 510: GetRayCollisionSphere() (3 input parameters) +Function 512: GetRayCollisionSphere() (3 input parameters) Name: GetRayCollisionSphere Return type: RayCollision Description: Get collision info between ray and sphere Param[1]: ray (type: Ray) Param[2]: center (type: Vector3) Param[3]: radius (type: float) -Function 511: GetRayCollisionBox() (2 input parameters) +Function 513: GetRayCollisionBox() (2 input parameters) Name: GetRayCollisionBox Return type: RayCollision Description: Get collision info between ray and box Param[1]: ray (type: Ray) Param[2]: box (type: BoundingBox) -Function 512: GetRayCollisionMesh() (3 input parameters) +Function 514: GetRayCollisionMesh() (3 input parameters) Name: GetRayCollisionMesh Return type: RayCollision Description: Get collision info between ray and mesh Param[1]: ray (type: Ray) Param[2]: mesh (type: Mesh) Param[3]: transform (type: Matrix) -Function 513: GetRayCollisionTriangle() (4 input parameters) +Function 515: GetRayCollisionTriangle() (4 input parameters) Name: GetRayCollisionTriangle Return type: RayCollision Description: Get collision info between ray and triangle @@ -4294,7 +4309,7 @@ Function 513: GetRayCollisionTriangle() (4 input parameters) Param[2]: p1 (type: Vector3) Param[3]: p2 (type: Vector3) Param[4]: p3 (type: Vector3) -Function 514: GetRayCollisionQuad() (5 input parameters) +Function 516: GetRayCollisionQuad() (5 input parameters) Name: GetRayCollisionQuad Return type: RayCollision Description: Get collision info between ray and quad @@ -4303,158 +4318,158 @@ Function 514: GetRayCollisionQuad() (5 input parameters) Param[3]: p2 (type: Vector3) Param[4]: p3 (type: Vector3) Param[5]: p4 (type: Vector3) -Function 515: InitAudioDevice() (0 input parameters) +Function 517: InitAudioDevice() (0 input parameters) Name: InitAudioDevice Return type: void Description: Initialize audio device and context No input parameters -Function 516: CloseAudioDevice() (0 input parameters) +Function 518: CloseAudioDevice() (0 input parameters) Name: CloseAudioDevice Return type: void Description: Close the audio device and context No input parameters -Function 517: IsAudioDeviceReady() (0 input parameters) +Function 519: IsAudioDeviceReady() (0 input parameters) Name: IsAudioDeviceReady Return type: bool Description: Check if audio device has been initialized successfully No input parameters -Function 518: SetMasterVolume() (1 input parameters) +Function 520: SetMasterVolume() (1 input parameters) Name: SetMasterVolume Return type: void Description: Set master volume (listener) Param[1]: volume (type: float) -Function 519: GetMasterVolume() (0 input parameters) +Function 521: GetMasterVolume() (0 input parameters) Name: GetMasterVolume Return type: float Description: Get master volume (listener) No input parameters -Function 520: LoadWave() (1 input parameters) +Function 522: LoadWave() (1 input parameters) Name: LoadWave Return type: Wave Description: Load wave data from file Param[1]: fileName (type: const char *) -Function 521: LoadWaveFromMemory() (3 input parameters) +Function 523: LoadWaveFromMemory() (3 input parameters) Name: LoadWaveFromMemory Return type: Wave Description: Load wave from memory buffer, fileType refers to extension: i.e. '.wav' Param[1]: fileType (type: const char *) Param[2]: fileData (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 522: IsWaveValid() (1 input parameters) +Function 524: IsWaveValid() (1 input parameters) Name: IsWaveValid Return type: bool Description: Checks if wave data is valid (data loaded and parameters) Param[1]: wave (type: Wave) -Function 523: LoadSound() (1 input parameters) +Function 525: LoadSound() (1 input parameters) Name: LoadSound Return type: Sound Description: Load sound from file Param[1]: fileName (type: const char *) -Function 524: LoadSoundFromWave() (1 input parameters) +Function 526: LoadSoundFromWave() (1 input parameters) Name: LoadSoundFromWave Return type: Sound Description: Load sound from wave data Param[1]: wave (type: Wave) -Function 525: LoadSoundAlias() (1 input parameters) +Function 527: LoadSoundAlias() (1 input parameters) Name: LoadSoundAlias Return type: Sound Description: Create a new sound that shares the same sample data as the source sound, does not own the sound data Param[1]: source (type: Sound) -Function 526: IsSoundValid() (1 input parameters) +Function 528: IsSoundValid() (1 input parameters) Name: IsSoundValid Return type: bool Description: Checks if a sound is valid (data loaded and buffers initialized) Param[1]: sound (type: Sound) -Function 527: UpdateSound() (3 input parameters) +Function 529: UpdateSound() (3 input parameters) Name: UpdateSound Return type: void Description: Update sound buffer with new data Param[1]: sound (type: Sound) Param[2]: data (type: const void *) Param[3]: sampleCount (type: int) -Function 528: UnloadWave() (1 input parameters) +Function 530: UnloadWave() (1 input parameters) Name: UnloadWave Return type: void Description: Unload wave data Param[1]: wave (type: Wave) -Function 529: UnloadSound() (1 input parameters) +Function 531: UnloadSound() (1 input parameters) Name: UnloadSound Return type: void Description: Unload sound Param[1]: sound (type: Sound) -Function 530: UnloadSoundAlias() (1 input parameters) +Function 532: UnloadSoundAlias() (1 input parameters) Name: UnloadSoundAlias Return type: void Description: Unload a sound alias (does not deallocate sample data) Param[1]: alias (type: Sound) -Function 531: ExportWave() (2 input parameters) +Function 533: ExportWave() (2 input parameters) Name: ExportWave Return type: bool Description: Export wave data to file, returns true on success Param[1]: wave (type: Wave) Param[2]: fileName (type: const char *) -Function 532: ExportWaveAsCode() (2 input parameters) +Function 534: ExportWaveAsCode() (2 input parameters) Name: ExportWaveAsCode Return type: bool Description: Export wave sample data to code (.h), returns true on success Param[1]: wave (type: Wave) Param[2]: fileName (type: const char *) -Function 533: PlaySound() (1 input parameters) +Function 535: PlaySound() (1 input parameters) Name: PlaySound Return type: void Description: Play a sound Param[1]: sound (type: Sound) -Function 534: StopSound() (1 input parameters) +Function 536: StopSound() (1 input parameters) Name: StopSound Return type: void Description: Stop playing a sound Param[1]: sound (type: Sound) -Function 535: PauseSound() (1 input parameters) +Function 537: PauseSound() (1 input parameters) Name: PauseSound Return type: void Description: Pause a sound Param[1]: sound (type: Sound) -Function 536: ResumeSound() (1 input parameters) +Function 538: ResumeSound() (1 input parameters) Name: ResumeSound Return type: void Description: Resume a paused sound Param[1]: sound (type: Sound) -Function 537: IsSoundPlaying() (1 input parameters) +Function 539: IsSoundPlaying() (1 input parameters) Name: IsSoundPlaying Return type: bool Description: Check if a sound is currently playing Param[1]: sound (type: Sound) -Function 538: SetSoundVolume() (2 input parameters) +Function 540: SetSoundVolume() (2 input parameters) Name: SetSoundVolume Return type: void Description: Set volume for a sound (1.0 is max level) Param[1]: sound (type: Sound) Param[2]: volume (type: float) -Function 539: SetSoundPitch() (2 input parameters) +Function 541: SetSoundPitch() (2 input parameters) Name: SetSoundPitch Return type: void Description: Set pitch for a sound (1.0 is base level) Param[1]: sound (type: Sound) Param[2]: pitch (type: float) -Function 540: SetSoundPan() (2 input parameters) +Function 542: SetSoundPan() (2 input parameters) Name: SetSoundPan Return type: void Description: Set pan for a sound (0.5 is center) Param[1]: sound (type: Sound) Param[2]: pan (type: float) -Function 541: WaveCopy() (1 input parameters) +Function 543: WaveCopy() (1 input parameters) Name: WaveCopy Return type: Wave Description: Copy a wave to a new wave Param[1]: wave (type: Wave) -Function 542: WaveCrop() (3 input parameters) +Function 544: WaveCrop() (3 input parameters) Name: WaveCrop Return type: void Description: Crop a wave to defined frames range Param[1]: wave (type: Wave *) Param[2]: initFrame (type: int) Param[3]: finalFrame (type: int) -Function 543: WaveFormat() (4 input parameters) +Function 545: WaveFormat() (4 input parameters) Name: WaveFormat Return type: void Description: Convert wave data to desired format @@ -4462,203 +4477,203 @@ Function 543: WaveFormat() (4 input parameters) Param[2]: sampleRate (type: int) Param[3]: sampleSize (type: int) Param[4]: channels (type: int) -Function 544: LoadWaveSamples() (1 input parameters) +Function 546: LoadWaveSamples() (1 input parameters) Name: LoadWaveSamples Return type: float * Description: Load samples data from wave as a 32bit float data array Param[1]: wave (type: Wave) -Function 545: UnloadWaveSamples() (1 input parameters) +Function 547: UnloadWaveSamples() (1 input parameters) Name: UnloadWaveSamples Return type: void Description: Unload samples data loaded with LoadWaveSamples() Param[1]: samples (type: float *) -Function 546: LoadMusicStream() (1 input parameters) +Function 548: LoadMusicStream() (1 input parameters) Name: LoadMusicStream Return type: Music Description: Load music stream from file Param[1]: fileName (type: const char *) -Function 547: LoadMusicStreamFromMemory() (3 input parameters) +Function 549: LoadMusicStreamFromMemory() (3 input parameters) Name: LoadMusicStreamFromMemory Return type: Music Description: Load music stream from data Param[1]: fileType (type: const char *) Param[2]: data (type: const unsigned char *) Param[3]: dataSize (type: int) -Function 548: IsMusicValid() (1 input parameters) +Function 550: IsMusicValid() (1 input parameters) Name: IsMusicValid Return type: bool Description: Checks if a music stream is valid (context and buffers initialized) Param[1]: music (type: Music) -Function 549: UnloadMusicStream() (1 input parameters) +Function 551: UnloadMusicStream() (1 input parameters) Name: UnloadMusicStream Return type: void Description: Unload music stream Param[1]: music (type: Music) -Function 550: PlayMusicStream() (1 input parameters) +Function 552: PlayMusicStream() (1 input parameters) Name: PlayMusicStream Return type: void Description: Start music playing Param[1]: music (type: Music) -Function 551: IsMusicStreamPlaying() (1 input parameters) +Function 553: IsMusicStreamPlaying() (1 input parameters) Name: IsMusicStreamPlaying Return type: bool Description: Check if music is playing Param[1]: music (type: Music) -Function 552: UpdateMusicStream() (1 input parameters) +Function 554: UpdateMusicStream() (1 input parameters) Name: UpdateMusicStream Return type: void Description: Updates buffers for music streaming Param[1]: music (type: Music) -Function 553: StopMusicStream() (1 input parameters) +Function 555: StopMusicStream() (1 input parameters) Name: StopMusicStream Return type: void Description: Stop music playing Param[1]: music (type: Music) -Function 554: PauseMusicStream() (1 input parameters) +Function 556: PauseMusicStream() (1 input parameters) Name: PauseMusicStream Return type: void Description: Pause music playing Param[1]: music (type: Music) -Function 555: ResumeMusicStream() (1 input parameters) +Function 557: ResumeMusicStream() (1 input parameters) Name: ResumeMusicStream Return type: void Description: Resume playing paused music Param[1]: music (type: Music) -Function 556: SeekMusicStream() (2 input parameters) +Function 558: SeekMusicStream() (2 input parameters) Name: SeekMusicStream Return type: void Description: Seek music to a position (in seconds) Param[1]: music (type: Music) Param[2]: position (type: float) -Function 557: SetMusicVolume() (2 input parameters) +Function 559: SetMusicVolume() (2 input parameters) Name: SetMusicVolume Return type: void Description: Set volume for music (1.0 is max level) Param[1]: music (type: Music) Param[2]: volume (type: float) -Function 558: SetMusicPitch() (2 input parameters) +Function 560: SetMusicPitch() (2 input parameters) Name: SetMusicPitch Return type: void Description: Set pitch for a music (1.0 is base level) Param[1]: music (type: Music) Param[2]: pitch (type: float) -Function 559: SetMusicPan() (2 input parameters) +Function 561: SetMusicPan() (2 input parameters) Name: SetMusicPan Return type: void Description: Set pan for a music (0.5 is center) Param[1]: music (type: Music) Param[2]: pan (type: float) -Function 560: GetMusicTimeLength() (1 input parameters) +Function 562: GetMusicTimeLength() (1 input parameters) Name: GetMusicTimeLength Return type: float Description: Get music time length (in seconds) Param[1]: music (type: Music) -Function 561: GetMusicTimePlayed() (1 input parameters) +Function 563: GetMusicTimePlayed() (1 input parameters) Name: GetMusicTimePlayed Return type: float Description: Get current music time played (in seconds) Param[1]: music (type: Music) -Function 562: LoadAudioStream() (3 input parameters) +Function 564: LoadAudioStream() (3 input parameters) Name: LoadAudioStream Return type: AudioStream Description: Load audio stream (to stream raw audio pcm data) Param[1]: sampleRate (type: unsigned int) Param[2]: sampleSize (type: unsigned int) Param[3]: channels (type: unsigned int) -Function 563: IsAudioStreamValid() (1 input parameters) +Function 565: IsAudioStreamValid() (1 input parameters) Name: IsAudioStreamValid Return type: bool Description: Checks if an audio stream is valid (buffers initialized) Param[1]: stream (type: AudioStream) -Function 564: UnloadAudioStream() (1 input parameters) +Function 566: UnloadAudioStream() (1 input parameters) Name: UnloadAudioStream Return type: void Description: Unload audio stream and free memory Param[1]: stream (type: AudioStream) -Function 565: UpdateAudioStream() (3 input parameters) +Function 567: UpdateAudioStream() (3 input parameters) Name: UpdateAudioStream Return type: void Description: Update audio stream buffers with data Param[1]: stream (type: AudioStream) Param[2]: data (type: const void *) Param[3]: frameCount (type: int) -Function 566: IsAudioStreamProcessed() (1 input parameters) +Function 568: IsAudioStreamProcessed() (1 input parameters) Name: IsAudioStreamProcessed Return type: bool Description: Check if any audio stream buffers requires refill Param[1]: stream (type: AudioStream) -Function 567: PlayAudioStream() (1 input parameters) +Function 569: PlayAudioStream() (1 input parameters) Name: PlayAudioStream Return type: void Description: Play audio stream Param[1]: stream (type: AudioStream) -Function 568: PauseAudioStream() (1 input parameters) +Function 570: PauseAudioStream() (1 input parameters) Name: PauseAudioStream Return type: void Description: Pause audio stream Param[1]: stream (type: AudioStream) -Function 569: ResumeAudioStream() (1 input parameters) +Function 571: ResumeAudioStream() (1 input parameters) Name: ResumeAudioStream Return type: void Description: Resume audio stream Param[1]: stream (type: AudioStream) -Function 570: IsAudioStreamPlaying() (1 input parameters) +Function 572: IsAudioStreamPlaying() (1 input parameters) Name: IsAudioStreamPlaying Return type: bool Description: Check if audio stream is playing Param[1]: stream (type: AudioStream) -Function 571: StopAudioStream() (1 input parameters) +Function 573: StopAudioStream() (1 input parameters) Name: StopAudioStream Return type: void Description: Stop audio stream Param[1]: stream (type: AudioStream) -Function 572: SetAudioStreamVolume() (2 input parameters) +Function 574: SetAudioStreamVolume() (2 input parameters) Name: SetAudioStreamVolume Return type: void Description: Set volume for audio stream (1.0 is max level) Param[1]: stream (type: AudioStream) Param[2]: volume (type: float) -Function 573: SetAudioStreamPitch() (2 input parameters) +Function 575: SetAudioStreamPitch() (2 input parameters) Name: SetAudioStreamPitch Return type: void Description: Set pitch for audio stream (1.0 is base level) Param[1]: stream (type: AudioStream) Param[2]: pitch (type: float) -Function 574: SetAudioStreamPan() (2 input parameters) +Function 576: SetAudioStreamPan() (2 input parameters) Name: SetAudioStreamPan Return type: void Description: Set pan for audio stream (0.5 is centered) Param[1]: stream (type: AudioStream) Param[2]: pan (type: float) -Function 575: SetAudioStreamBufferSizeDefault() (1 input parameters) +Function 577: SetAudioStreamBufferSizeDefault() (1 input parameters) Name: SetAudioStreamBufferSizeDefault Return type: void Description: Default size for new audio streams Param[1]: size (type: int) -Function 576: SetAudioStreamCallback() (2 input parameters) +Function 578: SetAudioStreamCallback() (2 input parameters) Name: SetAudioStreamCallback Return type: void Description: Audio thread callback to request new data Param[1]: stream (type: AudioStream) Param[2]: callback (type: AudioCallback) -Function 577: AttachAudioStreamProcessor() (2 input parameters) +Function 579: AttachAudioStreamProcessor() (2 input parameters) Name: AttachAudioStreamProcessor Return type: void Description: Attach audio stream processor to stream, receives the samples as 'float' Param[1]: stream (type: AudioStream) Param[2]: processor (type: AudioCallback) -Function 578: DetachAudioStreamProcessor() (2 input parameters) +Function 580: DetachAudioStreamProcessor() (2 input parameters) Name: DetachAudioStreamProcessor Return type: void Description: Detach audio stream processor from stream Param[1]: stream (type: AudioStream) Param[2]: processor (type: AudioCallback) -Function 579: AttachAudioMixedProcessor() (1 input parameters) +Function 581: AttachAudioMixedProcessor() (1 input parameters) Name: AttachAudioMixedProcessor Return type: void Description: Attach audio stream processor to the entire audio pipeline, receives the samples as 'float' Param[1]: processor (type: AudioCallback) -Function 580: DetachAudioMixedProcessor() (1 input parameters) +Function 582: DetachAudioMixedProcessor() (1 input parameters) Name: DetachAudioMixedProcessor Return type: void Description: Detach audio stream processor from the entire audio pipeline diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml index 58794b4eb..241b28ae8 100644 --- a/parser/output/raylib_api.xml +++ b/parser/output/raylib_api.xml @@ -3,9 +3,9 @@ - + - + @@ -507,7 +507,7 @@ - + @@ -537,8 +537,9 @@ + - + @@ -547,7 +548,11 @@ - + + + + + @@ -674,7 +679,7 @@ - + @@ -795,6 +800,8 @@ + + @@ -1179,6 +1186,9 @@ + + + @@ -2443,12 +2453,12 @@ - - + + - + @@ -2462,25 +2472,25 @@ - + - + - + - + - + - + - + @@ -2826,7 +2836,7 @@ - + diff --git a/parser/raylib_parser.c b/parser/raylib_parser.c index 94a715562..82e22f195 100644 --- a/parser/raylib_parser.c +++ b/parser/raylib_parser.c @@ -54,7 +54,7 @@ raylib-parser is licensed under an unmodified zlib/libpng license, which is an OSI-certified, BSD-like license that allows static linking with closed source software: - Copyright (c) 2021-2024 Ramon Santamaria (@raysan5) + Copyright (c) 2021-2025 Ramon Santamaria (@raysan5) **********************************************************************************************/ @@ -1084,7 +1084,7 @@ static void ShowCommandLineInfo(void) printf("// //\n"); printf("// more info and bugs-report: github.com/raysan5/raylib/parser //\n"); printf("// //\n"); - printf("// Copyright (c) 2021-2024 Ramon Santamaria (@raysan5) //\n"); + printf("// Copyright (c) 2021-2025 Ramon Santamaria (@raysan5) //\n"); printf("// //\n"); printf("//////////////////////////////////////////////////////////////////////////////////\n\n"); diff --git a/projects/4coder/Makefile b/projects/4coder/Makefile index 8e64702a6..1b598eed5 100644 --- a/projects/4coder/Makefile +++ b/projects/4coder/Makefile @@ -114,7 +114,7 @@ endif ifeq ($(PLATFORM),PLATFORM_WEB) # Emscripten required variables - EMSDK_PATH ?= C:/emsdk + EMSDK_PATH ?= C:/raylib/emsdk EMSCRIPTEN_PATH ?= $(EMSDK_PATH)/upstream/emscripten CLANG_PATH = $(EMSDK_PATH)/upstream/bin PYTHON_PATH = $(EMSDK_PATH)/python/3.9.2-nuget_64bit @@ -219,21 +219,23 @@ endif ifeq ($(PLATFORM),PLATFORM_WEB) # -Os # size optimization # -O2 # optimization level 2, if used, also set --memory-init-file 0 - # -s USE_GLFW=3 # Use glfw3 library (context/input management) - # -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL! - # -s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) - # -s USE_PTHREADS=1 # multithreading support - # -s WASM=0 # disable Web Assembly, emitted by default - # -s EMTERPRETIFY=1 # enable emscripten code interpreter (very slow) - # -s EMTERPRETIFY_ASYNC=1 # support synchronous loops by emterpreter - # -s FORCE_FILESYSTEM=1 # force filesystem to load/save files data - # -s ASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off) + # -sUSE_GLFW=3 # Use glfw3 library (context/input management) + # -sALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL! + # -sTOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) (67108864 = 64MB) + # -sUSE_PTHREADS=1 # multithreading support + # -sWASM=0 # disable Web Assembly, emitted by default + # -sASYNCIFY # lets synchronous C/C++ code interact with asynchronous JS + # -sFORCE_FILESYSTEM=1 # force filesystem to load/save files data + # -sASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off) + # -sMINIFY_HTML=0 # minify generated html from shell.html # --profiling # include information for code profiling # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) # --preload-file resources # specify a resources folder for data compilation - CFLAGS += -Os -s USE_GLFW=3 -s TOTAL_MEMORY=16777216 --preload-file resources + # --source-map-base # allow debugging in browser with source map + # --shell-file shell.html # define a custom shell .html and output extension + CFLAGS += -Os -sUSE_GLFW=3 -sTOTAL_MEMORY=16777216 --preload-file resources -sMINIFY_HTML=0 ifeq ($(BUILD_MODE), DEBUG) - CFLAGS += -s ASSERTIONS=1 --profiling + CFLAGS += -sASSERTIONS=1 --profiling endif # Define a custom shell .html and output extension diff --git a/projects/Notepad++/npes_saved_w64devkit.txt b/projects/Notepad++/npes_saved_w64devkit.txt index 92375c24a..767fa274d 100644 Binary files a/projects/Notepad++/npes_saved_w64devkit.txt and b/projects/Notepad++/npes_saved_w64devkit.txt differ diff --git a/projects/Notepad++/raylib_npp_parser/raylib_npp.xml b/projects/Notepad++/raylib_npp_parser/raylib_npp.xml index c869a1a18..3c642ad31 100644 --- a/projects/Notepad++/raylib_npp_parser/raylib_npp.xml +++ b/projects/Notepad++/raylib_npp_parser/raylib_npp.xml @@ -23,16 +23,16 @@ - + - + - + - + @@ -43,7 +43,7 @@ - + @@ -53,38 +53,38 @@ - + - + - + - + - + - + - + - + - + @@ -113,12 +113,12 @@ - + - + @@ -139,7 +139,7 @@ - + @@ -190,6 +190,9 @@ + + + @@ -315,8 +318,8 @@ - - + + @@ -370,20 +373,18 @@ - - - + + + - - + + + - - - - - + + @@ -392,12 +393,6 @@ - - - - - - @@ -412,6 +407,22 @@ + + + + + + + + + + + + + + + + @@ -430,6 +441,9 @@ + + + @@ -484,6 +498,8 @@ + + @@ -575,6 +591,7 @@ + @@ -629,6 +646,11 @@ + + + + + @@ -639,13 +661,18 @@ + + + + + - + @@ -701,6 +728,25 @@ + + + + + + + + + + + + + + + + + + + @@ -710,7 +756,7 @@ - + @@ -752,7 +798,7 @@ - + @@ -837,6 +883,14 @@ + + + + + + + + @@ -939,7 +993,7 @@ - + @@ -984,17 +1038,23 @@ + + + + + + - + - + @@ -1025,7 +1085,7 @@ - + @@ -1071,8 +1131,8 @@ - - + + @@ -1173,8 +1233,8 @@ - - + + @@ -1183,17 +1243,17 @@ - - + + - - - - + + + + @@ -1221,6 +1281,14 @@ + + + + + + + + @@ -1247,14 +1315,14 @@ - + - + @@ -1291,7 +1359,7 @@ - + @@ -1299,7 +1367,7 @@ - + @@ -1307,7 +1375,7 @@ - + @@ -1315,7 +1383,7 @@ - + @@ -1323,7 +1391,7 @@ - + @@ -1443,6 +1511,14 @@ + + + + + + + + @@ -1464,10 +1540,18 @@ + + + + + + + + - + @@ -1480,14 +1564,6 @@ - - - - - - - - @@ -1515,19 +1591,20 @@ - - - - - - - + + + + + + + + @@ -1543,8 +1620,8 @@ - - + + @@ -1661,6 +1738,12 @@ + + + + + + @@ -1725,6 +1808,13 @@ + + + + + + + @@ -1901,6 +1991,15 @@ + + + + + + + + + @@ -1968,6 +2067,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2023,8 +2167,8 @@ - - + + @@ -2033,8 +2177,8 @@ - - + + @@ -2131,6 +2275,12 @@ + + + + + + @@ -2138,7 +2288,7 @@ - + @@ -2195,6 +2345,13 @@ + + + + + + + @@ -2228,7 +2385,7 @@ - + @@ -2252,8 +2409,8 @@ - - + + @@ -2480,7 +2637,7 @@ - + @@ -2534,11 +2691,27 @@ + + + + + + + + + + + + + + + + @@ -2577,7 +2750,7 @@ - + @@ -2734,8 +2907,8 @@ - - + + @@ -2787,6 +2960,24 @@ + + + + + + + + + + + + + + + + + + @@ -2798,7 +2989,7 @@ - + @@ -2822,7 +3013,7 @@ - + @@ -2862,12 +3053,6 @@ - - - - - - @@ -2878,6 +3063,18 @@ + + + + + + + + + + + + @@ -2968,8 +3165,8 @@ - - + + @@ -3001,7 +3198,14 @@ - + + + + + + + + @@ -3121,8 +3325,8 @@ - - + + @@ -3141,8 +3345,8 @@ - - + + @@ -3231,10 +3435,10 @@ - + - - + + @@ -3269,8 +3473,8 @@ - - + + @@ -3352,8 +3556,8 @@ - - + + @@ -3430,7 +3634,7 @@ - + @@ -3443,7 +3647,7 @@ - + diff --git a/projects/Notepad++/raylib_npp_parser/raylib_to_parse.h b/projects/Notepad++/raylib_npp_parser/raylib_to_parse.h index 0a3c2417d..2ff4c9cb3 100644 --- a/projects/Notepad++/raylib_npp_parser/raylib_to_parse.h +++ b/projects/Notepad++/raylib_npp_parser/raylib_to_parse.h @@ -8,36 +8,36 @@ RLAPI void CloseWindow(void); // Close windo RLAPI bool WindowShouldClose(void); // Check if application should close (KEY_ESCAPE pressed or windows close icon clicked) RLAPI bool IsWindowReady(void); // Check if window has been initialized successfully RLAPI bool IsWindowFullscreen(void); // Check if window is currently fullscreen -RLAPI bool IsWindowHidden(void); // Check if window is currently hidden (only PLATFORM_DESKTOP) -RLAPI bool IsWindowMinimized(void); // Check if window is currently minimized (only PLATFORM_DESKTOP) -RLAPI bool IsWindowMaximized(void); // Check if window is currently maximized (only PLATFORM_DESKTOP) -RLAPI bool IsWindowFocused(void); // Check if window is currently focused (only PLATFORM_DESKTOP) +RLAPI bool IsWindowHidden(void); // Check if window is currently hidden +RLAPI bool IsWindowMinimized(void); // Check if window is currently minimized +RLAPI bool IsWindowMaximized(void); // Check if window is currently maximized +RLAPI bool IsWindowFocused(void); // Check if window is currently focused RLAPI bool IsWindowResized(void); // Check if window has been resized last frame RLAPI bool IsWindowState(unsigned int flag); // Check if one specific window flag is enabled -RLAPI void SetWindowState(unsigned int flags); // Set window configuration state using flags (only PLATFORM_DESKTOP) +RLAPI void SetWindowState(unsigned int flags); // Set window configuration state using flags RLAPI void ClearWindowState(unsigned int flags); // Clear window configuration state flags -RLAPI void ToggleFullscreen(void); // Toggle window state: fullscreen/windowed (only PLATFORM_DESKTOP) -RLAPI void ToggleBorderlessWindowed(void); // Toggle window state: borderless windowed (only PLATFORM_DESKTOP) -RLAPI void MaximizeWindow(void); // Set window state: maximized, if resizable (only PLATFORM_DESKTOP) -RLAPI void MinimizeWindow(void); // Set window state: minimized, if resizable (only PLATFORM_DESKTOP) -RLAPI void RestoreWindow(void); // Set window state: not minimized/maximized (only PLATFORM_DESKTOP) -RLAPI void SetWindowIcon(Image image); // Set icon for window (single image, RGBA 32bit, only PLATFORM_DESKTOP) -RLAPI void SetWindowIcons(Image *images, int count); // Set icon for window (multiple images, RGBA 32bit, only PLATFORM_DESKTOP) -RLAPI void SetWindowTitle(const char *title); // Set title for window (only PLATFORM_DESKTOP and PLATFORM_WEB) -RLAPI void SetWindowPosition(int x, int y); // Set window position on screen (only PLATFORM_DESKTOP) +RLAPI void ToggleFullscreen(void); // Toggle window state: fullscreen/windowed, resizes monitor to match window resolution +RLAPI void ToggleBorderlessWindowed(void); // Toggle window state: borderless windowed, resizes window to match monitor resolution +RLAPI void MaximizeWindow(void); // Set window state: maximized, if resizable +RLAPI void MinimizeWindow(void); // Set window state: minimized, if resizable +RLAPI void RestoreWindow(void); // Set window state: not minimized/maximized +RLAPI void SetWindowIcon(Image image); // Set icon for window (single image, RGBA 32bit) +RLAPI void SetWindowIcons(Image *images, int count); // Set icon for window (multiple images, RGBA 32bit) +RLAPI void SetWindowTitle(const char *title); // Set title for window +RLAPI void SetWindowPosition(int x, int y); // Set window position on screen RLAPI void SetWindowMonitor(int monitor); // Set monitor for the current window RLAPI void SetWindowMinSize(int width, int height); // Set window minimum dimensions (for FLAG_WINDOW_RESIZABLE) RLAPI void SetWindowMaxSize(int width, int height); // Set window maximum dimensions (for FLAG_WINDOW_RESIZABLE) RLAPI void SetWindowSize(int width, int height); // Set window dimensions -RLAPI void SetWindowOpacity(float opacity); // Set window opacity [0.0f..1.0f] (only PLATFORM_DESKTOP) -RLAPI void SetWindowFocused(void); // Set window focused (only PLATFORM_DESKTOP) +RLAPI void SetWindowOpacity(float opacity); // Set window opacity [0.0f..1.0f] +RLAPI void SetWindowFocused(void); // Set window focused RLAPI void *GetWindowHandle(void); // Get native window handle RLAPI int GetScreenWidth(void); // Get current screen width RLAPI int GetScreenHeight(void); // Get current screen height RLAPI int GetRenderWidth(void); // Get current render width (it considers HiDPI) RLAPI int GetRenderHeight(void); // Get current render height (it considers HiDPI) RLAPI int GetMonitorCount(void); // Get number of connected monitors -RLAPI int GetCurrentMonitor(void); // Get current connected monitor +RLAPI int GetCurrentMonitor(void); // Get current monitor where window is placed RLAPI Vector2 GetMonitorPosition(int monitor); // Get specified monitor position RLAPI int GetMonitorWidth(int monitor); // Get specified monitor width (current video mode used by monitor) RLAPI int GetMonitorHeight(int monitor); // Get specified monitor height (current video mode used by monitor) @@ -49,6 +49,7 @@ RLAPI Vector2 GetWindowScaleDPI(void); // Get window RLAPI const char *GetMonitorName(int monitor); // Get the human-readable, UTF-8 encoded name of the specified monitor RLAPI void SetClipboardText(const char *text); // Set clipboard text content RLAPI const char *GetClipboardText(void); // Get clipboard text content +RLAPI Image GetClipboardImage(void); // Get clipboard image RLAPI void EnableEventWaiting(void); // Enable waiting for events on EndDrawing(), no automatic event polling RLAPI void DisableEventWaiting(void); // Disable waiting for events on EndDrawing(), automatic events polling @@ -87,7 +88,7 @@ RLAPI void UnloadVrStereoConfig(VrStereoConfig config); // Unload VR s // NOTE: Shader functionality is not available on OpenGL 1.1 RLAPI Shader LoadShader(const char *vsFileName, const char *fsFileName); // Load shader from files and bind default locations RLAPI Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode); // Load shader from code strings and bind default locations -RLAPI bool IsShaderReady(Shader shader); // Check if a shader is ready +RLAPI bool IsShaderValid(Shader shader); // Check if a shader is valid (loaded on GPU) RLAPI int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location RLAPI int GetShaderLocationAttrib(Shader shader, const char *attribName); // Get shader attribute location RLAPI void SetShaderValue(Shader shader, int locIndex, const void *value, int uniformType); // Set shader uniform value @@ -97,13 +98,15 @@ RLAPI void SetShaderValueTexture(Shader shader, int locIndex, Texture2D texture) RLAPI void UnloadShader(Shader shader); // Unload shader from GPU memory (VRAM) // Screen-space-related functions -RLAPI Ray GetMouseRay(Vector2 mousePosition, Camera camera); // Get a ray trace from mouse position -RLAPI Matrix GetCameraMatrix(Camera camera); // Get camera transform matrix (view matrix) -RLAPI Matrix GetCameraMatrix2D(Camera2D camera); // Get camera 2d transform matrix -RLAPI Vector2 GetWorldToScreen(Vector3 position, Camera camera); // Get the screen space position for a 3d world space position -RLAPI Vector2 GetScreenToWorld2D(Vector2 position, Camera2D camera); // Get the world space position for a 2d camera screen space position +#define GetMouseRay GetScreenToWorldRay // Compatibility hack for previous raylib versions +RLAPI Ray GetScreenToWorldRay(Vector2 position, Camera camera); // Get a ray trace from screen position (i.e mouse) +RLAPI Ray GetScreenToWorldRayEx(Vector2 position, Camera camera, int width, int height); // Get a ray trace from screen position (i.e mouse) in a viewport +RLAPI Vector2 GetWorldToScreen(Vector3 position, Camera camera); // Get the screen space position for a 3d world space position RLAPI Vector2 GetWorldToScreenEx(Vector3 position, Camera camera, int width, int height); // Get size position for a 3d world space position -RLAPI Vector2 GetWorldToScreen2D(Vector2 position, Camera2D camera); // Get the screen space position for a 2d camera world space position +RLAPI Vector2 GetWorldToScreen2D(Vector2 position, Camera2D camera); // Get the screen space position for a 2d camera world space position +RLAPI Vector2 GetScreenToWorld2D(Vector2 position, Camera2D camera); // Get the world space position for a 2d camera screen space position +RLAPI Matrix GetCameraMatrix(Camera camera); // Get camera transform matrix (view matrix) +RLAPI Matrix GetCameraMatrix2D(Camera2D camera); // Get camera 2d transform matrix // Timing-related functions RLAPI void SetTargetFPS(int fps); // Set target FPS (maximum) @@ -112,6 +115,9 @@ RLAPI double GetTime(void); // Get elapsed RLAPI int GetFPS(void); // Get current FPS // Custom frame control functions +// NOTE: Those functions are intended for advanced users that want full control over the frame processing +// By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timing + PollInputEvents() +// To avoid that behaviour and control frame processes manually, enable in config.h: SUPPORT_CUSTOM_FRAME_CONTROL RLAPI void SwapScreenBuffer(void); // Swap back buffer with front buffer (screen drawing) RLAPI void PollInputEvents(void); // Register all input events RLAPI void WaitTime(double seconds); // Wait for some time (halt program execution) @@ -127,6 +133,8 @@ RLAPI void TakeScreenshot(const char *fileName); // Takes a scr RLAPI void SetConfigFlags(unsigned int flags); // Setup init configuration flags (view FLAGS) RLAPI void OpenURL(const char *url); // Open URL with default system browser (if available) +// NOTE: Following functions implemented in module [utils] +//------------------------------------------------------------------ RLAPI void TraceLog(int logLevel, const char *text, ...); // Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...) RLAPI void SetTraceLogLevel(int logLevel); // Set the current threshold (minimum) log level RLAPI void *MemAlloc(unsigned int size); // Internal memory allocator @@ -149,6 +157,7 @@ RLAPI bool ExportDataAsCode(const unsigned char *data, int dataSize, const char RLAPI char *LoadFileText(const char *fileName); // Load text data from file (read), returns a '\0' terminated string RLAPI void UnloadFileText(char *text); // Unload file text data allocated by LoadFileText() RLAPI bool SaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated, returns true on success +//------------------------------------------------------------------ // File system functions RLAPI bool FileExists(const char *fileName); // Check if file exists @@ -162,10 +171,12 @@ RLAPI const char *GetDirectoryPath(const char *filePath); // Get full pa RLAPI const char *GetPrevDirectoryPath(const char *dirPath); // Get previous directory path for a given path (uses static string) RLAPI const char *GetWorkingDirectory(void); // Get current working directory (uses static string) RLAPI const char *GetApplicationDirectory(void); // Get the directory of the running application (uses static string) +RLAPI int MakeDirectory(const char *dirPath); // Create directories (including full path requested), returns 0 on success RLAPI bool ChangeDirectory(const char *dir); // Change working directory, return true on success RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory +RLAPI bool IsFileNameValid(const char *fileName); // Check if fileName is valid for the platform/OS RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths -RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and recursive directory scan +RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result RLAPI void UnloadDirectoryFiles(FilePathList files); // Unload filepaths RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window RLAPI FilePathList LoadDroppedFiles(void); // Load dropped filepaths @@ -177,10 +188,14 @@ 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 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 int ComputeCRC32(unsigned char *data, int dataSize); // Compute CRC32 hash code +RLAPI unsigned int *ComputeMD5(unsigned char *data, int dataSize); // Compute MD5 hash code, returns static int[4] (16 bytes) +RLAPI unsigned int *ComputeSHA1(unsigned char *data, int dataSize); // Compute SHA1 hash code, returns static int[5] (20 bytes) + // Automation events functionality 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 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 @@ -194,25 +209,27 @@ RLAPI void PlayAutomationEvent(AutomationEvent event); // Input-related functions: keyboard RLAPI bool IsKeyPressed(int key); // Check if a key has been pressed once -RLAPI bool IsKeyPressedRepeat(int key); // Check if a key has been pressed again (Only PLATFORM_DESKTOP) +RLAPI bool IsKeyPressedRepeat(int key); // Check if a key has been pressed again RLAPI bool IsKeyDown(int key); // Check if a key is being pressed RLAPI bool IsKeyReleased(int key); // Check if a key has been released once 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 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 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 -RLAPI bool IsGamepadAvailable(int gamepad); // Check if a gamepad is available -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 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 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 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 int SetGamepadMappings(const char *mappings); // Set internal gamepad mappings (SDL_GameControllerDB) +RLAPI bool IsGamepadAvailable(int gamepad); // Check if a gamepad is available +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 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 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 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 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) // Input-related functions: mouse RLAPI bool IsMouseButtonPressed(int button); // Check if a mouse button has been pressed once @@ -243,7 +260,7 @@ RLAPI int GetTouchPointCount(void); // Get number of t 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 int GetGestureDetected(void); // Get latest detected gesture -RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds +RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in seconds RLAPI Vector2 GetGestureDragVector(void); // Get gesture drag vector RLAPI float GetGestureDragAngle(void); // Get gesture drag angle RLAPI Vector2 GetGesturePinchVector(void); // Get gesture pinch delta @@ -262,19 +279,21 @@ RLAPI void UpdateCameraPro(Camera *camera, Vector3 movement, Vector3 rotation, f // 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 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 Rectangle GetShapesTextureRectangle(void); // Get texture source rectangle that is used for shapes drawing // Basic shapes drawing functions -RLAPI void DrawPixel(int posX, int posY, Color color); // Draw a pixel -RLAPI void DrawPixelV(Vector2 position, Color color); // Draw a pixel (Vector version) +RLAPI void DrawPixel(int posX, int posY, Color color); // Draw a pixel using geometry [Can be slow, use with care] +RLAPI void DrawPixelV(Vector2 position, Color color); // Draw a pixel using geometry (Vector version) [Can be slow, use with care] RLAPI void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color); // Draw a line RLAPI void DrawLineV(Vector2 startPos, Vector2 endPos, Color color); // Draw a line (using gl lines) RLAPI void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line (using triangles/quads) -RLAPI void DrawLineStrip(Vector2 *points, int pointCount, Color color); // Draw lines sequence (using gl lines) +RLAPI void DrawLineStrip(const Vector2 *points, int pointCount, Color color); // Draw lines sequence (using gl lines) RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw line segment cubic-bezier in-out interpolation RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle RLAPI void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw circle sector outline -RLAPI void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2); // Draw a gradient-filled circle +RLAPI void DrawCircleGradient(int centerX, int centerY, float radius, Color inner, Color outer); // Draw a gradient-filled circle RLAPI void DrawCircleV(Vector2 center, float radius, Color color); // Draw a color-filled circle (Vector version) RLAPI void DrawCircleLines(int centerX, int centerY, float radius, Color color); // Draw circle outline RLAPI void DrawCircleLinesV(Vector2 center, float radius, Color color); // Draw circle outline (Vector version) @@ -286,27 +305,28 @@ RLAPI void DrawRectangle(int posX, int posY, int width, int height, Color color) RLAPI void DrawRectangleV(Vector2 position, Vector2 size, Color color); // Draw a color-filled rectangle (Vector version) RLAPI void DrawRectangleRec(Rectangle rec, Color color); // Draw a color-filled rectangle RLAPI void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color); // Draw a color-filled rectangle with pro parameters -RLAPI void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2);// Draw a vertical-gradient-filled rectangle -RLAPI void DrawRectangleGradientH(int posX, int posY, int width, int height, Color color1, Color color2);// Draw a horizontal-gradient-filled rectangle -RLAPI void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4); // Draw a gradient-filled rectangle with custom vertex colors +RLAPI void DrawRectangleGradientV(int posX, int posY, int width, int height, Color top, Color bottom); // Draw a vertical-gradient-filled rectangle +RLAPI void DrawRectangleGradientH(int posX, int posY, int width, int height, Color left, Color right); // Draw a horizontal-gradient-filled rectangle +RLAPI void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Color topRight, Color bottomRight); // Draw a gradient-filled rectangle with custom vertex colors RLAPI void DrawRectangleLines(int posX, int posY, int width, int height, Color color); // Draw rectangle outline RLAPI void DrawRectangleLinesEx(Rectangle rec, float lineThick, Color color); // Draw rectangle outline with extended parameters RLAPI void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color color); // Draw rectangle with rounded edges -RLAPI void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, float lineThick, Color color); // Draw rectangle with rounded edges outline +RLAPI void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, Color color); // Draw rectangle lines with rounded edges +RLAPI void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, float lineThick, Color color); // Draw rectangle with rounded edges outline RLAPI void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw a color-filled triangle (vertex in counter-clockwise order!) RLAPI void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline (vertex in counter-clockwise order!) -RLAPI void DrawTriangleFan(Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points (first vertex is the center) -RLAPI void DrawTriangleStrip(Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points +RLAPI void DrawTriangleFan(const Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points (first vertex is the center) +RLAPI void DrawTriangleStrip(const Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points RLAPI void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a regular polygon (Vector version) RLAPI void DrawPolyLines(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a polygon outline of n sides RLAPI void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, float lineThick, Color color); // Draw a polygon outline of n sides with extended parameters // Splines drawing functions -RLAPI void DrawSplineLinear(Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Linear, minimum 2 points -RLAPI void DrawSplineBasis(Vector2 *points, int pointCount, float thick, Color color); // Draw spline: B-Spline, minimum 4 points -RLAPI void DrawSplineCatmullRom(Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Catmull-Rom, minimum 4 points -RLAPI void DrawSplineBezierQuadratic(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(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 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 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 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 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 @@ -324,12 +344,13 @@ RLAPI Vector2 GetSplinePointBezierCubic(Vector2 p1, Vector2 c2, Vector2 c3, Vect RLAPI bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2); // Check collision between two rectangles RLAPI bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, float radius2); // Check collision between two circles RLAPI bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec); // Check collision between circle and rectangle +RLAPI bool CheckCollisionCircleLine(Vector2 center, float radius, Vector2 p1, Vector2 p2); // Check if circle collides with a line created betweeen two points [p1] and [p2] RLAPI bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle RLAPI bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius); // Check if point is inside circle RLAPI bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2 p3); // Check if point is inside a triangle -RLAPI bool CheckCollisionPointPoly(Vector2 point, Vector2 *points, int pointCount); // Check if point is within a polygon described by array of vertices -RLAPI bool CheckCollisionLines(Vector2 startPos1, Vector2 endPos1, Vector2 startPos2, Vector2 endPos2, Vector2 *collisionPoint); // Check the collision between two lines defined by two points each, returns collision point by reference RLAPI bool CheckCollisionPointLine(Vector2 point, Vector2 p1, Vector2 p2, int threshold); // Check if point belongs to line created between two points [p1] and [p2] with defined margin in pixels [threshold] +RLAPI bool CheckCollisionPointPoly(Vector2 point, const Vector2 *points, int pointCount); // Check if point is within a polygon described by array of vertices +RLAPI bool CheckCollisionLines(Vector2 startPos1, Vector2 endPos1, Vector2 startPos2, Vector2 endPos2, Vector2 *collisionPoint); // Check the collision between two lines defined by two points each, returns collision point by reference RLAPI Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2); // Get collision rectangle for two rectangles collision //------------------------------------------------------------------------------------ @@ -340,12 +361,12 @@ RLAPI Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2); // NOTE: These functions do not require GPU access RLAPI Image LoadImage(const char *fileName); // Load image from file into CPU memory (RAM) RLAPI Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize); // Load image from RAW file data -RLAPI Image LoadImageSvg(const char *fileNameOrString, int width, int height); // Load image from SVG file data or string with specified size RLAPI Image LoadImageAnim(const char *fileName, int *frames); // Load image sequence from file (frames appended to image.data) +RLAPI Image LoadImageAnimFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int *frames); // Load image sequence from memory buffer RLAPI Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load image from memory buffer, fileType refers to extension: i.e. '.png' RLAPI Image LoadImageFromTexture(Texture2D texture); // Load image from GPU texture data RLAPI Image LoadImageFromScreen(void); // Load image from screen buffer and (screenshot) -RLAPI bool IsImageReady(Image image); // Check if an image is ready +RLAPI bool IsImageValid(Image image); // Check if an image is valid (data and parameters) RLAPI void UnloadImage(Image image); // Unload image from CPU memory (RAM) RLAPI bool ExportImage(Image image, const char *fileName); // Export image data to file, returns true on success RLAPI unsigned char *ExportImageToMemory(Image image, const char *fileType, int *fileSize); // Export image to memory buffer @@ -365,6 +386,7 @@ RLAPI Image GenImageText(int width, int height, const char *text); // Image manipulation functions RLAPI Image ImageCopy(Image image); // Create an image duplicate (useful for transformations) RLAPI Image ImageFromImage(Image image, Rectangle rec); // Create an image from another image piece +RLAPI Image ImageFromChannel(Image image, int selectedChannel); // Create an image from a selected channel of another image (GRAYSCALE) RLAPI Image ImageText(const char *text, int fontSize, Color color); // Create an image from text (default font) RLAPI Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Color tint); // Create an image from text (custom sprite font) RLAPI void ImageFormat(Image *image, int newFormat); // Convert image data to desired format @@ -375,10 +397,10 @@ RLAPI void ImageAlphaClear(Image *image, Color color, float threshold); RLAPI void ImageAlphaMask(Image *image, Image alphaMask); // Apply alpha mask to image RLAPI void ImageAlphaPremultiply(Image *image); // Premultiply alpha channel RLAPI void ImageBlurGaussian(Image *image, int blurSize); // Apply Gaussian blur using a box blur approximation -RLAPI void ImageKernelConvolution(Image *image, float* kernel, int kernelSize); // Apply Custom Square image convolution kernel +RLAPI void ImageKernelConvolution(Image *image, const float *kernel, int kernelSize); // Apply custom square convolution kernel to image RLAPI void ImageResize(Image *image, int newWidth, int newHeight); // Resize image (Bicubic scaling algorithm) RLAPI void ImageResizeNN(Image *image, int newWidth,int newHeight); // Resize image (Nearest-Neighbor scaling algorithm) -RLAPI void ImageResizeCanvas(Image *image, int newWidth, int newHeight, int offsetX, int offsetY, Color fill); // Resize canvas and fill with color +RLAPI void ImageResizeCanvas(Image *image, int newWidth, int newHeight, int offsetX, int offsetY, Color fill); // Resize canvas and fill with color RLAPI void ImageMipmaps(Image *image); // Compute all mipmap levels for a provided image RLAPI void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp); // Dither image data to 16bpp or lower (Floyd-Steinberg dithering) RLAPI void ImageFlipVertical(Image *image); // Flip image vertically @@ -406,6 +428,7 @@ RLAPI void ImageDrawPixel(Image *dst, int posX, int posY, Color color); RLAPI void ImageDrawPixelV(Image *dst, Vector2 position, Color color); // Draw pixel within an image (Vector version) RLAPI void ImageDrawLine(Image *dst, int startPosX, int startPosY, int endPosX, int endPosY, Color color); // Draw line within an image RLAPI void ImageDrawLineV(Image *dst, Vector2 start, Vector2 end, Color color); // Draw line within an image (Vector version) +RLAPI void ImageDrawLineEx(Image *dst, Vector2 start, Vector2 end, int thick, Color color); // Draw a line defining thickness within an image RLAPI void ImageDrawCircle(Image *dst, int centerX, int centerY, int radius, Color color); // Draw a filled circle within an image RLAPI void ImageDrawCircleV(Image *dst, Vector2 center, int radius, Color color); // Draw a filled circle within an image (Vector version) RLAPI void ImageDrawCircleLines(Image *dst, int centerX, int centerY, int radius, Color color); // Draw circle outline within an image @@ -414,6 +437,11 @@ RLAPI void ImageDrawRectangle(Image *dst, int posX, int posY, int width, int hei RLAPI void ImageDrawRectangleV(Image *dst, Vector2 position, Vector2 size, Color color); // Draw rectangle within an image (Vector version) RLAPI void ImageDrawRectangleRec(Image *dst, Rectangle rec, Color color); // Draw rectangle within an image RLAPI void ImageDrawRectangleLines(Image *dst, Rectangle rec, int thick, Color color); // Draw rectangle lines within an image +RLAPI void ImageDrawTriangle(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle within an image +RLAPI void ImageDrawTriangleEx(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3); // Draw triangle with interpolated colors within an image +RLAPI void ImageDrawTriangleLines(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline within an image +RLAPI void ImageDrawTriangleFan(Image *dst, Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points within an image (first vertex is the center) +RLAPI void ImageDrawTriangleStrip(Image *dst, Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points within an image RLAPI void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec, Color tint); // Draw a source image within a destination image (tint applied to source) RLAPI void ImageDrawText(Image *dst, const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font) within an image (destination) RLAPI void ImageDrawTextEx(Image *dst, Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text (custom sprite font) within an image (destination) @@ -424,9 +452,9 @@ RLAPI Texture2D LoadTexture(const char *fileName); RLAPI Texture2D LoadTextureFromImage(Image image); // Load texture from image data RLAPI TextureCubemap LoadTextureCubemap(Image image, int layout); // Load cubemap from image, multiple image cubemap layouts supported RLAPI RenderTexture2D LoadRenderTexture(int width, int height); // Load texture for rendering (framebuffer) -RLAPI bool IsTextureReady(Texture2D texture); // Check if a texture is ready +RLAPI bool IsTextureValid(Texture2D texture); // Check if a texture is valid (loaded in GPU) RLAPI void UnloadTexture(Texture2D texture); // Unload texture from GPU memory (VRAM) -RLAPI bool IsRenderTextureReady(RenderTexture2D target); // Check if a render texture is ready +RLAPI bool IsRenderTextureValid(RenderTexture2D target); // Check if a render texture is valid (loaded in GPU) RLAPI void UnloadRenderTexture(RenderTexture2D target); // Unload render texture from GPU memory (VRAM) RLAPI void UpdateTexture(Texture2D texture, const void *pixels); // Update GPU texture with new data RLAPI void UpdateTextureRec(Texture2D texture, Rectangle rec, const void *pixels); // Update GPU texture rectangle with new data @@ -445,8 +473,9 @@ RLAPI void DrawTexturePro(Texture2D texture, Rectangle source, Rectangle dest, V RLAPI void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle dest, Vector2 origin, float rotation, Color tint); // Draws a texture (or part of it) that stretches or shrinks nicely // Color/pixel related functions +RLAPI bool ColorIsEqual(Color col1, Color col2); // Check if two colors are equal RLAPI Color Fade(Color color, float alpha); // Get color with alpha applied, alpha goes from 0.0f to 1.0f -RLAPI int ColorToInt(Color color); // Get hexadecimal value for a Color +RLAPI int ColorToInt(Color color); // Get hexadecimal value for a Color (0xRRGGBBAA) RLAPI Vector4 ColorNormalize(Color color); // Get Color normalized as float [0..1] RLAPI Color ColorFromNormalized(Vector4 normalized); // Get Color from normalized values [0..1] RLAPI Vector3 ColorToHSV(Color color); // Get HSV values for a Color, hue [0..360], saturation/value [0..1] @@ -456,6 +485,7 @@ RLAPI Color ColorBrightness(Color color, float factor); // G RLAPI Color ColorContrast(Color color, float contrast); // Get color with contrast correction, contrast values between -1.0f and 1.0f RLAPI Color ColorAlpha(Color color, float alpha); // Get color with alpha applied, alpha goes from 0.0f to 1.0f RLAPI Color ColorAlphaBlend(Color dst, Color src, Color tint); // Get src alpha-blended into dst color with tint +RLAPI Color ColorLerp(Color color1, Color color2, float factor); // Get color lerp interpolation between two colors, factor [0.0f..1.0f] RLAPI Color GetColor(unsigned int hexValue); // Get Color structure from hexadecimal value RLAPI Color GetPixelColor(void *srcPtr, int format); // Get Color from a source pixel pointer of certain format RLAPI void SetPixelColor(void *dstPtr, Color color, int format); // Set color formatted into destination pixel pointer @@ -468,10 +498,10 @@ RLAPI int GetPixelDataSize(int width, int height, int format); // G // Font loading/unloading functions RLAPI Font GetFontDefault(void); // Get the default Font RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM) -RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set +RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style) RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf' -RLAPI bool IsFontReady(Font font); // Check if a font is ready +RLAPI bool IsFontValid(Font font); // Check if a font is valid (font data loaded, WARNING: GPU texture not checked) RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount, int type); // Load font data for further use RLAPI Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyphCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info RLAPI void UnloadFontData(GlyphInfo *glyphs, int glyphCount); // Unload font chars info data (RAM) @@ -512,7 +542,7 @@ RLAPI bool TextIsEqual(const char *text1, const char *text2); RLAPI unsigned int TextLength(const char *text); // Get text length, checks for '\0' ending RLAPI const char *TextFormat(const char *text, ...); // Text formatting with variables (sprintf() style) RLAPI const char *TextSubtext(const char *text, int position, int length); // Get a piece of a text string -RLAPI char *TextReplace(char *text, const char *replace, const char *by); // Replace text string (WARNING: memory must be freed!) +RLAPI char *TextReplace(const char *text, const char *replace, const char *by); // Replace text string (WARNING: memory must be freed!) RLAPI char *TextInsert(const char *text, const char *insert, int position); // Insert text in a position (WARNING: memory must be freed!) RLAPI const char *TextJoin(const char **textList, int count, const char *delimiter); // Join text strings with delimiter RLAPI const char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings @@ -521,7 +551,11 @@ RLAPI int TextFindIndex(const char *text, const char *find); 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 *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 *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 float TextToFloat(const char *text); // Get float value from text (negative values not supported) //------------------------------------------------------------------------------------ // Basic 3d Shapes Drawing Functions (Module: models) @@ -532,7 +566,7 @@ RLAPI void DrawLine3D(Vector3 startPos, Vector3 endPos, Color color); RLAPI void DrawPoint3D(Vector3 position, Color color); // Draw a point in 3D space, actually a small line RLAPI void DrawCircle3D(Vector3 center, float radius, Vector3 rotationAxis, float rotationAngle, Color color); // Draw a circle in 3D world space RLAPI void DrawTriangle3D(Vector3 v1, Vector3 v2, Vector3 v3, Color color); // Draw a color-filled triangle (vertex in counter-clockwise order!) -RLAPI void DrawTriangleStrip3D(Vector3 *points, int pointCount, Color color); // Draw a triangle strip defined by points +RLAPI void DrawTriangleStrip3D(const Vector3 *points, int pointCount, Color color); // Draw a triangle strip defined by points RLAPI void DrawCube(Vector3 position, float width, float height, float length, Color color); // Draw cube RLAPI void DrawCubeV(Vector3 position, Vector3 size, Color color); // Draw cube (Vector version) RLAPI void DrawCubeWires(Vector3 position, float width, float height, float length, Color color); // Draw cube wires @@ -557,7 +591,7 @@ RLAPI void DrawGrid(int slices, float spacing); // Model management functions RLAPI Model LoadModel(const char *fileName); // Load model from files (meshes and materials) RLAPI Model LoadModelFromMesh(Mesh mesh); // Load model from generated mesh (default material) -RLAPI bool IsModelReady(Model model); // Check if a model is ready +RLAPI bool IsModelValid(Model model); // Check if a model is valid (loaded in GPU, VAO/VBOs) RLAPI void UnloadModel(Model model); // Unload model (including meshes) from memory (RAM and/or VRAM) RLAPI BoundingBox GetModelBoundingBox(Model model); // Compute model bounding box limits (considers all meshes) @@ -566,8 +600,10 @@ RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint); RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set) RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters +RLAPI void DrawModelPoints(Model model, Vector3 position, float scale, Color tint); // Draw a model as points +RLAPI void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model as points with extended parameters RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires) -RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float size, Color tint); // Draw a billboard texture +RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint); // Draw a billboard texture RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source RLAPI void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector3 up, Vector2 size, Vector2 origin, float rotation, Color tint); // Draw a billboard texture defined by source and rotation @@ -577,9 +613,10 @@ RLAPI void UpdateMeshBuffer(Mesh mesh, int index, const void *data, int dataSize RLAPI void UnloadMesh(Mesh mesh); // Unload mesh data from CPU and GPU RLAPI void DrawMesh(Mesh mesh, Material material, Matrix transform); // Draw a 3d mesh with material and transform RLAPI void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, int instances); // Draw multiple mesh instances with material and different transforms -RLAPI bool ExportMesh(Mesh mesh, const char *fileName); // Export mesh data to file, returns true on success RLAPI BoundingBox GetMeshBoundingBox(Mesh mesh); // Compute mesh bounding box limits RLAPI void GenMeshTangents(Mesh *mesh); // Compute mesh tangents +RLAPI bool ExportMesh(Mesh mesh, const char *fileName); // Export mesh data to file, returns true on success +RLAPI bool ExportMeshAsCode(Mesh mesh, const char *fileName); // Export mesh as code file (.h) defining multiple arrays of vertex attributes // Mesh generation functions RLAPI Mesh GenMeshPoly(int sides, float radius); // Generate polygonal mesh @@ -597,14 +634,15 @@ RLAPI Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize); // Material loading/unloading functions RLAPI Material *LoadMaterials(const char *fileName, int *materialCount); // Load materials from model file RLAPI Material LoadMaterialDefault(void); // Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps) -RLAPI bool IsMaterialReady(Material material); // Check if a material is ready +RLAPI bool IsMaterialValid(Material material); // Check if a material is valid (shader assigned, map textures loaded in GPU) RLAPI void UnloadMaterial(Material material); // Unload material from GPU memory (VRAM) RLAPI void SetMaterialTexture(Material *material, int mapType, Texture2D texture); // Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...) RLAPI void SetModelMeshMaterial(Model *model, int meshId, int materialId); // Set material for a mesh // Model animations loading/unloading functions RLAPI ModelAnimation *LoadModelAnimations(const char *fileName, int *animCount); // Load model animations from file -RLAPI void UpdateModelAnimation(Model model, ModelAnimation anim, int frame); // Update model animation pose +RLAPI void UpdateModelAnimation(Model model, ModelAnimation anim, int frame); // Update model animation pose (CPU) +RLAPI void UpdateModelAnimationBones(Model model, ModelAnimation anim, int frame); // Update model animation mesh bone matrices (GPU skinning) RLAPI void UnloadModelAnimation(ModelAnimation anim); // Unload animation data RLAPI void UnloadModelAnimations(ModelAnimation *animations, int animCount); // Unload animation array data RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match @@ -634,11 +672,11 @@ RLAPI float GetMasterVolume(void); // Get mas // Wave/Sound loading/unloading functions RLAPI Wave LoadWave(const char *fileName); // Load wave data from file RLAPI Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load wave from memory buffer, fileType refers to extension: i.e. '.wav' -RLAPI bool IsWaveReady(Wave wave); // Checks if wave data is ready +RLAPI bool IsWaveValid(Wave wave); // Checks if wave data is valid (data loaded and parameters) RLAPI Sound LoadSound(const char *fileName); // Load sound from file RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound from wave data RLAPI Sound LoadSoundAlias(Sound source); // Create a new sound that shares the same sample data as the source sound, does not own the sound data -RLAPI bool IsSoundReady(Sound sound); // Checks if a sound is ready +RLAPI bool IsSoundValid(Sound sound); // Checks if a sound is valid (data loaded and buffers initialized) RLAPI void UpdateSound(Sound sound, const void *data, int sampleCount); // Update sound buffer with new data RLAPI void UnloadWave(Wave wave); // Unload wave data RLAPI void UnloadSound(Sound sound); // Unload sound @@ -656,7 +694,7 @@ RLAPI void SetSoundVolume(Sound sound, float volume); // Set vol RLAPI void SetSoundPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level) RLAPI void SetSoundPan(Sound sound, float pan); // Set pan for a sound (0.5 is center) RLAPI Wave WaveCopy(Wave wave); // Copy a wave to a new wave -RLAPI void WaveCrop(Wave *wave, int initSample, int finalSample); // Crop a wave to defined samples range +RLAPI void WaveCrop(Wave *wave, int initFrame, int finalFrame); // Crop a wave to defined frames range RLAPI void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels); // Convert wave data to desired format RLAPI float *LoadWaveSamples(Wave wave); // Load samples data from wave as a 32bit float data array RLAPI void UnloadWaveSamples(float *samples); // Unload samples data loaded with LoadWaveSamples() @@ -664,7 +702,7 @@ RLAPI void UnloadWaveSamples(float *samples); // Unload // Music management functions RLAPI Music LoadMusicStream(const char *fileName); // Load music stream from file RLAPI Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data, int dataSize); // Load music stream from data -RLAPI bool IsMusicReady(Music music); // Checks if a music stream is ready +RLAPI bool IsMusicValid(Music music); // Checks if a music stream is valid (context and buffers initialized) RLAPI void UnloadMusicStream(Music music); // Unload music stream RLAPI void PlayMusicStream(Music music); // Start music playing RLAPI bool IsMusicStreamPlaying(Music music); // Check if music is playing @@ -681,7 +719,7 @@ RLAPI float GetMusicTimePlayed(Music music); // Get cur // AudioStream management functions RLAPI AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, unsigned int channels); // Load audio stream (to stream raw audio pcm data) -RLAPI bool IsAudioStreamReady(AudioStream stream); // Checks if an audio stream is ready +RLAPI bool IsAudioStreamValid(AudioStream stream); // Checks if an audio stream is valid (buffers initialized) RLAPI void UnloadAudioStream(AudioStream stream); // Unload audio stream and free memory RLAPI void UpdateAudioStream(AudioStream stream, const void *data, int frameCount); // Update audio stream buffers with data RLAPI bool IsAudioStreamProcessed(AudioStream stream); // Check if any audio stream buffers requires refill @@ -696,9 +734,9 @@ RLAPI void SetAudioStreamPan(AudioStream stream, float pan); // Set pan RLAPI void SetAudioStreamBufferSizeDefault(int size); // Default size for new audio streams RLAPI void SetAudioStreamCallback(AudioStream stream, AudioCallback callback); // Audio thread callback to request new data -RLAPI void AttachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Attach audio stream processor to stream, receives the samples as s +RLAPI void AttachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Attach audio stream processor to stream, receives the samples as 'float' RLAPI void DetachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Detach audio stream processor from stream -RLAPI void AttachAudioMixedProcessor(AudioCallback processor); // Attach audio stream processor to the entire audio pipeline, receives the samples as s +RLAPI void AttachAudioMixedProcessor(AudioCallback processor); // Attach audio stream processor to the entire audio pipeline, receives the samples as 'float' RLAPI void DetachAudioMixedProcessor(AudioCallback processor); // Detach audio stream processor from the entire audio pipeline diff --git a/projects/VS2022/examples/core_input_gamepad_info.vcxproj b/projects/VS2022/examples/core_input_virtual_controls.vcxproj similarity index 98% rename from projects/VS2022/examples/core_input_gamepad_info.vcxproj rename to projects/VS2022/examples/core_input_virtual_controls.vcxproj index 7227ef2f4..c5a043b74 100644 --- a/projects/VS2022/examples/core_input_gamepad_info.vcxproj +++ b/projects/VS2022/examples/core_input_virtual_controls.vcxproj @@ -35,11 +35,11 @@ - {27AA7BDA-0C34-4733-9009-73D3E64234FB} + {0981CA28-E4A5-4DF1-987F-A41D09131EFC} Win32Proj - core_input_gamepad_info + core_input_virtual_controls 10.0 - core_input_gamepad_info + core_input_virtual_controls @@ -374,7 +374,7 @@ - + diff --git a/projects/VS2022/examples/models_bone_socket.vcxproj b/projects/VS2022/examples/models_bone_socket.vcxproj new file mode 100644 index 000000000..9d89856b0 --- /dev/null +++ b/projects/VS2022/examples/models_bone_socket.vcxproj @@ -0,0 +1,387 @@ + + + + + Debug.DLL + Win32 + + + Debug.DLL + x64 + + + Debug + Win32 + + + Debug + x64 + + + Release.DLL + Win32 + + + Release.DLL + x64 + + + Release + Win32 + + + Release + x64 + + + + {3A7FE53D-35F7-49DC-9C9A-A5204A53523F} + Win32Proj + models_bone_socket + 10.0 + models_bone_socket + + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + false + $(DefaultPlatformToolset) + true + Unicode + + + Application + false + $(DefaultPlatformToolset) + true + Unicode + + + Application + false + $(DefaultPlatformToolset) + true + Unicode + + + Application + false + $(DefaultPlatformToolset) + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + true + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + true + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + true + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + $(SolutionDir)..\..\examples\models + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\models + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\models + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\models + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\models + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\models + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\models + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\models + WindowsLocalDebugger + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) + CompileAsC + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + + + Console + true + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) + CompileAsC + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + /FS %(AdditionalOptions) + + + Console + true + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) + CompileAsC + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + + + Console + true + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" + Copy Debug DLL to output directory + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) + CompileAsC + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + + + Console + true + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" + Copy Debug DLL to output directory + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + CompileAsC + true + + + Console + true + true + true + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + CompileAsC + true + + + Console + true + true + true + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + CompileAsC + true + + + Console + true + true + true + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + + + xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" + + + Copy Release DLL to output directory + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + CompileAsC + true + + + Console + true + true + true + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + + + xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" + + + Copy Release DLL to output directory + + + + + + + + {e89d61ac-55de-4482-afd4-df7242ebc859} + + + + + + \ No newline at end of file diff --git a/projects/VS2022/examples/shaders_vertex_displacement.vcxproj b/projects/VS2022/examples/shaders_vertex_displacement.vcxproj new file mode 100644 index 000000000..294d5f76d --- /dev/null +++ b/projects/VS2022/examples/shaders_vertex_displacement.vcxproj @@ -0,0 +1,387 @@ + + + + + Debug.DLL + Win32 + + + Debug.DLL + x64 + + + Debug + Win32 + + + Debug + x64 + + + Release.DLL + Win32 + + + Release.DLL + x64 + + + Release + Win32 + + + Release + x64 + + + + {CCA63A76-D9FC-4130-9F67-4D97F9770D53} + Win32Proj + shaders_vertex_displacement + 10.0 + shaders_vertex_displacement + + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + false + $(DefaultPlatformToolset) + true + Unicode + + + Application + false + $(DefaultPlatformToolset) + true + Unicode + + + Application + false + $(DefaultPlatformToolset) + true + Unicode + + + Application + false + $(DefaultPlatformToolset) + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + true + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + true + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + true + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + $(SolutionDir)..\..\examples\shaders + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shaders + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shaders + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shaders + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shaders + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shaders + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shaders + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shaders + WindowsLocalDebugger + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) + CompileAsC + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + + + Console + true + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) + CompileAsC + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + /FS %(AdditionalOptions) + + + Console + true + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) + CompileAsC + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + + + Console + true + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" + Copy Debug DLL to output directory + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) + CompileAsC + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + + + Console + true + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" + Copy Debug DLL to output directory + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + CompileAsC + true + + + Console + true + true + true + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + CompileAsC + true + + + Console + true + true + true + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + CompileAsC + true + + + Console + true + true + true + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + + + xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" + + + Copy Release DLL to output directory + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + CompileAsC + true + + + Console + true + true + true + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + + + xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" + + + Copy Release DLL to output directory + + + + + + + + {e89d61ac-55de-4482-afd4-df7242ebc859} + + + + + + \ No newline at end of file diff --git a/projects/VS2022/examples/shapes_rectangle_advanced.vcxproj b/projects/VS2022/examples/shapes_rectangle_advanced.vcxproj index 9e5a04710..7ec07e4b3 100644 --- a/projects/VS2022/examples/shapes_rectangle_advanced.vcxproj +++ b/projects/VS2022/examples/shapes_rectangle_advanced.vcxproj @@ -35,7 +35,7 @@ - {703BE7BA-5B99-4F70-806D-3A259F6A991E} + {FAFEE2F9-24B0-4AF1-B512-433E9590033F} Win32Proj shapes_rectangle_advanced 10.0 @@ -387,4 +387,4 @@ - + \ No newline at end of file diff --git a/projects/VS2022/raylib.sln b/projects/VS2022/raylib.sln index e2f512d81..f4f0600e1 100644 --- a/projects/VS2022/raylib.sln +++ b/projects/VS2022/raylib.sln @@ -279,8 +279,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_automation_events", "e EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "audio_mixed_processor", "examples\audio_mixed_processor.vcxproj", "{A4B0D971-3CD6-41C9-8AB2-055D25A33373}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_input_gamepad_info", "examples\core_input_gamepad_info.vcxproj", "{27AA7BDA-0C34-4733-9009-73D3E64234FB}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_input_mouse_wheel", "examples\core_input_mouse_wheel.vcxproj", "{15CDD310-6980-42A6-8082-3A6B7730D13F}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_smooth_pixelperfect", "examples\core_smooth_pixelperfect.vcxproj", "{71DB4284-5B1C-4E86-9AF5-B91542D44A6F}" @@ -297,13 +295,17 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_splines_drawing", "e EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_top_down_lights", "examples\shapes_top_down_lights.vcxproj", "{703BE7BA-5B99-4F70-806D-3A259F6A991E}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_rectangle_advanced", "examples\shapes_rectangle_advanced.vcxproj", "{703BE7BA-5B99-4F70-806D-3A259F6A991E}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_rectangle_advanced", "examples\shapes_rectangle_advanced.vcxproj", "{FAFEE2F9-24B0-4AF1-B512-433E9590033F}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models_gpu_skinning", "examples\models_gpu_skinning.vcxproj", "{8245DAD9-D402-4D5C-8F45-32229CD3B263}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shaders_shadowmap", "examples\shaders_shadowmap.vcxproj", "{41BBCC10-6FDE-48A1-B2E0-A0EC6A668629}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_input_virtual_controls", "examples\core_input_virtual_controls.vcxproj", "{92B64AE7-D773-6F03-89F1-CE59BBF4F053}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_input_virtual_controls", "examples\core_input_virtual_controls.vcxproj", "{0981CA28-E4A5-4DF1-987F-A41D09131EFC}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models_bone_socket", "examples\models_bone_socket.vcxproj", "{3A7FE53D-35F7-49DC-9C9A-A5204A53523F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shaders_vertex_displacement", "examples\shaders_vertex_displacement.vcxproj", "{CCA63A76-D9FC-4130-9F67-4D97F9770D53}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -689,16 +691,12 @@ Global {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|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.Build.0 = Debug|Win32 {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.Build.0 = Release.DLL|Win32 {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.Build.0 = Release|Win32 {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|x86.ActiveCfg = Debug.DLL|Win32 @@ -2521,6 +2519,22 @@ Global {703BE7BA-5B99-4F70-806D-3A259F6A991E}.Release|x64.Build.0 = Release|x64 {703BE7BA-5B99-4F70-806D-3A259F6A991E}.Release|x86.ActiveCfg = Release|Win32 {703BE7BA-5B99-4F70-806D-3A259F6A991E}.Release|x86.Build.0 = Release|Win32 + {FAFEE2F9-24B0-4AF1-B512-433E9590033F}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {FAFEE2F9-24B0-4AF1-B512-433E9590033F}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {FAFEE2F9-24B0-4AF1-B512-433E9590033F}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {FAFEE2F9-24B0-4AF1-B512-433E9590033F}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {FAFEE2F9-24B0-4AF1-B512-433E9590033F}.Debug|x64.ActiveCfg = Debug|x64 + {FAFEE2F9-24B0-4AF1-B512-433E9590033F}.Debug|x64.Build.0 = Debug|x64 + {FAFEE2F9-24B0-4AF1-B512-433E9590033F}.Debug|x86.ActiveCfg = Debug|Win32 + {FAFEE2F9-24B0-4AF1-B512-433E9590033F}.Debug|x86.Build.0 = Debug|Win32 + {FAFEE2F9-24B0-4AF1-B512-433E9590033F}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {FAFEE2F9-24B0-4AF1-B512-433E9590033F}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {FAFEE2F9-24B0-4AF1-B512-433E9590033F}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {FAFEE2F9-24B0-4AF1-B512-433E9590033F}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {FAFEE2F9-24B0-4AF1-B512-433E9590033F}.Release|x64.ActiveCfg = Release|x64 + {FAFEE2F9-24B0-4AF1-B512-433E9590033F}.Release|x64.Build.0 = Release|x64 + {FAFEE2F9-24B0-4AF1-B512-433E9590033F}.Release|x86.ActiveCfg = Release|Win32 + {FAFEE2F9-24B0-4AF1-B512-433E9590033F}.Release|x86.Build.0 = Release|Win32 {8245DAD9-D402-4D5C-8F45-32229CD3B263}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 {8245DAD9-D402-4D5C-8F45-32229CD3B263}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 {8245DAD9-D402-4D5C-8F45-32229CD3B263}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 @@ -2553,22 +2567,54 @@ Global {41BBCC10-6FDE-48A1-B2E0-A0EC6A668629}.Release|x64.Build.0 = Release|x64 {41BBCC10-6FDE-48A1-B2E0-A0EC6A668629}.Release|x86.ActiveCfg = Release|Win32 {41BBCC10-6FDE-48A1-B2E0-A0EC6A668629}.Release|x86.Build.0 = Release|Win32 - {92B64AE7-D773-6F03-89F1-CE59BBF4F053}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {92B64AE7-D773-6F03-89F1-CE59BBF4F053}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {92B64AE7-D773-6F03-89F1-CE59BBF4F053}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {92B64AE7-D773-6F03-89F1-CE59BBF4F053}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {92B64AE7-D773-6F03-89F1-CE59BBF4F053}.Debug|x64.ActiveCfg = Debug|x64 - {92B64AE7-D773-6F03-89F1-CE59BBF4F053}.Debug|x64.Build.0 = Debug|x64 - {92B64AE7-D773-6F03-89F1-CE59BBF4F053}.Debug|x86.ActiveCfg = Debug|Win32 - {92B64AE7-D773-6F03-89F1-CE59BBF4F053}.Debug|x86.Build.0 = Debug|Win32 - {92B64AE7-D773-6F03-89F1-CE59BBF4F053}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {92B64AE7-D773-6F03-89F1-CE59BBF4F053}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {92B64AE7-D773-6F03-89F1-CE59BBF4F053}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {92B64AE7-D773-6F03-89F1-CE59BBF4F053}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {92B64AE7-D773-6F03-89F1-CE59BBF4F053}.Release|x64.ActiveCfg = Release|x64 - {92B64AE7-D773-6F03-89F1-CE59BBF4F053}.Release|x64.Build.0 = Release|x64 - {92B64AE7-D773-6F03-89F1-CE59BBF4F053}.Release|x86.ActiveCfg = Release|Win32 - {92B64AE7-D773-6F03-89F1-CE59BBF4F053}.Release|x86.Build.0 = Release|Win32 + {0981CA28-E4A5-4DF1-987F-A41D09131EFC}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {0981CA28-E4A5-4DF1-987F-A41D09131EFC}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {0981CA28-E4A5-4DF1-987F-A41D09131EFC}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {0981CA28-E4A5-4DF1-987F-A41D09131EFC}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {0981CA28-E4A5-4DF1-987F-A41D09131EFC}.Debug|x64.ActiveCfg = Debug|x64 + {0981CA28-E4A5-4DF1-987F-A41D09131EFC}.Debug|x64.Build.0 = Debug|x64 + {0981CA28-E4A5-4DF1-987F-A41D09131EFC}.Debug|x86.ActiveCfg = Debug|Win32 + {0981CA28-E4A5-4DF1-987F-A41D09131EFC}.Debug|x86.Build.0 = Debug|Win32 + {0981CA28-E4A5-4DF1-987F-A41D09131EFC}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {0981CA28-E4A5-4DF1-987F-A41D09131EFC}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {0981CA28-E4A5-4DF1-987F-A41D09131EFC}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {0981CA28-E4A5-4DF1-987F-A41D09131EFC}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {0981CA28-E4A5-4DF1-987F-A41D09131EFC}.Release|x64.ActiveCfg = Release|x64 + {0981CA28-E4A5-4DF1-987F-A41D09131EFC}.Release|x64.Build.0 = Release|x64 + {0981CA28-E4A5-4DF1-987F-A41D09131EFC}.Release|x86.ActiveCfg = Release|Win32 + {0981CA28-E4A5-4DF1-987F-A41D09131EFC}.Release|x86.Build.0 = Release|Win32 + {3A7FE53D-35F7-49DC-9C9A-A5204A53523F}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {3A7FE53D-35F7-49DC-9C9A-A5204A53523F}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {3A7FE53D-35F7-49DC-9C9A-A5204A53523F}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {3A7FE53D-35F7-49DC-9C9A-A5204A53523F}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {3A7FE53D-35F7-49DC-9C9A-A5204A53523F}.Debug|x64.ActiveCfg = Debug|x64 + {3A7FE53D-35F7-49DC-9C9A-A5204A53523F}.Debug|x64.Build.0 = Debug|x64 + {3A7FE53D-35F7-49DC-9C9A-A5204A53523F}.Debug|x86.ActiveCfg = Debug|Win32 + {3A7FE53D-35F7-49DC-9C9A-A5204A53523F}.Debug|x86.Build.0 = Debug|Win32 + {3A7FE53D-35F7-49DC-9C9A-A5204A53523F}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {3A7FE53D-35F7-49DC-9C9A-A5204A53523F}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {3A7FE53D-35F7-49DC-9C9A-A5204A53523F}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {3A7FE53D-35F7-49DC-9C9A-A5204A53523F}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {3A7FE53D-35F7-49DC-9C9A-A5204A53523F}.Release|x64.ActiveCfg = Release|x64 + {3A7FE53D-35F7-49DC-9C9A-A5204A53523F}.Release|x64.Build.0 = Release|x64 + {3A7FE53D-35F7-49DC-9C9A-A5204A53523F}.Release|x86.ActiveCfg = Release|Win32 + {3A7FE53D-35F7-49DC-9C9A-A5204A53523F}.Release|x86.Build.0 = Release|Win32 + {CCA63A76-D9FC-4130-9F67-4D97F9770D53}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {CCA63A76-D9FC-4130-9F67-4D97F9770D53}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {CCA63A76-D9FC-4130-9F67-4D97F9770D53}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {CCA63A76-D9FC-4130-9F67-4D97F9770D53}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {CCA63A76-D9FC-4130-9F67-4D97F9770D53}.Debug|x64.ActiveCfg = Debug|x64 + {CCA63A76-D9FC-4130-9F67-4D97F9770D53}.Debug|x64.Build.0 = Debug|x64 + {CCA63A76-D9FC-4130-9F67-4D97F9770D53}.Debug|x86.ActiveCfg = Debug|Win32 + {CCA63A76-D9FC-4130-9F67-4D97F9770D53}.Debug|x86.Build.0 = Debug|Win32 + {CCA63A76-D9FC-4130-9F67-4D97F9770D53}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {CCA63A76-D9FC-4130-9F67-4D97F9770D53}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {CCA63A76-D9FC-4130-9F67-4D97F9770D53}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {CCA63A76-D9FC-4130-9F67-4D97F9770D53}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {CCA63A76-D9FC-4130-9F67-4D97F9770D53}.Release|x64.ActiveCfg = Release|x64 + {CCA63A76-D9FC-4130-9F67-4D97F9770D53}.Release|x64.Build.0 = Release|x64 + {CCA63A76-D9FC-4130-9F67-4D97F9770D53}.Release|x86.ActiveCfg = Release|Win32 + {CCA63A76-D9FC-4130-9F67-4D97F9770D53}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -2719,9 +2765,12 @@ Global {EFA150D4-F93B-4D7D-A69C-9E8B4663BECD} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} {DF25E545-00FF-4E64-844C-7DF98991F901} = {278D8859-20B1-428F-8448-064F46E1F021} {703BE7BA-5B99-4F70-806D-3A259F6A991E} = {278D8859-20B1-428F-8448-064F46E1F021} + {FAFEE2F9-24B0-4AF1-B512-433E9590033F} = {278D8859-20B1-428F-8448-064F46E1F021} {8245DAD9-D402-4D5C-8F45-32229CD3B263} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C} {41BBCC10-6FDE-48A1-B2E0-A0EC6A668629} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} - {92B64AE7-D773-6F03-89F1-CE59BBF4F053} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} + {0981CA28-E4A5-4DF1-987F-A41D09131EFC} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} + {3A7FE53D-35F7-49DC-9C9A-A5204A53523F} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C} + {CCA63A76-D9FC-4130-9F67-4D97F9770D53} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29} diff --git a/projects/VS2022/raylib/raylib.vcxproj b/projects/VS2022/raylib/raylib.vcxproj index 0c03027a4..347ff5d11 100644 --- a/projects/VS2022/raylib/raylib.vcxproj +++ b/projects/VS2022/raylib/raylib.vcxproj @@ -302,6 +302,76 @@ + + true + true + true + true + true + true + true + true + + + true + true + true + true + true + true + true + true + + + true + true + true + true + true + true + true + true + + + true + true + true + true + true + true + true + true + + + true + true + true + true + true + true + true + true + + + true + true + true + true + true + true + true + true + + + true + true + true + true + true + true + true + true + diff --git a/projects/VS2022/raylib/raylib.vcxproj.filters b/projects/VS2022/raylib/raylib.vcxproj.filters new file mode 100644 index 000000000..182358229 --- /dev/null +++ b/projects/VS2022/raylib/raylib.vcxproj.filters @@ -0,0 +1,120 @@ + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files\Platform Files + + + Source Files\Platform Files + + + Source Files\Platform Files + + + Source Files\Platform Files + + + Source Files\Platform Files + + + Source Files\Platform Files + + + Source Files\Platform Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + + + + {88e8d1f8-5c93-4f9e-a856-819a1f82a387} + + + {cba93591-3674-4384-9325-bc0ae2d72b9b} + + + {d18433d7-0e5c-40d7-a39d-e0f11f80d183} + + + \ No newline at end of file diff --git a/projects/VSCode/Makefile b/projects/VSCode/Makefile index 65a6f9544..389a12cf9 100644 --- a/projects/VSCode/Makefile +++ b/projects/VSCode/Makefile @@ -117,7 +117,7 @@ endif ifeq ($(PLATFORM),PLATFORM_WEB) # Emscripten required variables - EMSDK_PATH ?= C:/emsdk + EMSDK_PATH ?= C:/raylib/emsdk EMSCRIPTEN_PATH ?= $(EMSDK_PATH)/upstream/emscripten CLANG_PATH = $(EMSDK_PATH)/upstream/bin PYTHON_PATH = $(EMSDK_PATH)/python/3.9.2-nuget_64bit @@ -225,21 +225,23 @@ endif ifeq ($(PLATFORM),PLATFORM_WEB) # -Os # size optimization # -O2 # optimization level 2, if used, also set --memory-init-file 0 - # -s USE_GLFW=3 # Use glfw3 library (context/input management) - # -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL! - # -s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) - # -s USE_PTHREADS=1 # multithreading support - # -s WASM=0 # disable Web Assembly, emitted by default - # -s EMTERPRETIFY=1 # enable emscripten code interpreter (very slow) - # -s EMTERPRETIFY_ASYNC=1 # support synchronous loops by emterpreter - # -s FORCE_FILESYSTEM=1 # force filesystem to load/save files data - # -s ASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off) + # -sUSE_GLFW=3 # Use glfw3 library (context/input management) + # -sALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL! + # -sTOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) (67108864 = 64MB) + # -sUSE_PTHREADS=1 # multithreading support + # -sWASM=0 # disable Web Assembly, emitted by default + # -sASYNCIFY # lets synchronous C/C++ code interact with asynchronous JS + # -sFORCE_FILESYSTEM=1 # force filesystem to load/save files data + # -sASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off) + # -sMINIFY_HTML=0 # minify generated html from shell.html # --profiling # include information for code profiling # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) # --preload-file resources # specify a resources folder for data compilation - CFLAGS += -Os -s USE_GLFW=3 -s TOTAL_MEMORY=16777216 --preload-file resources + # --source-map-base # allow debugging in browser with source map + # --shell-file shell.html # define a custom shell .html and output extension + CFLAGS += -Os -sUSE_GLFW=3 -sTOTAL_MEMORY=16777216 --preload-file resources -sMINIFY_HTML=0 ifeq ($(BUILD_MODE), DEBUG) - CFLAGS += -s ASSERTIONS=1 --profiling + CFLAGS += -sASSERTIONS=1 --profiling endif # Define a custom shell .html and output extension diff --git a/projects/VSCode/main.c b/projects/VSCode/main.c index 5a2e342bd..cad32c2ef 100644 --- a/projects/VSCode/main.c +++ b/projects/VSCode/main.c @@ -15,7 +15,7 @@ * This example has been created using raylib 1.0 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * -* Copyright (c) 2013-2024 Ramon Santamaria (@raysan5) +* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9735e267f..a7313a0b4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -23,6 +23,7 @@ endif() # Used as public API to be included into other projects set(raylib_public_headers raylib.h + rcamera.h rlgl.h raymath.h ) diff --git a/src/Makefile b/src/Makefile index 1f0b730c6..a626db52e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -20,6 +20,8 @@ # - Linux (X11 desktop mode) # - macOS/OSX (x64, arm64 (not tested)) # - Others (not tested) +# > PLATFORM_WEB_RGFW: +# - HTML5 (WebAssembly) # > PLATFORM_WEB: # - HTML5 (WebAssembly) # > PLATFORM_DRM: @@ -31,7 +33,7 @@ # Many thanks to Milan Nikolic (@gen2brain) for implementing Android platform pipeline. # Many thanks to Emanuele Petriglia for his contribution on GNU/Linux pipeline. # -# Copyright (c) 2013-2024 Ramon Santamaria (@raysan5) +# Copyright (c) 2013-2025 Ramon Santamaria (@raysan5) # # This software is provided "as-is", without any express or implied warranty. In no event # will the authors be held liable for any damages arising from the use of this software. @@ -59,11 +61,10 @@ #------------------------------------------------------------------------------------------------ # Define target platform PLATFORM ?= PLATFORM_DESKTOP - ifeq ($(PLATFORM), PLATFORM_DESKTOP) - TARGET_PLATFORM = PLATFORM_DESKTOP_GLFW + TARGET_PLATFORM = PLATFORM_DESKTOP_GLFW else - TARGET_PLATFORM = $(PLATFORM) + TARGET_PLATFORM = $(PLATFORM) endif # Define required raylib variables @@ -118,6 +119,7 @@ GLFW_LINUX_ENABLE_X11 ?= TRUE # WARNING: Library is not included in raylib, it MUST be configured by users SDL_INCLUDE_PATH ?= $(RAYLIB_SRC_PATH)/external/SDL2/include SDL_LIBRARY_PATH ?= $(RAYLIB_SRC_PATH)/external/SDL2/lib +SDL_LIBRARIES ?= -lSDL2 -lSDL2main # 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") @@ -128,7 +130,7 @@ HOST_PLATFORM_OS ?= WINDOWS PLATFORM_OS ?= WINDOWS # Determine PLATFORM_OS when required -ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW PLATFORM_DESKTOP_SDL PLATFORM_DESKTOP_RGFW PLATFORM_WEB PLATFORM_ANDROID)) +ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW PLATFORM_DESKTOP_SDL PLATFORM_DESKTOP_RGFW PLATFORM_WEB PLATFORM_WEB_RGFW PLATFORM_ANDROID)) # No uname.exe on MinGW!, but OS=Windows_NT on Windows! # ifeq ($(UNAME),Msys) -> Windows ifeq ($(OS),Windows_NT) @@ -170,7 +172,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) PLATFORM_SHELL = sh endif endif -ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) +ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) ifeq ($(PLATFORM_OS),LINUX) ifndef PLATFORM_SHELL PLATFORM_SHELL = sh @@ -178,10 +180,10 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) endif endif -ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) +ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) ifeq ($(PLATFORM_OS), WINDOWS) # Emscripten required variables - EMSDK_PATH ?= C:/emsdk + EMSDK_PATH ?= C:/raylib/emsdk EMSCRIPTEN_PATH ?= $(EMSDK_PATH)/upstream/emscripten CLANG_PATH := $(EMSDK_PATH)/upstream/bin PYTHON_PATH := $(EMSDK_PATH)/python/3.9.2-nuget_64bit @@ -252,7 +254,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) # On DRM OpenGL ES 2.0 must be used GRAPHICS = GRAPHICS_API_OPENGL_ES2 endif -ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) +ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) # On HTML5 OpenGL ES 2.0 is used, emscripten translates it to WebGL 1.0 GRAPHICS = GRAPHICS_API_OPENGL_ES2 #GRAPHICS = GRAPHICS_API_OPENGL_ES3 @@ -286,7 +288,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) AR = $(RPI_TOOLCHAIN)/bin/$(RPI_TOOLCHAIN_NAME)-ar endif endif -ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) +ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) # HTML5 emscripten compiler CC = emcc AR = emar @@ -329,7 +331,7 @@ ifneq ($(RAYLIB_CONFIG_FLAGS), NONE) CFLAGS += -DEXTERNAL_CONFIG_FLAGS $(RAYLIB_CONFIG_FLAGS) endif -ifeq ($(TARGET_PLATFORM), PLATFORM_WEB) +ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) # NOTE: When using multi-threading in the user code, it requires -pthread enabled CFLAGS += -std=gnu99 else @@ -345,7 +347,7 @@ ifeq ($(RAYLIB_BUILD_MODE),DEBUG) endif ifeq ($(RAYLIB_BUILD_MODE),RELEASE) - ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) + ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) CFLAGS += -Os endif ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) @@ -364,23 +366,26 @@ endif ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) CFLAGS += -Werror=implicit-function-declaration endif -ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) +ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) # -Os # size optimization # -O2 # optimization level 2, if used, also set --memory-init-file 0 - # -sUSE_GLFW=3 # Use glfw3 library (context/input management) -> Only for linker! - # -sALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL! - # -sTOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) - # -sUSE_PTHREADS=1 # multithreading support - # -sFORCE_FILESYSTEM=1 # force filesystem to load/save files data - # -sASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off) - # -sGL_ENABLE_GET_PROC_ADDRESS # enable using the *glGetProcAddress() family of functions, required for extensions loading + # -sUSE_GLFW=3 # Use glfw3 library (context/input management) + # -sALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL! + # -sTOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) (67108864 = 64MB) + # -sUSE_PTHREADS=1 # multithreading support + # -sWASM=0 # disable Web Assembly, emitted by default + # -sASYNCIFY # lets synchronous C/C++ code interact with asynchronous JS + # -sFORCE_FILESYSTEM=1 # force filesystem to load/save files data + # -sASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off) + # -sMINIFY_HTML=0 # minify generated html from shell.html # --profiling # include information for code profiling # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) # --preload-file resources # specify a resources folder for data compilation + # --source-map-base # allow debugging in browser with source map + # --shell-file shell.html # define a custom shell .html and output extension ifeq ($(RAYLIB_BUILD_MODE),DEBUG) CFLAGS += -sASSERTIONS=1 --profiling endif - #CFLAGS += -sGL_ENABLE_GET_PROC_ADDRESS endif ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) # Compiler flags for arquitecture @@ -460,7 +465,7 @@ CFLAGS += $(CUSTOM_CFLAGS) # Define include paths for required headers: INCLUDE_PATHS # NOTE: Several external required libraries (stb and others) #------------------------------------------------------------------------------------------------ -INCLUDE_PATHS = -I. +INCLUDE_PATHS = -I. $(EXTRA_INCLUDE_PATHS) # Define additional directories containing required header files ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) @@ -586,7 +591,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_SDL) LDLIBS += -lX11 endif endif - LDLIBS += -lSDL2 -lSDL2main + LDLIBS += $(SDL_LIBRARIES) endif ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_RGFW) ifeq ($(PLATFORM_OS),WINDOWS) @@ -657,11 +662,11 @@ all: raylib # Compile raylib library # NOTE: Release directory is created if not exist raylib: $(OBJS) -ifeq ($(TARGET_PLATFORM),PLATFORM_WEB) +ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) # Compile raylib libray for web #$(CC) $(OBJS) -r -o $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).bc - $(AR) rcs $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).a $(OBJS) - @echo "raylib library generated (lib$(RAYLIB_LIB_NAME).a)!" + $(AR) rcs $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).web.a $(OBJS) + @echo "raylib library generated (lib$(RAYLIB_LIB_NAME).web.a)!" else ifeq ($(RAYLIB_LIBTYPE),SHARED) ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW PLATFORM_DESKTOP_SDL PLATFORM_DESKTOP_RGFW)) diff --git a/src/config.h b/src/config.h index f37a9de3e..f7b015305 100644 --- a/src/config.h +++ b/src/config.h @@ -6,7 +6,7 @@ * * LICENSE: zlib/libpng * -* Copyright (c) 2018-2024 Ahmad Fatoum & Ramon Santamaria (@raysan5) +* Copyright (c) 2018-2025 Ahmad Fatoum & Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. @@ -71,6 +71,31 @@ // Enabling this flag allows manual control of the frame processes, use at your own risk //#define SUPPORT_CUSTOM_FRAME_CONTROL 1 +// Support for clipboard image loading +// NOTE: Only working on SDL3, GLFW (Windows) and RGFW (Windows) +#define SUPPORT_CLIPBOARD_IMAGE 1 + +// NOTE: Clipboard image loading requires support for some image file formats +// TODO: Those defines should probably be removed from here, I prefer to let the user manage them +#if defined(SUPPORT_CLIPBOARD_IMAGE) + #ifndef SUPPORT_MODULE_RTEXTURES + #define SUPPORT_MODULE_RTEXTURES 1 + #endif + #ifndef STBI_REQUIRED + #define STBI_REQUIRED + #endif + #ifndef SUPPORT_FILEFORMAT_BMP // For clipboard image on Windows + #define SUPPORT_FILEFORMAT_BMP 1 + #endif + #ifndef SUPPORT_FILEFORMAT_PNG // Wayland uses png for prints, at least it was on 22 LTS ubuntu + #define SUPPORT_FILEFORMAT_PNG 1 + #endif + #ifndef SUPPORT_FILEFORMAT_JPG + #define SUPPORT_FILEFORMAT_JPG 1 + #endif +#endif + + // rcore: Configuration values //------------------------------------------------------------------------------------ #define MAX_FILEPATH_CAPACITY 8192 // Maximum file paths capacity @@ -126,6 +151,8 @@ #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS 7 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 8 #endif +#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INSTANCE_TX 9 + // 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 diff --git a/src/external/RGFW.h b/src/external/RGFW.h index 978536f2d..d4ec7d77f 100644 --- a/src/external/RGFW.h +++ b/src/external/RGFW.h @@ -1,5 +1,8 @@ /* -* Copyright (C) 2023-24 ColleagueRiley +* +* RGFW 1.5.1-dev +* +* Copyright (C) 2022-25 ColleagueRiley * * libpng license * @@ -29,7 +32,7 @@ /* #define RGFW_IMPLEMENTATION - (required) makes it so the source code is included - #define RGFW_PRINT_ERRORS - (optional) makes it so RGFW prints errors when they're found + #define RGFW_DEBUG - (optional) makes it so RGFW prints debug messages anderrors when they're found #define RGFW_OSMESA - (optional) use OSmesa as backend (instead of system's opengl api + regular opengl) #define RGFW_BUFFER - (optional) just draw directly to (RGFW) window pixel buffer that is drawn to screen (the buffer is in the RGBA format) #define RGFW_EGL - (optional) use EGL for loading an OpenGL context (instead of the system's opengl api) @@ -42,52 +45,117 @@ #define RGFW_NO_API - (optional) don't use any rendering API (no opengl, no vulkan, no directX) #define RGFW_LINK_EGL (optional) (windows only) if EGL is being used, if EGL functions should be defined dymanically (using GetProcAddress) - #define RGFW_LINK_OSMESA (optional) (windows only) if EGL is being used, if OS Mesa functions should be defined dymanically (using GetProcAddress) - #define RGFW_X11 (optional) (unix only) if X11 should be used. This option is turned on by default by unix systems except for MacOS - #define RGFW_WGL_LOAD (optional) (windows only) if WGL should be loaded dynamically during runtime + #define RGFW_WAYLAND (optional) (unix only) if Wayland should be used. (This can be used with X11) + #define RGFW_NO_X11 (optional) (unix only) if X11 should be used (with Wayland). + #define RGFW_NO_LOAD_WGL (optional) (windows only) if WGL should be loaded dynamically during runtime #define RGFW_NO_X11_CURSOR (optional) (unix only) don't use XCursor #define RGFW_NO_X11_CURSOR_PRELOAD (optional) (unix only) Use XCursor, but don't link it in code, (you'll have to link it with -lXcursor) + #define RGFW_NO_LOAD_WINMM (optional) (windows only) Use winmm (timeBeginPeriod), but don't link it in code, (you'll have to link it with -lwinmm) + #define RGFW_NO_WINMM (optional) (windows only) don't use winmm + #define RGFW_NO_IOKIT (optional) (macOS) don't use IOKit + #define RGFW_NO_UNIX_CLOCK (optional) (unux) don't link unix clock functions + #define RGFW_NO_DWM (windows only) - Do not use or linj dwmapi + #define RGFW_USE_XDL (optional) (X11) use X11 in RGFW (must include XDL.h along with RGFW) (XLib Dynamic Loader) #define RGFW_NO_DPI - Do not include calculate DPI (no XRM nor libShcore included) #define RGFW_ALLOC_DROPFILES (optional) if room should be allocating for drop files (by default it's global data) - #define RGFW_MALLOC x - choose what function to use to allocate, by default the standard malloc is used - #define RGFW_CALLOC x - choose what function to use to allocate (calloc), by default the standard calloc is used - #define RGFW_FREE x - choose what function to use to allocated memory, by default the standard free is used + #define RGFW_alloc(userptr, size) x - choose what default function to use to allocate, by default the standard malloc is used + #define RGFW_free(userptr, ptr) x - choose what default function to use to allocated memory, by default the standard free is used + #define RGFW_USERPTR x - choose the default userptr sent to the malloc call, (NULL by default) - #define RGFW_EXPORT - Use when building RGFW + #define RGFW_EXPORT - Use when building RGFW #define RGFW_IMPORT - Use when linking with RGFW (not as a single-header) - - #define RGFW_STD_INT - force the use stdint.h (for systems that might not have stdint.h (msvc)) + + #define RGFW_USE_INT - force the use c-types rather than stdint.h (for systems that might not have stdint.h (msvc)) */ +/* +Example to get you started : + +linux : gcc main.c -lX11 -lXrandr -lGL +windows : gcc main.c -lopengl32 -lgdi32 +macos : gcc main.c -framework Cocoa -framework OpenGL -framework IOKit + +#define RGFW_IMPLEMENTATION +#include "RGFW.h" + +u8 icon[4 * 3 * 3] = {0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF}; + +int main() { + RGFW_window* win = RGFW_createWindow("name", RGFW_RECT(100, 100, 500, 500), (u64)0); + + RGFW_window_setIcon(win, icon, RGFW_AREA(3, 3), 4); + + for (;;) { + RGFW_window_checkEvent(win); // NOTE: checking events outside of a while loop may cause input lag + if (win->event.type == RGFW_quit || RGFW_isPressed(win, RGFW_escape)) + break; + + RGFW_window_swapBuffers(win); + + glClearColor(1, 1, 1, 1); + glClear(GL_COLOR_BUFFER_BIT); + } + + RGFW_window_close(win); +} + + compiling : + + if you wish to compile the library all you have to do is create a new file with this in it + + rgfw.c + #define RGFW_IMPLEMENTATION + #include "RGFW.h" + + You may also want to add + `#define RGFW_EXPORT` when compiling and + `#define RGFW_IMPORT`when linking RGFW on it's own: + this reduces inline functions and prevents bloat in the object file + + then you can use gcc (or whatever compile you wish to use) to compile the library into object file + + ex. gcc -c RGFW.c -fPIC + + after you compile the library into an object file, you can also turn the object file into an static or shared library + + (commands ar and gcc can be replaced with whatever equivalent your system uses) + + static : ar rcs RGFW.a RGFW.o + shared : + windows: + gcc -shared RGFW.o -lopengl32 -lgdi32 -o RGFW.dll + linux: + gcc -shared RGFW.o -lX11 -lGL -lXrandr -o RGFW.so + macos: + gcc -shared RGFW.o -framework Cocoa -framework OpenGL -framework IOKit +*/ + + + /* Credits : - EimaMei/Sacode : Much of the code for creating windows using winapi, Wrote the Silicon library, helped with MacOS Support, siliapp.h -> referencing + EimaMei/Sacode : Much of the code for creating windows using winapi, Wrote the Silicon library, helped with MacOS Support, siliapp.h -> referencing stb - This project is heavily inspired by the stb single header files GLFW: certain parts of winapi and X11 are very poorly documented, - GLFW's source code was referenced and used throughout the project (used code is marked in some way), - this mainly includes, code for drag and drops, code for setting the icon to a bitmap and the code for managing the clipboard for X11 (as these parts are not documented very well) - - GLFW Copyright, https::/github.com/GLFW/GLFW - - Copyright (c) 2002-2006 Marcus Geelnard - Copyright (c) 2006-2019 Camilla Löwy - + GLFW's source code was referenced and used throughout the project. + contributors : (feel free to put yourself here if you contribute) krisvers -> code review EimaMei (SaCode) -> code review Code-Nycticebus -> bug fixes - Rob Rohan -> X11 bugs and missing features, MacOS/Cocoa fixing memory issues/bugs + Rob Rohan -> X11 bugs and missing features, MacOS/Cocoa fixing memory issues/bugs AICDG (@THISISAGOODNAME) -> vulkan support (example) @Easymode -> support, testing/debugging, bug fixes and reviews Joshua Rowe (omnisci3nce) - bug fix, review (macOS) @lesleyrs -> bug fix, review (OpenGL) Nick Porcino (meshula) - testing, organization, review (MacOS, examples) + @DarekParodia -> code review (X11) (C++) */ #if _MSC_VER @@ -98,17 +166,38 @@ #pragma comment(lib, "user32") #endif -#ifndef RGFW_MALLOC +#ifndef RGFW_UNUSED + #define RGFW_UNUSED(x) (void)(x) +#endif + +#ifndef RGFW_USERPTR + #define RGFW_USERPTR NULL +#endif + +#ifndef RGFW_ROUND +#define RGFW_ROUND(x) (int)((x) >= 0 ? (x) + 0.5f : (x) - 0.5f) +#endif + +#ifndef RGFW_ALLOC #include #ifndef __USE_POSIX199309 #define __USE_POSIX199309 #endif - #include - #define RGFW_MALLOC malloc - #define RGFW_CALLOC calloc - #define RGFW_FREE free + #define RGFW_ALLOC(userptr, size) (RGFW_UNUSED(userptr),malloc(size)) + #define RGFW_FREE(userptr, ptr) (RGFW_UNUSED(userptr),free(ptr)) +#endif + +#ifndef RGFW_MEMCPY + #include + + #define RGFW_MEMCPY(dist, src, len) memcpy(dist, src, len) + #define RGFW_STRNCMP(s1, s2, max) strncmp(s1, s2, max) + //required for X11 + #define RGFW_STRTOL(str, endptr, base) strtol(str, endptr, base) +#else +#undef _INC_STRING #endif #if !_MSC_VER @@ -132,7 +221,7 @@ #if defined(RGFW_EXPORT) #define RGFWDEF __declspec(dllexport) - #else + #else #define RGFWDEF __declspec(dllimport) #endif #else @@ -140,25 +229,22 @@ #define RGFWDEF __attribute__((visibility("default"))) #endif #endif -#endif +#endif #ifndef RGFWDEF - #ifdef __clang__ - #define RGFWDEF static inline - #else - #define RGFWDEF inline - #endif + #define RGFWDEF inline #endif #ifndef RGFW_ENUM #define RGFW_ENUM(type, name) type name; enum #endif -#ifndef RGFW_UNUSED - #define RGFW_UNUSED(x) (void)(x); -#endif #if defined(__cplusplus) && !defined(__EMSCRIPTEN__) + #ifdef __clang__ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wnullability-completeness" + #endif extern "C" { #endif @@ -168,17 +254,18 @@ #define RGFW_HEADER #if !defined(u8) - #if ((defined(_MSC_VER) || defined(__SYMBIAN32__)) && !defined(RGFW_STD_INT)) /* MSVC might not have stdint.h */ + #ifdef RGFW_USE_INT /* optional for any system that might not have stdint.h */ typedef unsigned char u8; typedef signed char i8; typedef unsigned short u16; typedef signed short i16; - typedef unsigned int u32; - typedef signed int i32; - typedef unsigned long u64; - typedef signed long i64; + typedef unsigned long int u32; + typedef signed long int i32; + typedef unsigned long long u64; + typedef signed long long i64; #else /* use stdint standard types instead of c ""standard"" types */ #include + #include typedef uint8_t u8; typedef int8_t i8; @@ -189,11 +276,13 @@ typedef uint64_t u64; typedef int64_t i64; #endif + #define u8 u8 #endif #if !defined(b8) /* RGFW bool type */ typedef u8 b8; typedef u32 b32; + #define b8 b8 #endif #define RGFW_TRUE (!(0)) @@ -221,14 +310,14 @@ #endif #endif -#if defined(RGFW_X11) && defined(__APPLE__) +#if defined(RGFW_X11) && defined(__APPLE__) && !defined(RGFW_CUSTOM_BACKEND) #define RGFW_MACOS_X11 + #define RGFW_UNIX #undef __APPLE__ #endif -#if defined(_WIN32) && !defined(RGFW_X11) && !defined(RGFW_WEBASM) /* (if you're using X11 on windows some how) */ +#if defined(_WIN32) && !defined(RGFW_UNIX) && !defined(RGFW_WEBASM) && !defined(RGFW_CUSTOM_BACKEND) /* (if you're using X11 on windows some how) */ #define RGFW_WINDOWS - /* make sure the correct architecture is defined */ #if defined(_WIN64) #define _AMD64_ @@ -249,6 +338,7 @@ #endif #if defined(RGFW_DIRECTX) + #define OEMRESOURCE #include #include #include @@ -260,18 +350,22 @@ #endif #elif defined(RGFW_WAYLAND) - #if !defined(RGFW_NO_API) && (!defined(RGFW_BUFFER) || defined(RGFW_OPENGL)) + #define RGFW_DEBUG // wayland will be in debug mode by default for now + #if !defined(RGFW_NO_API) && (!defined(RGFW_BUFFER) || defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA) #define RGFW_EGL #define RGFW_OPENGL + #define RGFW_UNIX #include #endif #include -#elif (defined(__unix__) || defined(RGFW_MACOS_X11) || defined(RGFW_X11)) && !defined(RGFW_WEBASM) +#endif +#if !defined(RGFW_NO_X11) && !defined(RGFW_NO_X11) && (defined(__unix__) || defined(RGFW_MACOS_X11) || defined(RGFW_X11)) && !defined(RGFW_WEBASM) && !defined(RGFW_CUSTOM_BACKEND) #define RGFW_MACOS_X11 #define RGFW_X11 + #define RGFW_UNIX #include -#elif defined(__APPLE__) && !defined(RGFW_MACOS_X11) && !defined(RGFW_X11) && !defined(RGFW_WEBASM) +#elif defined(__APPLE__) && !defined(RGFW_MACOS_X11) && !defined(RGFW_X11) && !defined(RGFW_WEBASM) && !defined(RGFW_CUSTOM_BACKEND) #define RGFW_MACOS #endif @@ -286,6 +380,13 @@ #ifdef RGFW_EGL #include #elif defined(RGFW_OSMESA) + #ifdef RGFW_WINDOWS + #define OEMRESOURCE + #include + #define GLAPIENTRY APIENTRY + #define GLAPI WINGDIAPI + #endif + #ifndef __APPLE__ #include #else @@ -300,61 +401,71 @@ #include /* GLX defs, xlib.h, gl.h */ #endif -#ifndef RGFW_ALPHA - #define RGFW_ALPHA 128 /* alpha value for RGFW_TRANSPARENT_WINDOW (WINAPI ONLY, macOS + linux don't need this) */ -#endif +/*! (unix) Toggle use of wayland, this will be on by default if you use `RGFW_WAYLAND` (if you don't use RGFW_WAYLAND, you dont' expose WAYLAND functions) + this is mostly used to allow you to force the use of XWayland +*/ +RGFWDEF void RGFW_useWayland(b8 wayland); -/*! Optional arguments for making a windows */ -#define RGFW_TRANSPARENT_WINDOW (1L<<9) /*!< the window is transparent (only properly works on X11 and MacOS, although it's although for windows) */ -#define RGFW_NO_BORDER (1L<<3) /*!< the window doesn't have border */ -#define RGFW_NO_RESIZE (1L<<4) /*!< the window cannot be resized by the user */ -#define RGFW_ALLOW_DND (1L<<5) /*!< the window supports drag and drop*/ -#define RGFW_HIDE_MOUSE (1L<<6) /*! the window should hide the mouse or not (can be toggled later on) using `RGFW_window_mouseShow*/ -#define RGFW_FULLSCREEN (1L<<8) /* the window is fullscreen by default or not */ -#define RGFW_CENTER (1L<<10) /*! center the window on the screen */ -#define RGFW_OPENGL_SOFTWARE (1L<<11) /*! use OpenGL software rendering */ -#define RGFW_COCOA_MOVE_TO_RESOURCE_DIR (1L << 12) /* (cocoa only), move to resource folder */ -#define RGFW_SCALE_TO_MONITOR (1L << 13) /* scale the window to the screen */ -#define RGFW_NO_INIT_API (1L << 2) /* DO not init an API (mostly for bindings, you should use `#define RGFW_NO_API` in C */ +/* + RGFW_allocator (optional) + you can ignore this if you use standard malloc/free +*/ +typedef void* (* RGFW_allocatorMallocfunc)(void* userdata, size_t size); +typedef void (* RGFW_allocatorFreefunc)(void* userdata, void* ptr); -#define RGFW_NO_GPU_RENDER (1L<<14) /* don't render (using the GPU based API)*/ -#define RGFW_NO_CPU_RENDER (1L<<15) /* don't render (using the CPU based buffer rendering)*/ -#define RGFW_WINDOW_HIDE (1L << 16)/* the window is hidden */ +typedef struct RGFW_allocator { + void* userdata; + RGFW_allocatorMallocfunc alloc; + RGFW_allocatorFreefunc free; +} RGFW_allocator; -typedef RGFW_ENUM(u8, RGFW_event_types) { +RGFWDEF RGFW_allocator RGFW_loadAllocator(RGFW_allocator allocator); +RGFWDEF void* RGFW_alloc(size_t len); +RGFWDEF void RGFW_free(void* ptr); + +/* + regular RGFW stuff +*/ + +typedef u8 RGFW_key; + +typedef RGFW_ENUM(u8, RGFW_eventType) { /*! event codes */ - RGFW_keyPressed = 1, /* a key has been pressed */ + RGFW_eventNone = 0, /*!< no event has been sent */ + RGFW_keyPressed, /* a key has been pressed */ RGFW_keyReleased, /*!< a key has been released*/ /*! key event note the code of the key pressed is stored in - RGFW_Event.keyCode + RGFW_event.key !!Keycodes defined at the bottom of the RGFW_HEADER part of this file!! while a string version is stored in - RGFW_Event.KeyString + RGFW_event.KeyString - RGFW_Event.lockState holds the current lockState + RGFW_event.keyMod holds the current keyMod this means if CapsLock, NumLock are active or not */ RGFW_mouseButtonPressed, /*!< a mouse button has been pressed (left,middle,right)*/ RGFW_mouseButtonReleased, /*!< a mouse button has been released (left,middle,right)*/ RGFW_mousePosChanged, /*!< the position of the mouse has been changed*/ /*! mouse event note - the x and y of the mouse can be found in the vector, RGFW_Event.point + the x and y of the mouse can be found in the vector, RGFW_event.point - RGFW_Event.button holds which mouse button was pressed + RGFW_event.button holds which mouse button was pressed */ - RGFW_jsButtonPressed, /*!< a joystick button was pressed */ - RGFW_jsButtonReleased, /*!< a joystick button was released */ - RGFW_jsAxisMove, /*!< an axis of a joystick was moved*/ - /*! joystick event note - RGFW_Event.joystick holds which joystick was altered, if any - RGFW_Event.button holds which joystick button was pressed + RGFW_gamepadConnected, /*!< a gamepad was connected */ + RGFW_gamepadDisconnected, /*!< a gamepad was disconnected */ + RGFW_gamepadButtonPressed, /*!< a gamepad button was pressed */ + RGFW_gamepadButtonReleased, /*!< a gamepad button was released */ + RGFW_gamepadAxisMove, /*!< an axis of a gamepad was moved*/ + /*! gamepad event note + RGFW_event.gamepad holds which gamepad was altered, if any + RGFW_event.button holds which gamepad button was pressed - RGFW_Event.axis holds the data of all the axis - RGFW_Event.axisCount says how many axis there are + RGFW_event.axis holds the data of all the axis + RGFW_event.axisesCount says how many axis there are */ - RGFW_windowMoved, /*!< the window was moved (by the user) */ + RGFW_windowMoved, /*!< the window was moved (b the user) */ RGFW_windowResized, /*!< the window was resized (by the user), [on webASM this means the browser was resized] */ RGFW_focusIn, /*!< window is in focus now */ RGFW_focusOut, /*!< window is out of focus now */ @@ -366,25 +477,28 @@ typedef RGFW_ENUM(u8, RGFW_event_types) { The event data is sent straight to the window structure with win->r.x, win->r.y, win->r.w and win->r.h */ - RGFW_quit, /*!< the user clicked the quit button*/ - RGFW_dnd, /*!< a file has been dropped into the window*/ - RGFW_dnd_init /*!< the start of a dnd event, when the place where the file drop is known */ + RGFW_quit, /*!< the user clicked the quit button*/ + RGFW_DND, /*!< a file has been dropped into the window*/ + RGFW_DNDInit /*!< the start of a dnd event, when the place where the file drop is known */ /* dnd data note - The x and y coords of the drop are stored in the vector RGFW_Event.point + The x and y coords of the drop are stored in the vector RGFW_event.point - RGFW_Event.droppedFilesCount holds how many files were dropped + RGFW_event.droppedFilesCount holds how many files were dropped This is also the size of the array which stores all the dropped file string, - RGFW_Event.droppedFiles + RGFW_event.droppedFiles */ }; -/*! mouse button codes (RGFW_Event.button) */ -#define RGFW_mouseLeft 1 /*!< left mouse button is pressed*/ -#define RGFW_mouseMiddle 2 /*!< mouse-wheel-button is pressed*/ -#define RGFW_mouseRight 3 /*!< right mouse button is pressed*/ -#define RGFW_mouseScrollUp 4 /*!< mouse wheel is scrolling up*/ -#define RGFW_mouseScrollDown 5 /*!< mouse wheel is scrolling down*/ +/*! mouse button codes (RGFW_event.button) */ +typedef RGFW_ENUM(u8, RGFW_mouseButton) { + RGFW_mouseNone = 0, /*!< no mouse button is pressed*/ + RGFW_mouseLeft, /*!< left mouse button is pressed*/ + RGFW_mouseMiddle, /*!< mouse-wheel-button is pressed*/ + RGFW_mouseRight, /*!< right mouse button is pressed*/ + RGFW_mouseScrollUp, /*!< mouse wheel is scrolling up*/ + RGFW_mouseScrollDown /*!< mouse wheel is scrolling down*/ +}; #ifndef RGFW_MAX_PATH #define RGFW_MAX_PATH 260 /* max length of a path (for dnd) */ @@ -393,31 +507,40 @@ typedef RGFW_ENUM(u8, RGFW_event_types) { #define RGFW_MAX_DROPS 260 /* max items you can drop at once */ #endif +#define RGFW_BIT(x) (1L << x) -/* for RGFW_Event.lockstate */ -#define RGFW_CAPSLOCK (1L << 1) -#define RGFW_NUMLOCK (1L << 2) +/* for RGFW_event.lockstate */ +typedef RGFW_ENUM(u8, RGFW_keymod) { + RGFW_modCapsLock = RGFW_BIT(0), + RGFW_modNumLock = RGFW_BIT(1), + RGFW_modControl = RGFW_BIT(2), + RGFW_modAlt = RGFW_BIT(3), + RGFW_modShift = RGFW_BIT(4), + RGFW_modSuper = RGFW_BIT(5) +}; -/*! joystick button codes (based on xbox/playstation), you may need to change these values per controller */ -#ifndef RGFW_joystick_codes - typedef RGFW_ENUM(u8, RGFW_joystick_codes) { - RGFW_JS_A = 0, /*!< or PS X button */ - RGFW_JS_B = 1, /*!< or PS circle button */ - RGFW_JS_Y = 2, /*!< or PS triangle button */ - RGFW_JS_X = 3, /*!< or PS square button */ - RGFW_JS_START = 9, /*!< start button */ - RGFW_JS_SELECT = 8, /*!< select button */ - RGFW_JS_HOME = 10, /*!< home button */ - RGFW_JS_UP = 13, /*!< dpad up */ - RGFW_JS_DOWN = 14, /*!< dpad down*/ - RGFW_JS_LEFT = 15, /*!< dpad left */ - RGFW_JS_RIGHT = 16, /*!< dpad right */ - RGFW_JS_L1 = 4, /*!< left bump */ - RGFW_JS_L2 = 5, /*!< left trigger*/ - RGFW_JS_R1 = 6, /*!< right bumper */ - RGFW_JS_R2 = 7, /*!< right trigger */ - }; -#endif +/*! gamepad button codes (based on xbox/playstation), you may need to change these values per controller */ +typedef RGFW_ENUM(u8, RGFW_gamepadCodes) { + RGFW_gamepadNone = 0, /*!< or PS X button */ + RGFW_gamepadA, /*!< or PS X button */ + RGFW_gamepadB, /*!< or PS circle button */ + RGFW_gamepadY, /*!< or PS triangle button */ + RGFW_gamepadX, /*!< or PS square button */ + RGFW_gamepadStart, /*!< start button */ + RGFW_gamepadSelect, /*!< select button */ + RGFW_gamepadHome, /*!< home button */ + RGFW_gamepadUp, /*!< dpad up */ + RGFW_gamepadDown, /*!< dpad down*/ + RGFW_gamepadLeft, /*!< dpad left */ + RGFW_gamepadRight, /*!< dpad right */ + RGFW_gamepadL1, /*!< left bump */ + RGFW_gamepadL2, /*!< left trigger*/ + RGFW_gamepadR1, /*!< right bumper */ + RGFW_gamepadR2, /*!< right trigger */ + RGFW_gamepadL3, /* left thumb stick */ + RGFW_gamepadR3, /*!< right thumb stick */ + RGFW_gamepadFinal +}; /*! basic vector type, if there's not already a point/vector type of choice */ #ifndef RGFW_point @@ -434,15 +557,9 @@ typedef RGFW_ENUM(u8, RGFW_event_types) { typedef struct { u32 w, h; } RGFW_area; #endif -#ifndef __cplusplus #define RGFW_POINT(x, y) (RGFW_point){(i32)(x), (i32)(y)} #define RGFW_RECT(x, y, w, h) (RGFW_rect){(i32)(x), (i32)(y), (i32)(w), (i32)(h)} #define RGFW_AREA(w, h) (RGFW_area){(u32)(w), (u32)(h)} -#else -#define RGFW_POINT(x, y) {(i32)(x), (i32)(y)} -#define RGFW_RECT(x, y, w, h) {(i32)(x), (i32)(y), (i32)(w), (i32)(h)} -#define RGFW_AREA(w, h) {(u32)(w), (u32)(h)} -#endif #ifndef RGFW_NO_MONITOR /*! structure for monitor data */ @@ -450,7 +567,8 @@ typedef RGFW_ENUM(u8, RGFW_event_types) { char name[128]; /*!< monitor name */ RGFW_rect rect; /*!< monitor Workarea */ float scaleX, scaleY; /*!< monitor content scale*/ - float physW, physH; /*!< monitor physical size */ + float pixelRatio; /*!< pixel ratio for monitor (1.0 for regular, 2.0 for hiDPI) */ + float physW, physH; /*!< monitor physical size in inches*/ } RGFW_monitor; /* @@ -463,11 +581,18 @@ typedef RGFW_ENUM(u8, RGFW_event_types) { RGFWDEF RGFW_monitor RGFW_getPrimaryMonitor(void); #endif -/* NOTE: some parts of the data can represent different things based on the event (read comments in RGFW_Event struct) */ -/*! Event structure for checking/getting events */ -typedef struct RGFW_Event { - char keyName[16]; /*!< key name of event*/ +/* RGFW mouse loading */ +typedef void RGFW_mouse; +/*!< loads mouse from bitmap (similar to RGFW_window_setIcon), icon NOT resized by default*/ +RGFWDEF RGFW_mouse* RGFW_loadMouse(u8* icon, RGFW_area a, i32 channels); +/*!< frees RGFW_mouse data */ +RGFWDEF void RGFW_freeMouse(RGFW_mouse* mouse); +/* */ + +/* NOTE: some parts of the data can represent different things based on the event (read comments in RGFW_event struct) */ +/*! Event structure for checking/getting events */ +typedef struct RGFW_event { /*! drag and drop data */ /* 260 max paths with a max length of 260 */ #ifdef RGFW_ALLOC_DROPFILES @@ -475,31 +600,34 @@ typedef struct RGFW_Event { #else char droppedFiles[RGFW_MAX_DROPS][RGFW_MAX_PATH]; /*!< dropped files*/ #endif - u32 droppedFilesCount; /*!< house many files were dropped */ + size_t droppedFilesCount; /*!< house many files were dropped */ - u32 type; /*!< which event has been sent?*/ + RGFW_eventType type; /*!< which event has been sent?*/ RGFW_point point; /*!< mouse x, y of event (or drop point) */ - - u8 keyCode; /*!< keycode of event !!Keycodes defined at the bottom of the RGFW_HEADER part of this file!! */ - + + RGFW_key key; /*!< the physical key of the event, refers to where key is physically !!Keycodes defined at the bottom of the RGFW_HEADER part of this file!! */ + u8 keyChar; /*!< mapped key char of the event*/ + b8 repeat; /*!< key press event repeated (the key is being held) */ b8 inFocus; /*!< if the window is in focus or not (this is always true for MacOS windows due to the api being weird) */ - u8 lockState; - - u8 button; /* !< which mouse button was pressed */ + RGFW_keymod keyMod; + + u8 button; /* !< which mouse (or gamepad) button was pressed */ double scroll; /*!< the raw mouse scroll value */ - u16 joystick; /*! which joystick this event applies to (if applicable to any) */ + u16 gamepad; /*! which gamepad this event applies to (if applicable to any) */ u8 axisesCount; /*!< number of axises */ - RGFW_point axis[2]; /*!< x, y of axises (-100 to 100) */ + + u8 whichAxis; /* which axis was effected */ + RGFW_point axis[4]; /*!< x, y of axises (-100 to 100) */ u64 frameTime, frameTime2; /*!< this is used for counting the fps */ -} RGFW_Event; +} RGFW_event; /*! source data for the window (used by the APIs) */ -typedef struct RGFW_window_src { #ifdef RGFW_WINDOWS +typedef struct RGFW_window_src { HWND window; /*!< source window */ HDC hdc; /*!< source HDC */ u32 hOffset; /*!< height offset for window */ @@ -517,12 +645,15 @@ typedef struct RGFW_window_src { EGLContext EGL_context; #endif - #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) + #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) HDC hdcMem; HBITMAP bitmap; #endif RGFW_area maxSize, minSize; /*!< for setting max/min resize (RGFW_WINDOWS) */ -#elif defined(RGFW_X11) +} RGFW_window_src; +#elif defined(RGFW_UNIX) +typedef struct RGFW_window_src { +#if defined(RGFW_X11) Display* display; /*!< source display */ Window window; /*!< source window */ #if (defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA) && !defined(RGFW_EGL) @@ -535,33 +666,44 @@ typedef struct RGFW_window_src { EGLContext EGL_context; #endif -#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) - XImage* bitmap; - GC gc; -#endif -#elif defined(RGFW_WAYLAND) - struct wl_display* display; + #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) + XImage* bitmap; + GC gc; + #endif +#endif /* RGFW_X11 */ +#if defined(RGFW_WAYLAND) + struct wl_display* wl_display; struct wl_surface* surface; struct wl_buffer* wl_buffer; struct wl_keyboard* keyboard; + struct wl_compositor* compositor; struct xdg_surface* xdg_surface; struct xdg_toplevel* xdg_toplevel; struct zxdg_toplevel_decoration_v1* decoration; - RGFW_Event events[20]; + struct xdg_wm_base* xdg_wm_base; + struct wl_shm* shm; + struct wl_seat *seat; + u8* buffer; + + RGFW_event events[20]; i32 eventLen; size_t eventIndex; #if defined(RGFW_EGL) - struct wl_egl_window* window; + struct wl_egl_window* eglWindow; + #endif + #if defined(RGFW_EGL) && !defined(RGFW_X11) EGLSurface EGL_surface; EGLDisplay EGL_display; EGLContext EGL_context; - #elif defined(RGFW_OSMESA) + #elif defined(RGFW_OSMESA) && !defined(RGFW_X11) OSMesaContext ctx; #endif -#elif defined(RGFW_MACOS) - u32 display; - void* displayLink; +#endif /* RGFW_WAYLAND */ +} RGFW_window_src; +#endif /* RGFW_UNIX */ +#if defined(RGFW_MACOS) +typedef struct RGFW_window_src { void* window; b8 dndPassed; #if (defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA) && !defined(RGFW_EGL) @@ -576,11 +718,13 @@ typedef struct RGFW_window_src { void* view; /*apple viewpoint thingy*/ -#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) +#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) void* bitmap; /*!< API's bitmap for storing or managing */ void* image; #endif +} RGFW_window_src; #elif defined(RGFW_WEBASM) +typedef struct RGFW_window_src { #ifdef RGFW_WEBGPU WGPUInstance ctx; WGPUDevice device; @@ -588,27 +732,42 @@ typedef struct RGFW_window_src { #else EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx; #endif -#endif } RGFW_window_src; +#endif - +/*! Optional arguments for making a windows */ +typedef RGFW_ENUM(u32, RGFW_windowFlags) { + RGFW_windowNoInitAPI = RGFW_BIT(0), /* DO not init an API (mostly for bindings, you should use `#define RGFW_NO_API` in C */ + RGFW_windowNoBorder = RGFW_BIT(1), /*!< the window doesn't have border */ + RGFW_windowNoResize = RGFW_BIT(2), /*!< the window cannot be resized by the user */ + RGFW_windowAllowDND = RGFW_BIT(3), /*!< the window supports drag and drop*/ + RGFW_windowHideMouse = RGFW_BIT(4), /*! the window should hide the mouse or not (can be toggled later on) using `RGFW_window_mouseShow*/ + RGFW_windowFullscreen = RGFW_BIT(5), /* the window is fullscreen by default or not */ + RGFW_windowTransparent = RGFW_BIT(6), /*!< the window is transparent (only properly works on X11 and MacOS, although it's although for windows) */ + RGFW_windowCenter = RGFW_BIT(7), /*! center the window on the screen */ + RGFW_windowOpenglSoftware = RGFW_BIT(8), /*! use OpenGL software rendering */ + RGFW_windowCocoaCHDirToRes = RGFW_BIT(9), /* (cocoa only), change directory to resource folder */ + RGFW_windowScaleToMonitor = RGFW_BIT(10), /* scale the window to the screen */ + RGFW_windowHide = RGFW_BIT(11)/* the window is hidden */ +}; typedef struct RGFW_window { RGFW_window_src src; /*!< src window data */ -#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) +#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) u8* buffer; /*!< buffer for non-GPU systems (OSMesa, basic software rendering) */ /* when rendering using RGFW_BUFFER, the buffer is in the RGBA format */ #endif void* userPtr; /* ptr for usr data */ - - RGFW_Event event; /*!< current event */ + + RGFW_event event; /*!< current event */ RGFW_rect r; /*!< the x, y, w and h of the struct */ - + RGFW_point _lastMousePoint; /*!< last cusor point (for raw mouse data) */ - - u32 _winArgs; /*!< windows args (for RGFW to check) */ + + u32 _flags; /*!< windows flags (for RGFW to check) */ + RGFW_allocator _mem; /*!< the allocator that was used to allocate RGFW window data, used to free it*/ } RGFW_window; /*!< Window structure for managing the window */ #if defined(RGFW_X11) || defined(RGFW_MACOS) @@ -618,27 +777,41 @@ typedef struct RGFW_window { #endif /** * @defgroup Window_management -* @{ */ +* @{ */ -/*! +/*! * the class name for X11 and WinAPI. apps with the same class will be grouped by the WM * by default the class name will == the root window's name */ -RGFWDEF void RGFW_setClassName(char* name); +RGFWDEF void RGFW_setClassName(const char* name); /*! this has to be set before createWindow is called, else the fulscreen size is used */ RGFWDEF void RGFW_setBufferSize(RGFW_area size); /*!< the buffer cannot be resized (by RGFW) */ +/* NOTE: (windows)If the executable has an icon resource named RGFW_ICON, it will be set as the initial icon for the window.*/ + RGFWDEF RGFW_window* RGFW_createWindow( const char* name, /* name of the window */ RGFW_rect rect, /* rect of window */ - u16 args /* extra arguments (NULL / (u16)0 means no args used)*/ -); /*!< function to create a window struct */ + RGFW_windowFlags flags /* extra arguments ((u32)0 means no flags used)*/ +); /*!< function to create a window and struct */ + +RGFWDEF RGFW_window* RGFW_createWindowPtr( + const char* name, /* name of the window */ + RGFW_rect rect, /* rect of window */ + RGFW_windowFlags flags, /* extra arguments (NULL / (u32)0 means no flags used)*/ + RGFW_window* win /* ptr to the window struct you want to use */ +); /*!< function to create a window (without allocating a window struct) */ /*! get the size of the screen to an area struct */ RGFWDEF RGFW_area RGFW_getScreenSize(void); +/*! frees win->buffer (if it was allocated by RGFW) and sets the pointer to your pointer */ +RGFWDEF void RGFW_window_setBufferPtr(RGFW_window* win, u8* ptr, RGFW_area size); +/*< the new buffer is not be resized or freed (by RGFW) */ + + /*! this function checks an *individual* event (and updates window structure attributes) this means, using this function without a while loop may cause event lag @@ -647,11 +820,11 @@ RGFWDEF RGFW_area RGFW_getScreenSize(void); while (RGFW_window_checkEvent(win) != NULL) [this keeps checking events until it reaches the last one] - this function is optional if you choose to use event callbacks, + this function is optional if you choose to use event callbacks, although you still need some way to tell RGFW to process events eg. `RGFW_window_checkEvents` */ -RGFWDEF RGFW_Event* RGFW_window_checkEvent(RGFW_window* win); /*!< check current event (returns a pointer to win->event or NULL if there is no event)*/ +RGFWDEF RGFW_event* RGFW_window_checkEvent(RGFW_window* win); /*!< check current event (returns a pointer to win->event or NULL if there is no event)*/ /*! for RGFW_window_eventWait and RGFW_window_checkEvents @@ -661,20 +834,20 @@ RGFWDEF RGFW_Event* RGFW_window_checkEvent(RGFW_window* win); /*!< check current if waitMS == a negative integer, the loop will not return until it gets another event */ typedef RGFW_ENUM(i32, RGFW_eventWait) { - RGFW_NEXT = -1, - RGFW_NO_WAIT = 0 + RGFW_eventWaitNext = -1, + RGFW_eventNoWait = 0 }; /*! sleep until RGFW gets an event or the timer ends (defined by OS) */ RGFWDEF void RGFW_window_eventWait(RGFW_window* win, i32 waitMS); /*! - check all the events until there are none left, + check all the events until there are none left, this should only be used if you're using callbacks only */ RGFWDEF void RGFW_window_checkEvents(RGFW_window* win, i32 waitMS); -/*! +/*! Tell RGFW_window_eventWait to stop waiting, to be ran from another thread */ RGFWDEF void RGFW_stopCheckEvents(void); @@ -709,35 +882,35 @@ RGFWDEF void RGFW_window_restore(RGFW_window* win); /*!< restore the window from /*! if the window should have a border or not (borderless) based on bool value of `border` */ RGFWDEF void RGFW_window_setBorder(RGFW_window* win, b8 border); -/*! turn on / off dnd (RGFW_ALLOW_DND stil must be passed to the window)*/ +/*! turn on / off dnd (RGFW_windowAllowDND stil must be passed to the window)*/ RGFWDEF void RGFW_window_setDND(RGFW_window* win, b8 allow); #ifndef RGFW_NO_PASSTHROUGH /*!! turn on / off mouse passthrough */ RGFWDEF void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough); -#endif +#endif /*! rename window to a given string */ RGFWDEF void RGFW_window_setName(RGFW_window* win, - char* name + const char* name ); -RGFWDEF void RGFW_window_setIcon(RGFW_window* win, /*!< source window */ +RGFWDEF b32 RGFW_window_setIcon(RGFW_window* win, /*!< source window */ u8* icon /*!< icon bitmap */, RGFW_area a /*!< width and height of the bitmap*/, i32 channels /*!< how many channels the bitmap has (rgb : 3, rgba : 4) */ ); /*!< image resized by default */ -/*!< sets mouse to bitmap (very simular to RGFW_window_setIcon), image NOT resized by default*/ -RGFWDEF void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels); +/*!< sets mouse to RGFW_mouse icon (loaded from a bitmap struct) */ +RGFWDEF void RGFW_window_setMouse(RGFW_window* win, RGFW_mouse* mouse); /*!< sets the mouse to a standard API cursor (based on RGFW_MOUSE, as seen at the end of the RGFW_HEADER part of this file) */ -RGFWDEF void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse); +RGFWDEF b32 RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse); -RGFWDEF void RGFW_window_setMouseDefault(RGFW_window* win); /*!< sets the mouse to the default mouse icon */ +RGFWDEF b32 RGFW_window_setMouseDefault(RGFW_window* win); /*!< sets the mouse to the default mouse icon */ /* Locks cursor at the center of the window - win->event.point become raw mouse movement data + win->event.point become raw mouse movement data this is useful for a 3D camera */ @@ -778,75 +951,66 @@ RGFWDEF b8 RGFW_window_isMinimized(RGFW_window* win); /*! if window is maximized */ RGFWDEF b8 RGFW_window_isMaximized(RGFW_window* win); -/** @} */ +/** @} */ /** * @defgroup Monitor -* @{ */ +* @{ */ #ifndef RGFW_NO_MONITOR /* scale the window to the monitor, -this is run by default if the user uses the arg `RGFW_SCALE_TO_MONITOR` during window creation +this is run by default if the user uses the arg `RGFW_scaleToMonitor` during window creation */ RGFWDEF void RGFW_window_scaleToMonitor(RGFW_window* win); /*! get the struct of the window's monitor */ RGFWDEF RGFW_monitor RGFW_window_getMonitor(RGFW_window* win); #endif -/** @} */ +/** @} */ /** * @defgroup Input -* @{ */ - -/*error handling*/ -RGFWDEF b8 RGFW_Error(void); /*!< returns true if an error has occurred (doesn't print errors itself) */ - -/*! returns true if the key should be shifted */ -RGFWDEF b8 RGFW_shouldShift(u32 keycode, u8 lockState); - -/*! get char from RGFW keycode (using a LUT), uses shift'd version if shift = true */ -RGFWDEF char RGFW_keyCodeToChar(u32 keycode, b8 shift); -/*! get char from RGFW keycode (using a LUT), uses lockState for shouldShift) */ -RGFWDEF char RGFW_keyCodeToCharAuto(u32 keycode, u8 lockState); +* @{ */ /*! if window == NULL, it checks if the key is pressed globally. Otherwise, it checks only if the key is pressed while the window in focus.*/ -RGFWDEF b8 RGFW_isPressed(RGFW_window* win, u8 key); /*!< if key is pressed (key code)*/ +RGFWDEF b8 RGFW_isPressed(RGFW_window* win, RGFW_key key); /*!< if key is pressed (key code)*/ -RGFWDEF b8 RGFW_wasPressed(RGFW_window* win, u8 key); /*!< if key was pressed (checks previous state only) (key code)*/ +RGFWDEF b8 RGFW_wasPressed(RGFW_window* win, RGFW_key key); /*!< if key was pressed (checks previous state only) (key code)*/ -RGFWDEF b8 RGFW_isHeld(RGFW_window* win, u8 key); /*!< if key is held (key code)*/ -RGFWDEF b8 RGFW_isReleased(RGFW_window* win, u8 key); /*!< if key is released (key code)*/ +RGFWDEF b8 RGFW_isHeld(RGFW_window* win, RGFW_key key); /*!< if key is held (key code)*/ +RGFWDEF b8 RGFW_isReleased(RGFW_window* win, RGFW_key key); /*!< if key is released (key code)*/ /* if a key is pressed and then released, pretty much the same as RGFW_isReleased */ -RGFWDEF b8 RGFW_isClicked(RGFW_window* win, u8 key /*!< key code*/); +RGFWDEF b8 RGFW_isClicked(RGFW_window* win, RGFW_key key /*!< key code*/); /*! if a mouse button is pressed */ -RGFWDEF b8 RGFW_isMousePressed(RGFW_window* win, u8 button /*!< mouse button code */ ); +RGFWDEF b8 RGFW_isMousePressed(RGFW_window* win, RGFW_mouseButton button /*!< mouse button code */ ); /*! if a mouse button is held */ -RGFWDEF b8 RGFW_isMouseHeld(RGFW_window* win, u8 button /*!< mouse button code */ ); +RGFWDEF b8 RGFW_isMouseHeld(RGFW_window* win, RGFW_mouseButton button /*!< mouse button code */ ); /*! if a mouse button was released */ -RGFWDEF b8 RGFW_isMouseReleased(RGFW_window* win, u8 button /*!< mouse button code */ ); +RGFWDEF b8 RGFW_isMouseReleased(RGFW_window* win, RGFW_mouseButton button /*!< mouse button code */ ); /*! if a mouse button was pressed (checks previous state only) */ -RGFWDEF b8 RGFW_wasMousePressed(RGFW_window* win, u8 button /*!< mouse button code */ ); -/** @} */ +RGFWDEF b8 RGFW_wasMousePressed(RGFW_window* win, RGFW_mouseButton button /*!< mouse button code */ ); +/** @} */ /** * @defgroup Clipboard -* @{ */ -RGFWDEF char* RGFW_readClipboard(size_t* size); /*!< read clipboard data */ -RGFWDEF void RGFW_clipboardFree(char* str); /*!< the string returned from RGFW_readClipboard must be freed */ +* @{ */ +typedef ptrdiff_t RGFW_ssize_t; +RGFWDEF const char* RGFW_readClipboard(size_t* size); /*!< read clipboard data */ +/*! read clipboard data or send a NULL str to just get the length of the clipboard data */ +RGFWDEF RGFW_ssize_t RGFW_readClipboardPtr(char* str, size_t strCapacity); RGFWDEF void RGFW_writeClipboard(const char* text, u32 textLen); /*!< write text to the clipboard */ -/** @} */ +/** @} */ /** - - - Event callbacks, - these are completely optional, you can use the normal + + + Event callbacks, + these are completely optional, you can use the normal RGFW_checkEvent() method if you prefer that * @defgroup Callbacks -* @{ +* @{ */ /*! RGFW_windowMoved, the window and its new rect value */ @@ -861,19 +1025,20 @@ typedef void (* RGFW_focusfunc)(RGFW_window* win, b8 inFocus); typedef void (* RGFW_mouseNotifyfunc)(RGFW_window* win, RGFW_point point, b8 status); /*! RGFW_mousePosChanged, the window that the move happened on and the new point of the mouse */ typedef void (* RGFW_mouseposfunc)(RGFW_window* win, RGFW_point point); -/*! RGFW_dnd_init, the window, the point of the drop on the windows */ +/*! RGFW_DNDInit, the window, the point of the drop on the windows */ typedef void (* RGFW_dndInitfunc)(RGFW_window* win, RGFW_point point); /*! RGFW_windowRefresh, the window that needs to be refreshed */ typedef void (* RGFW_windowrefreshfunc)(RGFW_window* win); -/*! RGFW_keyPressed / RGFW_keyReleased, the window that got the event, the keycode, the string version, the state of mod keys, if it was a press (else it's a release) */ -typedef void (* RGFW_keyfunc)(RGFW_window* win, u32 keycode, char keyName[16], u8 lockState, b8 pressed); +/*! RGFW_keyPressed / RGFW_keyReleased, the window that got the event, the mapped key, the physical key, the string version, the state of mod keys, if it was a press (else it's a release) */ +typedef void (* RGFW_keyfunc)(RGFW_window* win, u8 key, char keyChar, RGFW_keymod keyMod, b8 pressed); /*! RGFW_mouseButtonPressed / RGFW_mouseButtonReleased, the window that got the event, the button that was pressed, the scroll value, if it was a press (else it's a release) */ -typedef void (* RGFW_mousebuttonfunc)(RGFW_window* win, u8 button, double scroll, b8 pressed); -/*! RGFW_jsButtonPressed / RGFW_jsButtonReleased, the window that got the event, the button that was pressed, the scroll value, if it was a press (else it's a release) */ -typedef void (* RGFW_jsButtonfunc)(RGFW_window* win, u16 joystick, u8 button, b8 pressed); -/*! RGFW_jsAxisMove, the window that got the event, the joystick in question, the axis values and the amount of axises */ -typedef void (* RGFW_jsAxisfunc)(RGFW_window* win, u16 joystick, RGFW_point axis[2], u8 axisesCount); - +typedef void (* RGFW_mousebuttonfunc)(RGFW_window* win, RGFW_mouseButton button, double scroll, b8 pressed); +/*!gamepad /gamepad, the window that got the event, the button that was pressed, the scroll value, if it was a press (else it's a release) */ +typedef void (* RGFW_gamepadButtonfunc)(RGFW_window* win, u16 gamepad, u8 button, b8 pressed); +/*! RGFW_gamepadAxisMove, the window that got the event, the gamepad in question, the axis values and the amount of axises */ +typedef void (* RGFW_gamepadAxisfunc)(RGFW_window* win, u16 gamepad, RGFW_point axis[2], u8 axisesCount, u8 whichAxis); +/*! RGFW_gamepadConnected/RGFW_gamepadDisconnected, the window that got the event, the gamepad in question, if the controller was connected (or disconnected if false) */ +typedef void (* RGFW_gamepadfunc)(RGFW_window* win, u16 gamepad, b8 connected); /*! RGFW_dnd, the window that had the drop, the drop data and the amount files dropped returns previous callback function (if it was set) */ #ifdef RGFW_ALLOC_DROPFILES @@ -904,58 +1069,67 @@ RGFWDEF RGFW_keyfunc RGFW_setKeyCallback(RGFW_keyfunc func); /*! set callback for a mouse button (press / release ) event returns previous callback function (if it was set) */ RGFWDEF RGFW_mousebuttonfunc RGFW_setMouseButtonCallback(RGFW_mousebuttonfunc func); /*! set callback for a controller button (press / release ) event returns previous callback function (if it was set) */ -RGFWDEF RGFW_jsButtonfunc RGFW_setjsButtonCallback(RGFW_jsButtonfunc func); -/*! set callback for a joystick axis mov event returns previous callback function (if it was set) */ -RGFWDEF RGFW_jsAxisfunc RGFW_setjsAxisCallback(RGFW_jsAxisfunc func); +RGFWDEF RGFW_gamepadButtonfunc RGFW_setgamepadButtonCallback(RGFW_gamepadButtonfunc func); +/*! set callback for a gamepad axis mov event returns previous callback function (if it was set) */ +RGFWDEF RGFW_gamepadAxisfunc RGFW_setgamepadAxisCallback(RGFW_gamepadAxisfunc func); +/*! set callback for when a controller is connected or disconnected */ +RGFWDEF RGFW_gamepadfunc RGFW_setGamepadCallback(RGFW_gamepadfunc func); -/** @} */ +/** @} */ /** * @defgroup Threads -* @{ */ +* @{ */ #ifndef RGFW_NO_THREADS - /*! threading functions*/ +/*! threading functions*/ - /*! NOTE! (for X11/linux) : if you define a window in a thread, it must be run after the original thread's window is created or else there will be a memory error */ - /* - I'd suggest you use sili's threading functions instead - if you're going to use sili - which is a good idea generally - */ +/*! NOTE! (for X11/linux) : if you define a window in a thread, it must be run after the original thread's window is created or else there will be a memory error */ +/* + I'd suggest you use sili's threading functions instead + if you're going to use sili + which is a good idea generally +*/ - #if defined(__unix__) || defined(__APPLE__) || defined(RGFW_WEBASM) - typedef void* (* RGFW_threadFunc_ptr)(void*); - #else - typedef DWORD (__stdcall *RGFW_threadFunc_ptr) (LPVOID lpThreadParameter); - #endif - - RGFWDEF RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args); /*!< create a thread*/ - RGFWDEF void RGFW_cancelThread(RGFW_thread thread); /*!< cancels a thread*/ - RGFWDEF void RGFW_joinThread(RGFW_thread thread); /*!< join thread to current thread */ - RGFWDEF void RGFW_setThreadPriority(RGFW_thread thread, u8 priority); /*!< sets the priority priority */ +#if defined(__unix__) || defined(__APPLE__) || defined(RGFW_WEBASM) || defined(RGFW_CUSTOM_BACKEND) + typedef void* (* RGFW_threadFunc_ptr)(void*); +#else + typedef DWORD (__stdcall *RGFW_threadFunc_ptr) (LPVOID lpThreadParameter); #endif -/** @} */ +RGFWDEF RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args); /*!< create a thread*/ +RGFWDEF void RGFW_cancelThread(RGFW_thread thread); /*!< cancels a thread*/ +RGFWDEF void RGFW_joinThread(RGFW_thread thread); /*!< join thread to current thread */ +RGFWDEF void RGFW_setThreadPriority(RGFW_thread thread, u8 priority); /*!< sets the priority priority */ +#endif -/** * @defgroup joystick -* @{ */ +/** @} */ -/*! joystick count starts at 0*/ -/*!< register joystick to window based on a number (the number is based on when it was connected eg. /dev/js0)*/ -RGFWDEF u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber); -RGFWDEF u16 RGFW_registerJoystickF(RGFW_window* win, char* file); +/** * @defgroup gamepad +* @{ */ -RGFWDEF u32 RGFW_isPressedJS(RGFW_window* win, u16 controller, u8 button); +typedef RGFW_ENUM(u8, RGFW_gamepadType) { + RGFW_gamepadMicrosoft = 0, RGFW_gamepadSony, RGFW_gamepadNintendo, RGFW_gamepadLogitech, RGFW_gamepadUnknown +}; -/** @} */ +/*! gamepad count starts at 0*/ +RGFWDEF u32 RGFW_isPressedGamepad(RGFW_window* win, u8 controller, RGFW_gamepadCodes button); +RGFWDEF u32 RGFW_isReleasedGamepad(RGFW_window* win, u8 controller, RGFW_gamepadCodes button); +RGFWDEF u32 RGFW_isHeldGamepad(RGFW_window* win, u8 controller, RGFW_gamepadCodes button); +RGFWDEF u32 RGFW_wasPressedGamepad(RGFW_window* win, u8 controller, RGFW_gamepadCodes button); +RGFWDEF RGFW_point RGFW_getGamepadAxis(RGFW_window* win, u16 controller, u16 whichAxis); +RGFWDEF const char* RGFW_getGamepadName(RGFW_window* win, u16 controller); +RGFWDEF size_t RGFW_getGamepadCount(RGFW_window* win); +RGFWDEF RGFW_gamepadType RGFW_getGamepadType(RGFW_window* win, u16 controller); + +/** @} */ /** * @defgroup graphics_API -* @{ */ +* @{ */ /*!< make the window the current opengl drawing context NOTE: - if you want to switch the graphics context's thread, + if you want to switch the graphics context's thread, you have to run RGFW_window_makeCurrent(NULL); on the old thread then RGFW_window_makeCurrent(valid_window) on the new thread */ @@ -973,38 +1147,39 @@ RGFWDEF void RGFW_window_setCPURender(RGFW_window* win, i8 set); /*! native API functions */ #if defined(RGFW_OPENGL) || defined(RGFW_EGL) - /*! OpenGL init hints */ - RGFWDEF void RGFW_setGLStencil(i32 stencil); /*!< set stencil buffer bit size (8 by default) */ - RGFWDEF void RGFW_setGLSamples(i32 samples); /*!< set number of sampiling buffers (4 by default) */ - RGFWDEF void RGFW_setGLStereo(i32 stereo); /*!< use GL_STEREO (GL_FALSE by default) */ - RGFWDEF void RGFW_setGLAuxBuffers(i32 auxBuffers); /*!< number of aux buffers (0 by default) */ +/*! OpenGL init hints */ +RGFWDEF void RGFW_setGLStencil(i32 stencil); /*!< set stencil buffer bit size (8 by default) */ +RGFWDEF void RGFW_setGLSamples(i32 samples); /*!< set number of sampiling buffers (4 by default) */ +RGFWDEF void RGFW_setGLStereo(i32 stereo); /*!< use GL_STEREO (GL_FALSE by default) */ +RGFWDEF void RGFW_setGLAuxBuffers(i32 auxBuffers); /*!< number of aux buffers (0 by default) */ + +/*! which profile to use for the opengl verion */ +typedef RGFW_ENUM(u8, RGFW_glProfile) { RGFW_glCore = 0, RGFW_glCompatibility }; +/*! Set OpenGL version hint (core or compatibility profile)*/ +RGFWDEF void RGFW_setGLVersion(RGFW_glProfile profile, i32 major, i32 minor); +RGFWDEF void RGFW_setDoubleBuffer(b8 useDoubleBuffer); +RGFWDEF void* RGFW_getProcAddress(const char* procname); /*!< get native opengl proc address */ +RGFWDEF void RGFW_window_makeCurrent_OpenGL(RGFW_window* win); /*!< to be called by RGFW_window_makeCurrent */ - /*! which profile to use for the opengl verion */ - typedef RGFW_ENUM(u8, RGFW_GL_profile) { RGFW_GL_CORE = 0, RGFW_GL_COMPATIBILITY }; - /*! Set OpenGL version hint (core or compatibility profile)*/ - RGFWDEF void RGFW_setGLVersion(RGFW_GL_profile profile, i32 major, i32 minor); - RGFWDEF void RGFW_setDoubleBuffer(b8 useDoubleBuffer); - RGFWDEF void* RGFW_getProcAddress(const char* procname); /*!< get native opengl proc address */ - RGFWDEF void RGFW_window_makeCurrent_OpenGL(RGFW_window* win); /*!< to be called by RGFW_window_makeCurrent */ #elif defined(RGFW_DIRECTX) - typedef struct { - IDXGIFactory* pFactory; - IDXGIAdapter* pAdapter; - ID3D11Device* pDevice; - ID3D11DeviceContext* pDeviceContext; - } RGFW_directXinfo; +typedef struct { + IDXGIFactory* pFactory; + IDXGIAdapter* pAdapter; + ID3D11Device* pDevice; + ID3D11DeviceContext* pDeviceContext; +} RGFW_directXinfo; - /* - RGFW stores a global instance of RGFW_directXinfo, - you can use this function to get a pointer the instance - */ - RGFWDEF RGFW_directXinfo* RGFW_getDirectXInfo(void); +/* + RGFW stores a global instance of RGFW_directXinfo, + you can use this function to get a pointer the instance +*/ +RGFWDEF RGFW_directXinfo* RGFW_getDirectXInfo(void); #endif -/** @} */ +/** @} */ /** * @defgroup Supporting -* @{ */ +* @{ */ RGFWDEF u64 RGFW_getTime(void); /*!< get time in seconds */ RGFWDEF u64 RGFW_getTimeNS(void); /*!< get time in nanoseconds */ RGFWDEF void RGFW_sleep(u64 milisecond); /*!< sleep for a set time */ @@ -1013,9 +1188,66 @@ RGFWDEF void RGFW_sleep(u64 milisecond); /*!< sleep for a set time */ key codes and mouse icon enums */ -typedef RGFW_ENUM(u8, RGFW_Key) { - RGFW_KEY_NULL = 0, - RGFW_Escape, +typedef RGFW_ENUM(u8, RGFW_key) { + RGFW_keyNULL = 0, + RGFW_escape = '\033', + RGFW_backtick = '`', + RGFW_0 = '0', + RGFW_1 = '1', + RGFW_2 = '2', + RGFW_3 = '3', + RGFW_4 = '4', + RGFW_5 = '5', + RGFW_6 = '6', + RGFW_7 = '7', + RGFW_8 = '8', + RGFW_9 = '9', + + RGFW_minus = '-', + RGFW_equals = '=', + RGFW_backSpace = '\b', + RGFW_tab = '\t', + RGFW_space = ' ', + + RGFW_a = 'a', + RGFW_b = 'b', + RGFW_c = 'c', + RGFW_d = 'd', + RGFW_e = 'e', + RGFW_f = 'f', + RGFW_g = 'g', + RGFW_h = 'h', + RGFW_i = 'i', + RGFW_j = 'j', + RGFW_k = 'k', + RGFW_l = 'l', + RGFW_m = 'm', + RGFW_n = 'n', + RGFW_o = 'o', + RGFW_p = 'p', + RGFW_q = 'q', + RGFW_r = 'r', + RGFW_s = 's', + RGFW_t = 't', + RGFW_u = 'u', + RGFW_v = 'v', + RGFW_w = 'w', + RGFW_x = 'x', + RGFW_y = 'y', + RGFW_z = 'z', + + RGFW_period = '.', + RGFW_comma = ',', + RGFW_slash = '/', + RGFW_bracket = '{', + RGFW_closeBracket = '}', + RGFW_semicolon = ';', + RGFW_apostrophe = '\'', + RGFW_backSlash = '\\', + RGFW_return = '\n', + + RGFW_delete = '\177', /* 127 */ + RGFW_F1, RGFW_F2, RGFW_F3, @@ -1029,86 +1261,29 @@ typedef RGFW_ENUM(u8, RGFW_Key) { RGFW_F11, RGFW_F12, - RGFW_Backtick, + RGFW_capsLock, + RGFW_shiftL, + RGFW_controlL, + RGFW_altL, + RGFW_superL, + RGFW_shiftR, + RGFW_controlR, + RGFW_altR, + RGFW_superR, + RGFW_up, + RGFW_down, + RGFW_left, + RGFW_right, - RGFW_0, - RGFW_1, - RGFW_2, - RGFW_3, - RGFW_4, - RGFW_5, - RGFW_6, - RGFW_7, - RGFW_8, - RGFW_9, + RGFW_insert, + RGFW_end, + RGFW_home, + RGFW_pageUp, + RGFW_pageDown, - RGFW_Minus, - RGFW_Equals, - RGFW_BackSpace, - RGFW_Tab, - RGFW_CapsLock, - RGFW_ShiftL, - RGFW_ControlL, - RGFW_AltL, - RGFW_SuperL, - RGFW_ShiftR, - RGFW_ControlR, - RGFW_AltR, - RGFW_SuperR, - RGFW_Space, - - RGFW_a, - RGFW_b, - RGFW_c, - RGFW_d, - RGFW_e, - RGFW_f, - RGFW_g, - RGFW_h, - RGFW_i, - RGFW_j, - RGFW_k, - RGFW_l, - RGFW_m, - RGFW_n, - RGFW_o, - RGFW_p, - RGFW_q, - RGFW_r, - RGFW_s, - RGFW_t, - RGFW_u, - RGFW_v, - RGFW_w, - RGFW_x, - RGFW_y, - RGFW_z, - - RGFW_Period, - RGFW_Comma, - RGFW_Slash, - RGFW_Bracket, - RGFW_CloseBracket, - RGFW_Semicolon, - RGFW_Return, - RGFW_Quote, - RGFW_BackSlash, - - RGFW_Up, - RGFW_Down, - RGFW_Left, - RGFW_Right, - - RGFW_Delete, - RGFW_Insert, - RGFW_End, - RGFW_Home, - RGFW_PageUp, - RGFW_PageDown, - - RGFW_Numlock, + RGFW_numLock, RGFW_KP_Slash, - RGFW_Multiply, + RGFW_multiply, RGFW_KP_Minus, RGFW_KP_1, RGFW_KP_2, @@ -1122,104 +1297,101 @@ typedef RGFW_ENUM(u8, RGFW_Key) { RGFW_KP_0, RGFW_KP_Period, RGFW_KP_Return, - - final_key, + RGFW_keyLast }; +RGFWDEF u32 RGFW_apiKeyToRGFW(u32 keycode); typedef RGFW_ENUM(u8, RGFW_mouseIcons) { - RGFW_MOUSE_NORMAL = 0, - RGFW_MOUSE_ARROW, - RGFW_MOUSE_IBEAM, - RGFW_MOUSE_CROSSHAIR, - RGFW_MOUSE_POINTING_HAND, - RGFW_MOUSE_RESIZE_EW, - RGFW_MOUSE_RESIZE_NS, - RGFW_MOUSE_RESIZE_NWSE, - RGFW_MOUSE_RESIZE_NESW, - RGFW_MOUSE_RESIZE_ALL, - RGFW_MOUSE_NOT_ALLOWED, + RGFW_mouseNormal = 0, + RGFW_mouseArrow, + RGFW_mouseIbeam, + RGFW_mouseCrosshair, + RGFW_mousePointingHand, + RGFW_mouseResizeEW, + RGFW_mouseResizeNS, + RGFW_mouseResizeNWSE, + RGFW_mouseResizeNESW, + RGFW_mouseResizeAll, + RGFW_mouseNotAllowed, }; -/** @} */ +/** @} */ #endif /* RGFW_HEADER */ - -/* -Example to get you started : - -linux : gcc main.c -lX11 -lXcursor -lGL -windows : gcc main.c -lopengl32 -lshell32 -lgdi32 -macos : gcc main.c -framework Foundation -framework AppKit -framework OpenGL -framework CoreVideo - -#define RGFW_IMPLEMENTATION -#include "RGFW.h" - -u8 icon[4 * 3 * 3] = {0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF}; - -int main() { - RGFW_window* win = RGFW_createWindow("name", RGFW_RECT(500, 500, 500, 500), (u64)0); - - RGFW_window_setIcon(win, icon, RGFW_AREA(3, 3), 4); - - for (;;) { - RGFW_window_checkEvent(win); // NOTE: checking events outside of a while loop may cause input lag - if (win->event.type == RGFW_quit || RGFW_isPressed(win, RGFW_Escape)) - break; - - RGFW_window_swapBuffers(win); - - glClearColor(0xFF, 0XFF, 0xFF, 0xFF); - glClear(GL_COLOR_BUFFER_BIT); - } - - RGFW_window_close(win); -} - - compiling : - - if you wish to compile the library all you have to do is create a new file with this in it - - rgfw.c - #define RGFW_IMPLEMENTATION - #include "RGFW.h" - - then you can use gcc (or whatever compile you wish to use) to compile the library into object file - - ex. gcc -c RGFW.c -fPIC - - after you compile the library into an object file, you can also turn the object file into an static or shared library - - (commands ar and gcc can be replaced with whatever equivalent your system uses) - static : ar rcs RGFW.a RGFW.o - shared : - windows: - gcc -shared RGFW.o -lwinmm -lopengl32 -lshell32 -lgdi32 -o RGFW.dll - linux: - gcc -shared RGFW.o -lX11 -lXcursor -lGL -lXrandr -o RGFW.so - macos: - gcc -shared RGFW.o -framework Foundation -framework AppKit -framework OpenGL -framework CoreVideo -*/ - -#ifdef RGFW_X11 - #define RGFW_OS_BASED_VALUE(l, w, m, h, ww) l +#if defined(RGFW_X11) || defined(RGFW_WAYLAND) + #define RGFW_OS_BASED_VALUE(l, w, m, h) l #elif defined(RGFW_WINDOWS) - #define RGFW_OS_BASED_VALUE(l, w, m, h, ww) w + #define RGFW_OS_BASED_VALUE(l, w, m, h) w #elif defined(RGFW_MACOS) - #define RGFW_OS_BASED_VALUE(l, w, m, h, ww) m + #define RGFW_OS_BASED_VALUE(l, w, m, h) m #elif defined(RGFW_WEBASM) - #define RGFW_OS_BASED_VALUE(l, w, m, h, ww) h -#elif defined(RGFW_WAYLAND) - #define RGFW_OS_BASED_VALUE(l, w, m, h, ww) ww + #define RGFW_OS_BASED_VALUE(l, w, m, h) h #endif #ifdef RGFW_IMPLEMENTATION +b8 RGFW_useWaylandBool = 1; +#ifdef RGFW_DEBUG #include -#include -#include -#include +#endif + +#ifndef RGFW_ASSERT + #include + #define RGFW_ASSERT assert +#endif + +/* + RGFW_allocator, (optional) + you can ignore this if you use standard malloc/free +*/ + +void* RGFW_allocatorMalloc(void* userdata, size_t size) { + void* out = RGFW_ALLOC(userdata, size); RGFW_ASSERT(out != NULL); + return out; +} +void RGFW_allocatorFree(void* userdata, void* ptr) { RGFW_ASSERT(ptr != NULL); RGFW_FREE(userdata, ptr); } +RGFW_allocator RGFW_current_allocator = {RGFW_USERPTR, RGFW_allocatorMalloc, RGFW_allocatorFree}; + +RGFW_allocator RGFW_loadAllocator(RGFW_allocator allocator) { + RGFW_allocator old = RGFW_current_allocator; + RGFW_current_allocator = allocator; + return old; +} + +void* RGFW_alloc(size_t len) { return RGFW_current_allocator.alloc(RGFW_current_allocator.userdata, len); } +void RGFW_free(void* ptr) { RGFW_current_allocator.free(RGFW_current_allocator.userdata, ptr); } + + +char* RGFW_clipboard_data = NULL; +RGFW_allocator RGFW_clipboard_alloc; + +void RGFW_clipboard_switch(char* newstr) { + if (RGFW_clipboard_data != NULL) + RGFW_clipboard_alloc.free(RGFW_clipboard_alloc.userdata, RGFW_clipboard_data); + RGFW_clipboard_data = newstr; + RGFW_clipboard_alloc = RGFW_current_allocator; +} + +#define RGFW_CHECK_CLIPBOARD() \ + if (size <= 0 && RGFW_clipboard_data != NULL) \ + return (const char*)RGFW_clipboard_data; \ + else if (size <= 0) \ + return "\0"; + +const char* RGFW_readClipboard(size_t* len) { + RGFW_ssize_t size = RGFW_readClipboardPtr(NULL, 0); + RGFW_CHECK_CLIPBOARD(); + char* str = (char*)RGFW_alloc(size); + size = RGFW_readClipboardPtr(str, size); + RGFW_CHECK_CLIPBOARD(); + + if (len != NULL) *len = size; + + RGFW_clipboard_switch(str); + return (const char*)str; +} /* RGFW_IMPLEMENTATION starts with generic RGFW defines @@ -1227,165 +1399,148 @@ RGFW_IMPLEMENTATION starts with generic RGFW defines This is the start of keycode data Why not use macros instead of the numbers itself? - Windows -> Not all virtual keys are macros (VK_0 - VK_1, VK_a - VK_z) + Windows -> Not all scancodes keys are macros Linux -> Only symcodes are values, (XK_0 - XK_1, XK_a - XK_z) are larger than 0xFF00, I can't find any way to work with them without making the array an unreasonable size MacOS -> windows and linux already don't have keycodes as macros, so there's no point */ -/* - the c++ compiler doesn't support setting up an array like, +/* + the c++ compiler doesn't support setting up an array like, we'll have to do it during runtime using a function & this messy setup */ + +#ifndef RGFW_CUSTOM_BACKEND + #ifndef __cplusplus #define RGFW_NEXT , #define RGFW_MAP -#else +#else #define RGFW_NEXT ; #define RGFW_MAP RGFW_keycodes #endif -#ifdef RGFW_WAYLAND -#include -#endif - -u8 RGFW_keycodes [RGFW_OS_BASED_VALUE(136, 337, 128, DOM_VK_WIN_OEM_CLEAR + 1, 130)] = { +u8 RGFW_keycodes [RGFW_OS_BASED_VALUE(136, 0x15C + 1, 128, DOM_VK_WIN_OEM_CLEAR + 1)] = { #ifdef __cplusplus 0 }; void RGFW_init_keys(void) { #endif - RGFW_MAP [RGFW_OS_BASED_VALUE(49, 192, 50, DOM_VK_BACK_QUOTE, KEY_GRAVE)] = RGFW_Backtick RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(49, 0x029, 50, DOM_VK_BACK_QUOTE)] = RGFW_backtick RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(19, 0x30, 29, DOM_VK_0, KEY_0)] = RGFW_0 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(10, 0x31, 18, DOM_VK_1, KEY_1)] = RGFW_1 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(11, 0x32, 19, DOM_VK_2, KEY_2)] = RGFW_2 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(12, 0x33, 20, DOM_VK_3, KEY_3)] = RGFW_3 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(13, 0x34, 21, DOM_VK_4, KEY_4)] = RGFW_4 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(14, 0x35, 23, DOM_VK_5, KEY_5)] = RGFW_5 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(15, 0x36, 22, DOM_VK_6, KEY_6)] = RGFW_6 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(16, 0x37, 26, DOM_VK_7, KEY_7)] = RGFW_7 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(17, 0x38, 28, DOM_VK_8, KEY_8)] = RGFW_8 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(18, 0x39, 25, DOM_VK_9, KEY_9)] = RGFW_9, - - RGFW_MAP [RGFW_OS_BASED_VALUE(65, 0x20, 49, DOM_VK_SPACE, KEY_SPACE)] = RGFW_Space, - - RGFW_MAP [RGFW_OS_BASED_VALUE(38, 0x41, 0, DOM_VK_A, KEY_A)] = RGFW_a RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(56, 0x42, 11, DOM_VK_B, KEY_B)] = RGFW_b RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(54, 0x43, 8, DOM_VK_C, KEY_C)] = RGFW_c RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(40, 0x44, 2, DOM_VK_D, KEY_D)] = RGFW_d RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(26, 0x45, 14, DOM_VK_E, KEY_E)] = RGFW_e RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(41, 0x46, 3, DOM_VK_F, KEY_F)] = RGFW_f RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(42, 0x47, 5, DOM_VK_G, KEY_G)] = RGFW_g RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(43, 0x48, 4, DOM_VK_H, KEY_H)] = RGFW_h RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(31, 0x49, 34, DOM_VK_I, KEY_I)] = RGFW_i RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(44, 0x4A, 38, DOM_VK_J, KEY_J)] = RGFW_j RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(45, 0x4B, 40, DOM_VK_K, KEY_K)] = RGFW_k RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(46, 0x4C, 37, DOM_VK_L, KEY_L)] = RGFW_l RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(58, 0x4D, 46, DOM_VK_M, KEY_M)] = RGFW_m RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(57, 0x4E, 45, DOM_VK_N, KEY_N)] = RGFW_n RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(32, 0x4F, 31, DOM_VK_O, KEY_O)] = RGFW_o RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(33, 0x50, 35, DOM_VK_P, KEY_P)] = RGFW_p RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(24, 0x51, 12, DOM_VK_Q, KEY_Q)] = RGFW_q RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(27, 0x52, 15, DOM_VK_R, KEY_R)] = RGFW_r RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(39, 0x53, 1, DOM_VK_S, KEY_S)] = RGFW_s RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(28, 0x54, 17, DOM_VK_T, KEY_T)] = RGFW_t RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(30, 0x55, 32, DOM_VK_U, KEY_U)] = RGFW_u RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(55, 0x56, 9, DOM_VK_V, KEY_V)] = RGFW_v RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(25, 0x57, 13, DOM_VK_W, KEY_W)] = RGFW_w RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(53, 0x58, 7, DOM_VK_X, KEY_X)] = RGFW_x RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(29, 0x59, 16, DOM_VK_Y, KEY_Y)] = RGFW_y RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(52, 0x5A, 6, DOM_VK_Z, KEY_Z)] = RGFW_z, - - RGFW_MAP [RGFW_OS_BASED_VALUE(60, 190, 47, DOM_VK_PERIOD, KEY_DOT)] = RGFW_Period RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(59, 188, 43, DOM_VK_COMMA, KEY_COMMA)] = RGFW_Comma RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(61, 191, 44, DOM_VK_SLASH, KEY_SLASH)] = RGFW_Slash RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(34, 219, 33, DOM_VK_OPEN_BRACKET, KEY_LEFTBRACE)] = RGFW_Bracket RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(35, 221, 30, DOM_VK_CLOSE_BRACKET, KEY_RIGHTBRACE)] = RGFW_CloseBracket RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(47, 186, 41, DOM_VK_SEMICOLON, KEY_SEMICOLON)] = RGFW_Semicolon RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(48, 222, 39, DOM_VK_QUOTE, KEY_APOSTROPHE)] = RGFW_Quote RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(51, 322, 42, DOM_VK_BACK_SLASH, KEY_BACKSLASH)] = RGFW_BackSlash, - - RGFW_MAP [RGFW_OS_BASED_VALUE(36, 0x0D, 36, DOM_VK_RETURN, KEY_ENTER)] = RGFW_Return RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(119, 0x2E, 118, DOM_VK_DELETE, KEY_DELETE)] = RGFW_Delete RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(77, 0x90, 72, DOM_VK_NUM_LOCK, KEY_NUMLOCK)] = RGFW_Numlock RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(106, 0x6F, 82, DOM_VK_DIVIDE, KEY_KPSLASH)] = RGFW_KP_Slash RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(63, 0x6A, 76, DOM_VK_MULTIPLY, KEY_KPASTERISK)] = RGFW_Multiply RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(82, 0x6D, 67, DOM_VK_SUBTRACT, KEY_KPMINUS)] = RGFW_KP_Minus RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(87, 0x61, 84, DOM_VK_NUMPAD1, KEY_KP1)] = RGFW_KP_1 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(88, 0x62, 85, DOM_VK_NUMPAD2, KEY_KP2)] = RGFW_KP_2 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(89, 0x63, 86, DOM_VK_NUMPAD3, KEY_KP3)] = RGFW_KP_3 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(83, 0x64, 87, DOM_VK_NUMPAD4, KEY_KP4)] = RGFW_KP_4 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(84, 0x65, 88, DOM_VK_NUMPAD5, KEY_KP5)] = RGFW_KP_5 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(85, 0x66, 89, DOM_VK_NUMPAD6, KEY_KP6)] = RGFW_KP_6 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(79, 0x67, 90, DOM_VK_NUMPAD7, KEY_KP7)] = RGFW_KP_7 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(80, 0x68, 92, DOM_VK_NUMPAD8, KEY_KP8)] = RGFW_KP_8 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(81, 0x69, 93, DOM_VK_NUMPAD9, KEY_KP9)] = RGFW_KP_9 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(90, 0x60, 83, DOM_VK_NUMPAD0, KEY_KP0)] = RGFW_KP_0 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(91, 0x6E, 65, DOM_VK_DECIMAL, KEY_KPDOT)] = RGFW_KP_Period RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(104, 0x92, 77, 0, KEY_KPENTER)] = RGFW_KP_Return, - - RGFW_MAP [RGFW_OS_BASED_VALUE(20, 189, 27, DOM_VK_HYPHEN_MINUS, KEY_MINUS)] = RGFW_Minus RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(21, 187, 24, DOM_VK_EQUALS, KEY_EQUAL)] = RGFW_Equals RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(22, 8, 51, DOM_VK_BACK_SPACE, KEY_BACKSPACE)] = RGFW_BackSpace RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(23, 0x09, 48, DOM_VK_TAB, KEY_TAB)] = RGFW_Tab RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(66, 20, 57, DOM_VK_CAPS_LOCK, KEY_CAPSLOCK)] = RGFW_CapsLock RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(50, 0x10, 56, DOM_VK_SHIFT, KEY_LEFTSHIFT)] = RGFW_ShiftL RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(37, 0x11, 59, DOM_VK_CONTROL, KEY_LEFTCTRL)] = RGFW_ControlL RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(64,0x12, 58, DOM_VK_ALT, KEY_LEFTALT)] = RGFW_AltL RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(133, 0x5B, 55, DOM_VK_WIN, KEY_LEFTMETA)] = RGFW_SuperL, - - #if !defined(RGFW_WINDOWS) && !defined(RGFW_MACOS) && !defined(RGFW_WEBASM) - RGFW_MAP [RGFW_OS_BASED_VALUE(105, 0x11, 59, 0, KEY_RIGHTCTRL)] = RGFW_ControlR RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(135, 0xA4, 55, 0, KEY_RIGHTMETA)] = RGFW_SuperR, - RGFW_MAP [RGFW_OS_BASED_VALUE(62, 0x5C, 56, 0, KEY_RIGHTSHIFT)] = RGFW_ShiftR RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(108, 165, 58, 0, KEY_RIGHTALT)] = RGFW_AltR, + RGFW_MAP [RGFW_OS_BASED_VALUE(19, 0x00B, 29, DOM_VK_0)] = RGFW_0 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(10, 0x002, 18, DOM_VK_1)] = RGFW_1 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(11, 0x003, 19, DOM_VK_2)] = RGFW_2 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(12, 0x004, 20, DOM_VK_3)] = RGFW_3 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(13, 0x005, 21, DOM_VK_4)] = RGFW_4 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(14, 0x006, 23, DOM_VK_5)] = RGFW_5 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(15, 0x007, 22, DOM_VK_6)] = RGFW_6 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(16, 0x008, 26, DOM_VK_7)] = RGFW_7 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(17, 0x009, 28, DOM_VK_8)] = RGFW_8 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(18, 0x00A, 25, DOM_VK_9)] = RGFW_9, + RGFW_MAP [RGFW_OS_BASED_VALUE(65, 0x039, 49, DOM_VK_SPACE)] = RGFW_space, + RGFW_MAP [RGFW_OS_BASED_VALUE(38, 0x01E, 0, DOM_VK_A)] = RGFW_a RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(56, 0x030, 11, DOM_VK_B)] = RGFW_b RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(54, 0x02E, 8, DOM_VK_C)] = RGFW_c RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(40, 0x020, 2, DOM_VK_D)] = RGFW_d RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(26, 0x012, 14, DOM_VK_E)] = RGFW_e RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(41, 0x021, 3, DOM_VK_F)] = RGFW_f RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(42, 0x022, 5, DOM_VK_G)] = RGFW_g RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(43, 0x023, 4, DOM_VK_H)] = RGFW_h RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(31, 0x017, 34, DOM_VK_I)] = RGFW_i RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(44, 0x024, 38, DOM_VK_J)] = RGFW_j RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(45, 0x025, 40, DOM_VK_K)] = RGFW_k RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(46, 0x026, 37, DOM_VK_L)] = RGFW_l RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(58, 0x032, 46, DOM_VK_M)] = RGFW_m RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(57, 0x031, 45, DOM_VK_N)] = RGFW_n RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(32, 0x018, 31, DOM_VK_O)] = RGFW_o RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(33, 0x019, 35, DOM_VK_P)] = RGFW_p RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(24, 0x010, 12, DOM_VK_Q)] = RGFW_q RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(27, 0x013, 15, DOM_VK_R)] = RGFW_r RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(39, 0x01F, 1, DOM_VK_S)] = RGFW_s RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(28, 0x014, 17, DOM_VK_T)] = RGFW_t RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(30, 0x016, 32, DOM_VK_U)] = RGFW_u RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(55, 0x02F, 9, DOM_VK_V)] = RGFW_v RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(25, 0x011, 13, DOM_VK_W)] = RGFW_w RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(53, 0x02D, 7, DOM_VK_X)] = RGFW_x RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(29, 0x015, 16, DOM_VK_Y)] = RGFW_y RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(52, 0x02C, 6, DOM_VK_Z)] = RGFW_z, + RGFW_MAP [RGFW_OS_BASED_VALUE(60, 0x034, 47, DOM_VK_PERIOD)] = RGFW_period RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(59, 0x033, 43, DOM_VK_COMMA)] = RGFW_comma RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(61, 0x035, 44, DOM_VK_SLASH)] = RGFW_slash RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(34, 0x01A, 33, DOM_VK_OPEN_BRACKET)] = RGFW_bracket RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(35, 0x01B, 30, DOM_VK_CLOSE_BRACKET)] = RGFW_closeBracket RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(47, 0x027, 41, DOM_VK_SEMICOLON)] = RGFW_semicolon RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(48, 0x028, 39, DOM_VK_QUOTE)] = RGFW_apostrophe RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(51, 0x02B, 42, DOM_VK_BACK_SLASH)] = RGFW_backSlash, + RGFW_MAP [RGFW_OS_BASED_VALUE(36, 0x01C, 36, DOM_VK_RETURN)] = RGFW_return RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(119, 0x153, 118, DOM_VK_DELETE)] = RGFW_delete RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(77, 0x145, 72, DOM_VK_NUM_LOCK)] = RGFW_numLock RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(106, 0x135, 82, DOM_VK_DIVIDE)] = RGFW_KP_Slash RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(63, 0x037, 76, DOM_VK_MULTIPLY)] = RGFW_multiply RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(82, 0x04A, 67, DOM_VK_SUBTRACT)] = RGFW_KP_Minus RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(87, 0x04F, 84, DOM_VK_NUMPAD1)] = RGFW_KP_1 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(88, 0x050, 85, DOM_VK_NUMPAD2)] = RGFW_KP_2 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(89, 0x051, 86, DOM_VK_NUMPAD3)] = RGFW_KP_3 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(83, 0x04B, 87, DOM_VK_NUMPAD4)] = RGFW_KP_4 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(84, 0x04C, 88, DOM_VK_NUMPAD5)] = RGFW_KP_5 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(85, 0x04D, 89, DOM_VK_NUMPAD6)] = RGFW_KP_6 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(79, 0x047, 90, DOM_VK_NUMPAD7)] = RGFW_KP_7 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(80, 0x048, 92, DOM_VK_NUMPAD8)] = RGFW_KP_8 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(81, 0x049, 93, DOM_VK_NUMPAD9)] = RGFW_KP_9 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(90, 0x052, 83, DOM_VK_NUMPAD0)] = RGFW_KP_0 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(91, 0x053, 65, DOM_VK_DECIMAL)] = RGFW_KP_Period RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(104, 0x11C, 77, 0)] = RGFW_KP_Return, + RGFW_MAP [RGFW_OS_BASED_VALUE(20, 0x00C, 27, DOM_VK_HYPHEN_MINUS)] = RGFW_minus RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(21, 0x00D, 24, DOM_VK_EQUALS)] = RGFW_equals RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(22, 0x00E, 51, DOM_VK_BACK_SPACE)] = RGFW_backSpace RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(23, 0x00F, 48, DOM_VK_TAB)] = RGFW_tab RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(66, 0x03A, 57, DOM_VK_CAPS_LOCK)] = RGFW_capsLock RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(50, 0x02A, 56, DOM_VK_SHIFT)] = RGFW_shiftL RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(37, 0x01D, 59, DOM_VK_CONTROL)] = RGFW_controlL RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(64, 0x038, 58, DOM_VK_ALT)] = RGFW_altL RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(133, 0x15B, 55, DOM_VK_WIN)] = RGFW_superL, + #if !defined(RGFW_MACOS) && !defined(RGFW_WEBASM) + RGFW_MAP [RGFW_OS_BASED_VALUE(105, 0x11D, 59, 0)] = RGFW_controlR RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(135, 0x15C, 55, 0)] = RGFW_superR, + RGFW_MAP [RGFW_OS_BASED_VALUE(62, 0x036, 56, 0)] = RGFW_shiftR RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(108, 0x138, 58, 0)] = RGFW_altR, #endif - - RGFW_MAP [RGFW_OS_BASED_VALUE(67, 0x70, 127, DOM_VK_F1, KEY_F1)] = RGFW_F1 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(68, 0x71, 121, DOM_VK_F2, KEY_F2)] = RGFW_F2 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(69, 0x72, 100, DOM_VK_F3, KEY_F3)] = RGFW_F3 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(70, 0x73, 119, DOM_VK_F4, KEY_F4)] = RGFW_F4 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(71, 0x74, 97, DOM_VK_F5, KEY_F5)] = RGFW_F5 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(72, 0x75, 98, DOM_VK_F6, KEY_F6)] = RGFW_F6 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(73, 0x76, 99, DOM_VK_F7, KEY_F7)] = RGFW_F7 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(74, 0x77, 101, DOM_VK_F8, KEY_F8)] = RGFW_F8 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(75, 0x78, 102, DOM_VK_F9, KEY_F9)] = RGFW_F9 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(76, 0x79, 110, DOM_VK_F10, KEY_F10)] = RGFW_F10 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(95, 0x7A, 104, DOM_VK_F11, KEY_F11)] = RGFW_F11 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(96, 0x7B, 112, DOM_VK_F12, KEY_F12)] = RGFW_F12 RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(111, 0x26, 126, DOM_VK_UP, KEY_UP)] = RGFW_Up RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(116, 0x28, 125, DOM_VK_DOWN, KEY_DOWN)] = RGFW_Down RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(113, 0x25, 123, DOM_VK_LEFT, KEY_LEFT)] = RGFW_Left RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(114, 0x27, 124, DOM_VK_RIGHT, KEY_RIGHT)] = RGFW_Right RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(118, 0x2D, 115, DOM_VK_INSERT, KEY_INSERT)] = RGFW_Insert RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(115, 0x23, 120, DOM_VK_END, KEY_END)] = RGFW_End RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(112, 336, 117, DOM_VK_PAGE_UP, KEY_PAGEUP)] = RGFW_PageUp RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(117, 325, 122, DOM_VK_PAGE_DOWN, KEY_PAGEDOWN)] = RGFW_PageDown RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(9, 0x1B, 53, DOM_VK_ESCAPE, KEY_ESC)] = RGFW_Escape RGFW_NEXT - RGFW_MAP [RGFW_OS_BASED_VALUE(110, 0x24, 116, DOM_VK_HOME, KEY_HOME)] = RGFW_Home RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(67, 0x03B, 127, DOM_VK_F1)] = RGFW_F1 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(68, 0x03C, 121, DOM_VK_F2)] = RGFW_F2 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(69, 0x03D, 100, DOM_VK_F3)] = RGFW_F3 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(70, 0x03E, 119, DOM_VK_F4)] = RGFW_F4 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(71, 0x03F, 97, DOM_VK_F5)] = RGFW_F5 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(72, 0x040, 98, DOM_VK_F6)] = RGFW_F6 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(73, 0x041, 99, DOM_VK_F7)] = RGFW_F7 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(74, 0x042, 101, DOM_VK_F8)] = RGFW_F8 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(75, 0x043, 102, DOM_VK_F9)] = RGFW_F9 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(76, 0x044, 110, DOM_VK_F10)] = RGFW_F10 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(95, 0x057, 104, DOM_VK_F11)] = RGFW_F11 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(96, 0x058, 112, DOM_VK_F12)] = RGFW_F12 RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(111, 0x148, 126, DOM_VK_UP)] = RGFW_up RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(116, 0x150, 125, DOM_VK_DOWN)] = RGFW_down RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(113, 0x14B, 123, DOM_VK_LEFT)] = RGFW_left RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(114, 0x14D, 124, DOM_VK_RIGHT)] = RGFW_right RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(118, 0x152, 115, DOM_VK_INSERT)] = RGFW_insert RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(115, 0x14F, 120, DOM_VK_END)] = RGFW_end RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(112, 0x149, 117, DOM_VK_PAGE_UP)] = RGFW_pageUp RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(117, 0x151, 122, DOM_VK_PAGE_DOWN)] = RGFW_pageDown RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(9, 0x001, 53, DOM_VK_ESCAPE)] = RGFW_escape RGFW_NEXT + RGFW_MAP [RGFW_OS_BASED_VALUE(110, 0x147, 116, DOM_VK_HOME)] = RGFW_home RGFW_NEXT #ifndef __cplusplus }; -#else +#else } #endif #undef RGFW_NEXT #undef RGFW_MAP -typedef struct { - b8 current : 1; - b8 prev : 1; -} RGFW_keyState; - -RGFW_keyState RGFW_keyboard[final_key] = { {0, 0} }; - -RGFWDEF u32 RGFW_apiKeyCodeToRGFW(u32 keycode); - -u32 RGFW_apiKeyCodeToRGFW(u32 keycode) { +u32 RGFW_apiKeyToRGFW(u32 keycode) { #ifdef __cplusplus - if (RGFW_OS_BASED_VALUE(49, 192, 50, DOM_VK_BACK_QUOTE, KEY_GRAVE) != RGFW_Backtick) { + if (RGFW_OS_BASED_VALUE(49, 192, 50, DOM_VK_BACK_QUOTE, KEY_GRAVE) != RGFW_backtick) { RGFW_init_keys(); } #endif @@ -1393,69 +1548,48 @@ u32 RGFW_apiKeyCodeToRGFW(u32 keycode) { /* make sure the key isn't out of bounds */ if (keycode > sizeof(RGFW_keycodes) / sizeof(u8)) return 0; - + return RGFW_keycodes[keycode]; } +#endif + +typedef struct { + b8 current : 1; + b8 prev : 1; +} RGFW_keyState; + +RGFW_keyState RGFW_keyboard[RGFW_keyLast] = { {0, 0} }; RGFWDEF void RGFW_resetKey(void); void RGFW_resetKey(void) { - size_t len = final_key; /*!< last_key == length */ - + size_t len = RGFW_keyLast; /*!< last_key == length */ + size_t i; /*!< reset each previous state */ for (i = 0; i < len; i++) RGFW_keyboard[i].prev = 0; } -b8 RGFW_shouldShift(u32 keycode, u8 lockState) { - #define RGFW_xor(x, y) (( (x) && (!(y)) ) || ((y) && (!(x)) )) - b8 caps4caps = (lockState & RGFW_CAPSLOCK) && ((keycode >= RGFW_a) && (keycode <= RGFW_z)); - b8 shouldShift = RGFW_xor((RGFW_isPressed(NULL, RGFW_ShiftL) || RGFW_isPressed(NULL, RGFW_ShiftR)), caps4caps); - #undef RGFW_xor - - return shouldShift; -} - -char RGFW_keyCodeToChar(u32 keycode, b8 shift) { - static const char map[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '`', '0', '1', '2', '3', '4', '5', '6', '7', '8', - '9', '-', '=', 0, '\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '.', ',', '/', '[', ']', ';', '\n', '\'', '\\', - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '/', '*', '-', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '\n' - }; - - static const char mapCaps[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '~', ')', '!', '@', '#', '$', '%', '^', '&', '*', - '(', '_', '+', 0, '0', 0, 0, 0, 0, 0, 0, 0, 0, 0, ' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G', - 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', - 'X', 'Y', 'Z', '>', '<', '?', '{', '}', ':', '\n', '"', '|', - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '?', '*', '-', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - - if (shift == RGFW_FALSE) - return map[keycode]; - return mapCaps[keycode]; -} - -char RGFW_keyCodeToCharAuto(u32 keycode, u8 lockState) { return RGFW_keyCodeToChar(keycode, RGFW_shouldShift(keycode, lockState)); } - /* this is the end of keycode data */ -/* joystick data */ -u8 RGFW_jsPressed[4][16]; /*!< if a key is currently pressed or not (per joystick) */ +/* gamepad data */ +RGFW_keyState RGFW_gamepadPressed[4][18]; /*!< if a key is currently pressed or not (per gamepad) */ +RGFW_point RGFW_gamepadAxes[4][4]; /*!< if a key is currently pressed or not (per gamepad) */ -i32 RGFW_joysticks[4]; /*!< limit of 4 joysticks at a time */ -u16 RGFW_joystickCount; /*!< the actual amount of joysticks */ +RGFW_gamepadType RGFW_gamepads_type[4]; /*!< if a key is currently pressed or not (per gamepad) */ +i32 RGFW_gamepads[4] = {0, 0, 0, 0}; /*!< limit of 4 gamepads at a time */ +char RGFW_gamepads_name[4][128]; /*!< gamepad names */ +u16 RGFW_gamepadCount = 0; /*!< the actual amount of gamepads */ -/* +/* event callback defines start here */ /* - These exist to avoid the - if (func == NULL) check + These exist to avoid the + if (func == NULL) check for (allegedly) better performance */ void RGFW_windowmovefuncEMPTY(RGFW_window* win, RGFW_rect r) { RGFW_UNUSED(win); RGFW_UNUSED(r); } @@ -1466,10 +1600,11 @@ void RGFW_mouseNotifyfuncEMPTY(RGFW_window* win, RGFW_point point, b8 status) {R void RGFW_mouseposfuncEMPTY(RGFW_window* win, RGFW_point point) {RGFW_UNUSED(win); RGFW_UNUSED(point);} void RGFW_dndInitfuncEMPTY(RGFW_window* win, RGFW_point point) {RGFW_UNUSED(win); RGFW_UNUSED(point);} void RGFW_windowrefreshfuncEMPTY(RGFW_window* win) {RGFW_UNUSED(win); } -void RGFW_keyfuncEMPTY(RGFW_window* win, u32 keycode, char keyName[16], u8 lockState, b8 pressed) {RGFW_UNUSED(win); RGFW_UNUSED(keycode); RGFW_UNUSED(keyName); RGFW_UNUSED(lockState); RGFW_UNUSED(pressed);} -void RGFW_mousebuttonfuncEMPTY(RGFW_window* win, u8 button, double scroll, b8 pressed) {RGFW_UNUSED(win); RGFW_UNUSED(button); RGFW_UNUSED(scroll); RGFW_UNUSED(pressed);} -void RGFW_jsButtonfuncEMPTY(RGFW_window* win, u16 joystick, u8 button, b8 pressed){RGFW_UNUSED(win); RGFW_UNUSED(joystick); RGFW_UNUSED(button); RGFW_UNUSED(pressed); } -void RGFW_jsAxisfuncEMPTY(RGFW_window* win, u16 joystick, RGFW_point axis[2], u8 axisesCount){RGFW_UNUSED(win); RGFW_UNUSED(joystick); RGFW_UNUSED(axis); RGFW_UNUSED(axisesCount); } +void RGFW_keyfuncEMPTY(RGFW_window* win, RGFW_key key, char keyChar, RGFW_keymod keyMod, b8 pressed) {RGFW_UNUSED(win); RGFW_UNUSED(key); RGFW_UNUSED(keyChar); RGFW_UNUSED(keyMod); RGFW_UNUSED(pressed);} +void RGFW_mousebuttonfuncEMPTY(RGFW_window* win, RGFW_mouseButton button, double scroll, b8 pressed) {RGFW_UNUSED(win); RGFW_UNUSED(button); RGFW_UNUSED(scroll); RGFW_UNUSED(pressed);} +void RGFW_gamepadButtonfuncEMPTY(RGFW_window* win, u16 gamepad, u8 button, b8 pressed){RGFW_UNUSED(win); RGFW_UNUSED(gamepad); RGFW_UNUSED(button); RGFW_UNUSED(pressed); } +void RGFW_gamepadAxisfuncEMPTY(RGFW_window* win, u16 gamepad, RGFW_point axis[2], u8 axisesCount, u8 whichAxis){RGFW_UNUSED(win); RGFW_UNUSED(gamepad); RGFW_UNUSED(axis); RGFW_UNUSED(axisesCount); RGFW_UNUSED(whichAxis); } +void RGFW_gamepadfuncEMPTY(RGFW_window* win, u16 gamepad, b8 connected) {RGFW_UNUSED(win); RGFW_UNUSED(gamepad); RGFW_UNUSED(connected);} #ifdef RGFW_ALLOC_DROPFILES void RGFW_dndfuncEMPTY(RGFW_window* win, char** droppedFiles, u32 droppedFilesCount) {RGFW_UNUSED(win); RGFW_UNUSED(droppedFiles); RGFW_UNUSED(droppedFilesCount);} @@ -1488,22 +1623,23 @@ RGFW_dndfunc RGFW_dndCallback = RGFW_dndfuncEMPTY; RGFW_dndInitfunc RGFW_dndInitCallback = RGFW_dndInitfuncEMPTY; RGFW_keyfunc RGFW_keyCallback = RGFW_keyfuncEMPTY; RGFW_mousebuttonfunc RGFW_mouseButtonCallback = RGFW_mousebuttonfuncEMPTY; -RGFW_jsButtonfunc RGFW_jsButtonCallback = RGFW_jsButtonfuncEMPTY; -RGFW_jsAxisfunc RGFW_jsAxisCallback = RGFW_jsAxisfuncEMPTY; +RGFW_gamepadButtonfunc RGFW_gamepadButtonCallback = RGFW_gamepadButtonfuncEMPTY; +RGFW_gamepadAxisfunc RGFW_gamepadAxisCallback = RGFW_gamepadAxisfuncEMPTY; +RGFW_gamepadfunc RGFW_gamepadCallback = RGFW_gamepadfuncEMPTY; -void RGFW_window_checkEvents(RGFW_window* win, i32 waitMS) { +void RGFW_window_checkEvents(RGFW_window* win, i32 waitMS) { RGFW_window_eventWait(win, waitMS); - while (RGFW_window_checkEvent(win) != NULL && RGFW_window_shouldClose(win) == 0) { - if (win->event.type == RGFW_quit) return; + while (RGFW_window_checkEvent(win) != NULL && RGFW_window_shouldClose(win) == 0) { + if (win->event.type == RGFW_quit) return; } - + #ifdef RGFW_WEBASM /* webasm needs to run the sleep function for asyncify */ RGFW_sleep(0); #endif } -RGFW_windowmovefunc RGFW_setWindowMoveCallback(RGFW_windowmovefunc func) { +RGFW_windowmovefunc RGFW_setWindowMoveCallback(RGFW_windowmovefunc func) { RGFW_windowmovefunc prev = (RGFW_windowMoveCallback == RGFW_windowmovefuncEMPTY) ? NULL : RGFW_windowMoveCallback; RGFW_windowMoveCallback = func; return prev; @@ -1560,143 +1696,168 @@ RGFW_mousebuttonfunc RGFW_setMouseButtonCallback(RGFW_mousebuttonfunc func) { RGFW_mouseButtonCallback = func; return prev; } -RGFW_jsButtonfunc RGFW_setjsButtonCallback(RGFW_jsButtonfunc func) { - RGFW_jsButtonfunc prev = (RGFW_jsButtonCallback == RGFW_jsButtonfuncEMPTY) ? NULL : RGFW_jsButtonCallback; - RGFW_jsButtonCallback = func; +RGFW_gamepadButtonfunc RGFW_setgamepadButtonCallback(RGFW_gamepadButtonfunc func) { + RGFW_gamepadButtonfunc prev = (RGFW_gamepadButtonCallback == RGFW_gamepadButtonfuncEMPTY) ? NULL : RGFW_gamepadButtonCallback; + RGFW_gamepadButtonCallback = func; return prev; } -RGFW_jsAxisfunc RGFW_setjsAxisCallback(RGFW_jsAxisfunc func) { - RGFW_jsAxisfunc prev = (RGFW_jsAxisCallback == RGFW_jsAxisfuncEMPTY) ? NULL : RGFW_jsAxisCallback; - RGFW_jsAxisCallback = func; +RGFW_gamepadAxisfunc RGFW_setgamepadAxisCallback(RGFW_gamepadAxisfunc func) { + RGFW_gamepadAxisfunc prev = (RGFW_gamepadAxisCallback == RGFW_gamepadAxisfuncEMPTY) ? NULL : RGFW_gamepadAxisCallback; + RGFW_gamepadAxisCallback = func; return prev; } -/* +RGFW_gamepadfunc RGFW_setGamepadCallback(RGFW_gamepadfunc func) { + RGFW_gamepadfunc prev = (RGFW_gamepadCallback == RGFW_gamepadfuncEMPTY) ? NULL : RGFW_gamepadCallback; + RGFW_gamepadCallback = func; + return prev; +} +/* no more event call back defines */ -#define RGFW_ASSERT(check, str) {\ - if (!(check)) { \ - printf(str); \ - assert(check); \ - } \ -} - -b8 RGFW_error = 0; -b8 RGFW_Error(void) { return RGFW_error; } - #define SET_ATTRIB(a, v) { \ - assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \ + RGFW_ASSERT(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \ attribs[index++] = a; \ attribs[index++] = v; \ } - + +#define RGFW_NO_GPU_RENDER RGFW_BIT(20) /* don't render (using the GPU based API)*/ +#define RGFW_NO_CPU_RENDER RGFW_BIT(21) /* don't render (using the CPU based buffer rendering)*/ +#define RGFW_HOLD_MOUSE RGFW_BIT(22) /*!< hold the moues still */ +#define RGFW_MOUSE_LEFT RGFW_BIT(23) /* if mouse left the window */ +#define RGFW_WINDOW_ALLOC RGFW_BIT(24) /* if window was allocated by RGFW */ +#define RGFW_BUFFER_ALLOC RGFW_BIT(25) /* if window.buffer was allocated by RGFW */ + RGFW_area RGFW_bufferSize = {0, 0}; void RGFW_setBufferSize(RGFW_area size) { RGFW_bufferSize = size; } +RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, RGFW_windowFlags flags) { + RGFW_window* win = (RGFW_window*)RGFW_alloc(sizeof(RGFW_window)); + win->_flags |= RGFW_WINDOW_ALLOC; + return RGFW_createWindowPtr(name, rect, flags, win); +} -RGFWDEF RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args); +#if defined(RGFW_USE_XDL) && defined(RGFW_X11) + #define XDL_IMPLEMENTATION + #include "XDL.h" +#endif + +RGFWDEF void RGFW_window_basic_init(RGFW_window* win, RGFW_rect rect, RGFW_windowFlags flags); + +#if defined(RGFW_X11) || defined(RGFW_WINDOWS) +RGFW_mouse* RGFW_hiddenMouse = NULL; +#endif + +RGFW_window* RGFW_root = NULL; /* do a basic initialization for RGFW_window, this is to standard it for each OS */ -RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args) { - RGFW_window* win = (RGFW_window*) RGFW_MALLOC(sizeof(RGFW_window)); /*!< make a new RGFW struct */ - +void RGFW_window_basic_init(RGFW_window* win, RGFW_rect rect, RGFW_windowFlags flags) { /* clear out dnd info */ #ifdef RGFW_ALLOC_DROPFILES - win->event.droppedFiles = (char**) RGFW_MALLOC(sizeof(char*) * RGFW_MAX_DROPS); + win->event.droppedFiles = (char**) RGFW_alloc(sizeof(char*) * RGFW_MAX_DROPS); u32 i; - for (i = 0; i < RGFW_MAX_DROPS; i++) - win->event.droppedFiles[i] = (char*) RGFW_CALLOC(RGFW_MAX_PATH, sizeof(char)); + for (i = 0; i < RGFW_MAX_DROPS; i++) { + win->event.droppedFiles[i] = (char*) RGFW_alloc(RGFW_MAX_PATH); + win->event.droppedFiles[i][0] = 0; + } #endif /* X11 requires us to have a display to get the screen size */ - #ifndef RGFW_X11 + #ifndef RGFW_X11 RGFW_area screenR = RGFW_getScreenSize(); #else win->src.display = XOpenDisplay(NULL); - assert(win->src.display != NULL); + RGFW_ASSERT(win->src.display != NULL); - Screen* scrn = DefaultScreenOfDisplay((Display*)win->src.display); + Screen* scrn = DefaultScreenOfDisplay(win->src.display); RGFW_area screenR = RGFW_AREA((u32)scrn->width, (u32)scrn->height); #endif - - /* rect based the requested args */ - if (args & RGFW_FULLSCREEN) + + /* rect based the requested flags */ + if (flags & RGFW_windowFullscreen) rect = RGFW_RECT(0, 0, screenR.w, screenR.h); + if (RGFW_root == NULL) { + RGFW_root = win; + } + + #if defined(RGFW_X11) || defined(RGFW_WINDOWS) + if (RGFW_hiddenMouse == NULL) { + u8 RGFW_blk[] = { 0, 0, 0, 0 }; + RGFW_hiddenMouse = RGFW_loadMouse(RGFW_blk, RGFW_AREA(1, 1), 4); + } + #endif + /* set and init the new window's data */ win->r = rect; win->event.inFocus = 1; win->event.droppedFilesCount = 0; - RGFW_joystickCount = 0; - win->_winArgs = 0; - win->event.lockState = 0; - - return win; + win->_flags = 0; + win->event.keyMod = 0; + win->_mem.free = RGFW_current_allocator.free; } -#ifndef RGFW_NO_MONITOR -void RGFW_window_scaleToMonitor(RGFW_window* win) { - RGFW_monitor monitor = RGFW_window_getMonitor(win); - - RGFW_window_resize(win, RGFW_AREA((u32)(monitor.scaleX * (float)win->r.w), (u32)(monitor.scaleX * (float)win->r.h))); +void RGFW_window_setBufferPtr(RGFW_window* win, u8* ptr, RGFW_area size) { + RGFW_ASSERT(win); RGFW_ASSERT(ptr); + + #ifdef RGFW_BUFFER + if (win->buffer != NULL && ((win->_flags & RGFW_BUFFER_ALLOC))) { + win->_mem.free(win->_mem.userdata, win->buffer); + win->_flags ^= RGFW_BUFFER_ALLOC; + } + + RGFW_bufferSize = size; + win->buffer = ptr; + #else + RGFW_UNUSED(size); + #endif } -#endif - -RGFW_window* RGFW_root = NULL; - - -#define RGFW_HOLD_MOUSE (1L<<2) /*!< hold the moues still */ -#define RGFW_MOUSE_LEFT (1L<<3) /* if mouse left the window */ #ifdef RGFW_MACOS RGFWDEF void RGFW_window_cocoaSetLayer(RGFW_window* win, void* layer); RGFWDEF void* RGFW_cocoaGetLayer(void); #endif -char* RGFW_className = NULL; -void RGFW_setClassName(char* name) { +const char* RGFW_className = NULL; +void RGFW_setClassName(const char* name) { RGFW_className = name; } -void RGFW_clipboardFree(char* str) { RGFW_FREE(str); } - RGFW_keyState RGFW_mouseButtons[5] = { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} }; -b8 RGFW_isMousePressed(RGFW_window* win, u8 button) { - assert(win != NULL); - return RGFW_mouseButtons[button].current && (win != NULL) && win->event.inFocus; +b8 RGFW_isMousePressed(RGFW_window* win, RGFW_mouseButton button) { + return RGFW_mouseButtons[button].current && (win == NULL || win->event.inFocus); } -b8 RGFW_wasMousePressed(RGFW_window* win, u8 button) { - assert(win != NULL); - return RGFW_mouseButtons[button].prev && (win != NULL) && win->event.inFocus; +b8 RGFW_wasMousePressed(RGFW_window* win, RGFW_mouseButton button) { + return RGFW_mouseButtons[button].prev && (win != NULL || win->event.inFocus); } -b8 RGFW_isMouseHeld(RGFW_window* win, u8 button) { +b8 RGFW_isMouseHeld(RGFW_window* win, RGFW_mouseButton button) { return (RGFW_isMousePressed(win, button) && RGFW_wasMousePressed(win, button)); } -b8 RGFW_isMouseReleased(RGFW_window* win, u8 button) { - return (!RGFW_isMousePressed(win, button) && RGFW_wasMousePressed(win, button)); +b8 RGFW_isMouseReleased(RGFW_window* win, RGFW_mouseButton button) { + return (!RGFW_isMousePressed(win, button) && RGFW_wasMousePressed(win, button)); } -b8 RGFW_isPressed(RGFW_window* win, u8 key) { +b8 RGFW_isPressed(RGFW_window* win, RGFW_key key) { return RGFW_keyboard[key].current && (win == NULL || win->event.inFocus); } -b8 RGFW_wasPressed(RGFW_window* win, u8 key) { +b8 RGFW_wasPressed(RGFW_window* win, RGFW_key key) { return RGFW_keyboard[key].prev && (win == NULL || win->event.inFocus); } -b8 RGFW_isHeld(RGFW_window* win, u8 key) { +b8 RGFW_isHeld(RGFW_window* win, RGFW_key key) { return (RGFW_isPressed(win, key) && RGFW_wasPressed(win, key)); } -b8 RGFW_isClicked(RGFW_window* win, u8 key) { +b8 RGFW_isClicked(RGFW_window* win, RGFW_key key) { return (RGFW_wasPressed(win, key) && !RGFW_isPressed(win, key)); } -b8 RGFW_isReleased(RGFW_window* win, u8 key) { - return (!RGFW_isPressed(win, key) && RGFW_wasPressed(win, key)); +b8 RGFW_isReleased(RGFW_window* win, RGFW_key key) { + return (!RGFW_isPressed(win, key) && RGFW_wasPressed(win, key)); } #if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX) /* defines for directX context*/ @@ -1704,6 +1865,7 @@ b8 RGFW_isReleased(RGFW_window* win, u8 key) { RGFW_directXinfo* RGFW_getDirectXInfo(void) { return &RGFW_dxInfo; } #endif +#ifndef RGFW_CUSTOM_BACKEND void RGFW_window_makeCurrent(RGFW_window* win) { #if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX) if (win == NULL) @@ -1713,28 +1875,29 @@ void RGFW_window_makeCurrent(RGFW_window* win) { #elif defined(RGFW_OPENGL) RGFW_window_makeCurrent_OpenGL(win); #else - RGFW_UNUSED(win) + RGFW_UNUSED(win); #endif } +#endif void RGFW_window_setGPURender(RGFW_window* win, i8 set) { - if (!set && !(win->_winArgs & RGFW_NO_GPU_RENDER)) - win->_winArgs |= RGFW_NO_GPU_RENDER; - - else if (set && win->_winArgs & RGFW_NO_GPU_RENDER) - win->_winArgs ^= RGFW_NO_GPU_RENDER; + if (!set && !(win->_flags & RGFW_NO_GPU_RENDER)) + win->_flags |= RGFW_NO_GPU_RENDER; + + else if (set && win->_flags & RGFW_NO_GPU_RENDER) + win->_flags ^= RGFW_NO_GPU_RENDER; } void RGFW_window_setCPURender(RGFW_window* win, i8 set) { - if (!set && !(win->_winArgs & RGFW_NO_CPU_RENDER)) - win->_winArgs |= RGFW_NO_CPU_RENDER; + if (!set && !(win->_flags & RGFW_NO_CPU_RENDER)) + win->_flags |= RGFW_NO_CPU_RENDER; - else if (set && win->_winArgs & RGFW_NO_CPU_RENDER) - win->_winArgs ^= RGFW_NO_CPU_RENDER; + else if (set && win->_flags & RGFW_NO_CPU_RENDER) + win->_flags ^= RGFW_NO_CPU_RENDER; } void RGFW_window_maximize(RGFW_window* win) { - assert(win != NULL); + RGFW_ASSERT(win != NULL); RGFW_area screen = RGFW_getScreenSize(); @@ -1743,37 +1906,43 @@ void RGFW_window_maximize(RGFW_window* win) { } b8 RGFW_window_shouldClose(RGFW_window* win) { - assert(win != NULL); - return (win->event.type == RGFW_quit || RGFW_isPressed(win, RGFW_Escape)); + RGFW_ASSERT(win != NULL); + return (win->event.type == RGFW_quit || RGFW_isPressed(win, RGFW_escape)); } void RGFW_window_setShouldClose(RGFW_window* win) { win->event.type = RGFW_quit; RGFW_windowQuitCallback(win); } #ifndef RGFW_NO_MONITOR - void RGFW_window_moveToMonitor(RGFW_window* win, RGFW_monitor m) { - RGFW_window_move(win, RGFW_POINT(m.rect.x + win->r.x, m.rect.y + win->r.y)); - } +void RGFW_window_scaleToMonitor(RGFW_window* win) { + RGFW_monitor monitor = RGFW_window_getMonitor(win); + + RGFW_window_resize(win, RGFW_AREA((u32)(monitor.scaleX * (float)win->r.w), (u32)(monitor.scaleY * (float)win->r.h))); +} + +void RGFW_window_moveToMonitor(RGFW_window* win, RGFW_monitor m) { + RGFW_window_move(win, RGFW_POINT(m.rect.x + win->r.x, m.rect.y + win->r.y)); +} #endif RGFWDEF void RGFW_captureCursor(RGFW_window* win, RGFW_rect); RGFWDEF void RGFW_releaseCursor(RGFW_window* win); void RGFW_window_mouseHold(RGFW_window* win, RGFW_area area) { - if ((win->_winArgs & RGFW_HOLD_MOUSE)) + if ((win->_flags & RGFW_HOLD_MOUSE)) return; - + if (!area.w && !area.h) area = RGFW_AREA(win->r.w / 2, win->r.h / 2); - - win->_winArgs |= RGFW_HOLD_MOUSE; + + win->_flags |= RGFW_HOLD_MOUSE; RGFW_captureCursor(win, win->r); RGFW_window_moveMouse(win, RGFW_POINT(win->r.x + (win->r.w / 2), win->r.y + (win->r.h / 2))); } void RGFW_window_mouseUnhold(RGFW_window* win) { - if ((win->_winArgs & RGFW_HOLD_MOUSE)) { - win->_winArgs ^= RGFW_HOLD_MOUSE; + if ((win->_flags & RGFW_HOLD_MOUSE)) { + win->_flags ^= RGFW_HOLD_MOUSE; RGFW_releaseCursor(win); } @@ -1783,7 +1952,7 @@ u32 RGFW_window_checkFPS(RGFW_window* win, u32 fpsCap) { u64 deltaTime = RGFW_getTimeNS() - win->event.frameTime; u32 output_fps = 0; - u64 fps = round(1e+9 / deltaTime); + u64 fps = RGFW_ROUND(1e+9 / deltaTime); output_fps= fps; if (fpsCap && fps > fpsCap) { @@ -1797,132 +1966,179 @@ u32 RGFW_window_checkFPS(RGFW_window* win, u32 fpsCap) { } win->event.frameTime = RGFW_getTimeNS(); - - if (fpsCap == 0) + + if (fpsCap == 0) return (u32) output_fps; - + deltaTime = RGFW_getTimeNS() - win->event.frameTime2; - output_fps = round(1e+9 / deltaTime); + output_fps = RGFW_ROUND(1e+9 / deltaTime); win->event.frameTime2 = RGFW_getTimeNS(); return output_fps; } -u32 RGFW_isPressedJS(RGFW_window* win, u16 c, u8 button) { +u32 RGFW_isPressedGamepad(RGFW_window* win, u8 c, RGFW_gamepadCodes button) { RGFW_UNUSED(win); - return RGFW_jsPressed[c][button]; + return RGFW_gamepadPressed[c][button].current; +} +u32 RGFW_wasPressedGamepad(RGFW_window* win, u8 c, RGFW_gamepadCodes button) { + RGFW_UNUSED(win); + return RGFW_gamepadPressed[c][button].prev; +} +u32 RGFW_isReleasedGamepad(RGFW_window* win, u8 controller, RGFW_gamepadCodes button) { + RGFW_UNUSED(win); + return !RGFW_isPressedGamepad(win, controller, button) && RGFW_wasPressedGamepad(win, controller, button); +} +u32 RGFW_isHeldGamepad(RGFW_window* win, u8 controller, RGFW_gamepadCodes button) { + RGFW_UNUSED(win); + return RGFW_isPressedGamepad(win, controller, button) && RGFW_wasPressedGamepad(win, controller, button); +} + +RGFW_point RGFW_getGamepadAxis(RGFW_window* win, u16 controller, u16 whichAxis) { + RGFW_UNUSED(win); + return RGFW_gamepadAxes[controller][whichAxis]; +} +const char* RGFW_getGamepadName(RGFW_window* win, u16 controller) { + RGFW_UNUSED(win); + return (const char*)RGFW_gamepads_name[controller]; +} + +size_t RGFW_getGamepadCount(RGFW_window* win) { + RGFW_UNUSED(win); + return RGFW_gamepadCount; +} + +RGFW_gamepadType RGFW_getGamepadType(RGFW_window* win, u16 controller) { + RGFW_UNUSED(win); + return RGFW_gamepads_type[controller]; } #if defined(RGFW_X11) || defined(RGFW_WINDOWS) - void RGFW_window_showMouse(RGFW_window* win, i8 show) { - static u8 RGFW_blk[] = { 0, 0, 0, 0 }; - if (show == 0) - RGFW_window_setMouse(win, RGFW_blk, RGFW_AREA(1, 1), 4); - else - RGFW_window_setMouseDefault(win); - } +void RGFW_window_showMouse(RGFW_window* win, i8 show) { + if (show == 0) + RGFW_window_setMouse(win, RGFW_hiddenMouse); + else + RGFW_window_setMouseDefault(win); +} #endif -RGFWDEF void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock); -void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { - if (capital && !(win->event.lockState & RGFW_CAPSLOCK)) - win->event.lockState |= RGFW_CAPSLOCK; - else if (!capital && (win->event.lockState & RGFW_CAPSLOCK)) - win->event.lockState ^= RGFW_CAPSLOCK; - - if (numlock && !(win->event.lockState & RGFW_NUMLOCK)) - win->event.lockState |= RGFW_NUMLOCK; - else if (!numlock && (win->event.lockState & RGFW_NUMLOCK)) - win->event.lockState ^= RGFW_NUMLOCK; +RGFWDEF void RGFW_updateKeyMod(RGFW_window* win, RGFW_keymod mod, b8 value); +void RGFW_updateKeyMod(RGFW_window* win, RGFW_keymod mod, b8 value) { + if (value && !(win->event.keyMod & mod)) + win->event.keyMod |= mod; + else if (!value && ((win->event.keyMod & mod))) + win->event.keyMod ^= mod; +} + +RGFWDEF void RGFW_updateKeyModsPro(RGFW_window* win, b8 capital, b8 numlock, b8 control, b8 alt, b8 shift, b8 super); +void RGFW_updateKeyModsPro(RGFW_window* win, b8 capital, b8 numlock, b8 control, b8 alt, b8 shift, b8 super) { + RGFW_updateKeyMod(win, RGFW_modCapsLock, capital); + RGFW_updateKeyMod(win, RGFW_modNumLock, numlock); + RGFW_updateKeyMod(win, RGFW_modControl, control); + RGFW_updateKeyMod(win, RGFW_modAlt, alt); + RGFW_updateKeyMod(win, RGFW_modShift, shift); + RGFW_updateKeyMod(win, RGFW_modSuper, super); +} + +RGFWDEF void RGFW_updateKeyMods(RGFW_window* win, b8 capital, b8 numlock); +void RGFW_updateKeyMods(RGFW_window* win, b8 capital, b8 numlock) { + RGFW_updateKeyModsPro(win, capital, numlock, + RGFW_isPressed(win, RGFW_controlL) || RGFW_isPressed(win, RGFW_controlR), + RGFW_isPressed(win, RGFW_altL) || RGFW_isPressed(win, RGFW_altR), + RGFW_isPressed(win, RGFW_shiftL) || RGFW_isPressed(win, RGFW_shiftR), + RGFW_isPressed(win, RGFW_superL) || RGFW_isPressed(win, RGFW_superR)); } #if defined(RGFW_X11) || defined(RGFW_MACOS) || defined(RGFW_WEBASM) || defined(RGFW_WAYLAND) - struct timespec; +#include +struct timespec; - int nanosleep(const struct timespec* duration, struct timespec* rem); - int clock_gettime(clockid_t clk_id, struct timespec* tp); - int setenv(const char *name, const char *value, int overwrite); +#ifndef RGFW_NO_UNIX_CLOCK +int nanosleep(const struct timespec* duration, struct timespec* rem); +int clock_gettime(clockid_t clk_id, struct timespec* tp); +#endif - void RGFW_window_setDND(RGFW_window* win, b8 allow) { - if (allow && !(win->_winArgs & RGFW_ALLOW_DND)) - win->_winArgs |= RGFW_ALLOW_DND; +int setenv(const char *name, const char *value, int overwrite); - else if (!allow && (win->_winArgs & RGFW_ALLOW_DND)) - win->_winArgs ^= RGFW_ALLOW_DND; - } +void RGFW_window_setDND(RGFW_window* win, b8 allow) { + if (allow && !(win->_flags & RGFW_windowAllowDND)) + win->_flags |= RGFW_windowAllowDND; + + else if (!allow && (win->_flags & RGFW_windowAllowDND)) + win->_flags ^= RGFW_windowAllowDND; +} #endif /* graphics API specific code (end of generic code) - starts here + starts here */ -/* +/* OpenGL defines start here (Normal, EGL, OSMesa) */ -#if defined(RGFW_OPENGL) || defined(RGFW_EGL) || defined(RGFW_OSMESA) - #ifdef RGFW_WINDOWS - #define WIN32_LEAN_AND_MEAN - #define OEMRESOURCE - #include - #endif +#if defined(RGFW_OPENGL) || defined(RGFW_EGL) - #if !defined(__APPLE__) && !defined(RGFW_NO_GL_HEADER) - #include - #elif defined(__APPLE__) - #ifndef GL_SILENCE_DEPRECATION - #define GL_SILENCE_DEPRECATION - #endif - #include - #include +#ifdef RGFW_WINDOWS + #define WIN32_LEAN_AND_MEAN + #define OEMRESOURCE + #include +#endif + +#if !defined(__APPLE__) && !defined(RGFW_NO_GL_HEADER) + #include +#elif defined(__APPLE__) + #ifndef GL_SILENCE_DEPRECATION + #define GL_SILENCE_DEPRECATION #endif + #include + #include +#endif /* EGL, normal OpenGL only */ -#if !defined(RGFW_OSMESA) - i32 RGFW_majorVersion = 0, RGFW_minorVersion = 0; - b8 RGFW_profile = RGFW_GL_CORE; - - #ifndef RGFW_EGL - i32 RGFW_STENCIL = 8, RGFW_SAMPLES = 4, RGFW_STEREO = 0, RGFW_AUX_BUFFERS = 0, RGFW_DOUBLE_BUFFER = 1; - #else - i32 RGFW_STENCIL = 0, RGFW_SAMPLES = 0, RGFW_STEREO = 0, RGFW_AUX_BUFFERS = 0, RGFW_DOUBLE_BUFFER = 1; - #endif +i32 RGFW_majorVersion = 0, RGFW_minorVersion = 0; +b8 RGFW_profile = RGFW_glCore; +#ifndef RGFW_EGL +i32 RGFW_STENCIL = 8, RGFW_SAMPLES = 4, RGFW_STEREO = 0, RGFW_AUX_BUFFERS = 0, RGFW_DOUBLE_BUFFER = 1; +#else +i32 RGFW_STENCIL = 0, RGFW_SAMPLES = 0, RGFW_STEREO = 0, RGFW_AUX_BUFFERS = 0, RGFW_DOUBLE_BUFFER = 1; +#endif - void RGFW_setGLStencil(i32 stencil) { RGFW_STENCIL = stencil; } - void RGFW_setGLSamples(i32 samples) { RGFW_SAMPLES = samples; } - void RGFW_setGLStereo(i32 stereo) { RGFW_STEREO = stereo; } - void RGFW_setGLAuxBuffers(i32 auxBuffers) { RGFW_AUX_BUFFERS = auxBuffers; } - void RGFW_setDoubleBuffer(b8 useDoubleBuffer) { RGFW_DOUBLE_BUFFER = useDoubleBuffer; } +void RGFW_setGLStencil(i32 stencil) { RGFW_STENCIL = stencil; } +void RGFW_setGLSamples(i32 samples) { RGFW_SAMPLES = samples; } +void RGFW_setGLStereo(i32 stereo) { RGFW_STEREO = stereo; } +void RGFW_setGLAuxBuffers(i32 auxBuffers) { RGFW_AUX_BUFFERS = auxBuffers; } +void RGFW_setDoubleBuffer(b8 useDoubleBuffer) { RGFW_DOUBLE_BUFFER = useDoubleBuffer; } - void RGFW_setGLVersion(b8 profile, i32 major, i32 minor) { - RGFW_profile = profile; - RGFW_majorVersion = major; - RGFW_minorVersion = minor; - } +void RGFW_setGLVersion(b8 profile, i32 major, i32 minor) { + RGFW_profile = profile; + RGFW_majorVersion = major; + RGFW_minorVersion = minor; +} /* OPENGL normal only (no EGL / OSMesa) */ -#ifndef RGFW_EGL +#if !defined(RGFW_EGL) && !defined(RGFW_CUSTOM_BACKEND) -#define RGFW_GL_RENDER_TYPE RGFW_OS_BASED_VALUE(GLX_X_VISUAL_TYPE, 0x2003, 73, 0, 0) - #define RGFW_GL_ALPHA_SIZE RGFW_OS_BASED_VALUE(GLX_ALPHA_SIZE, 0x201b, 11, 0, 0) - #define RGFW_GL_DEPTH_SIZE RGFW_OS_BASED_VALUE(GLX_DEPTH_SIZE, 0x2022, 12, 0, 0) - #define RGFW_GL_DOUBLEBUFFER RGFW_OS_BASED_VALUE(GLX_DOUBLEBUFFER, 0x2011, 5, 0, 0) - #define RGFW_GL_STENCIL_SIZE RGFW_OS_BASED_VALUE(GLX_STENCIL_SIZE, 0x2023, 13, 0, 0) - #define RGFW_GL_SAMPLES RGFW_OS_BASED_VALUE(GLX_SAMPLES, 0x2042, 55, 0, 0) - #define RGFW_GL_STEREO RGFW_OS_BASED_VALUE(GLX_STEREO, 0x2012, 6, 0, 0) - #define RGFW_GL_AUX_BUFFERS RGFW_OS_BASED_VALUE(GLX_AUX_BUFFERS, 0x2024, 7, 0, 0) +#define RGFW_GL_RENDER_TYPE RGFW_OS_BASED_VALUE(GLX_X_VISUAL_TYPE, 0x2003, 73, 0) + #define RGFW_GL_ALPHA_SIZE RGFW_OS_BASED_VALUE(GLX_ALPHA_SIZE, 0x201b, 11, 0) + #define RGFW_GL_DEPTH_SIZE RGFW_OS_BASED_VALUE(GLX_DEPTH_SIZE, 0x2022, 12, 0) + #define RGFW_GL_DOUBLEBUFFER RGFW_OS_BASED_VALUE(GLX_DOUBLEBUFFER, 0x2011, 5, 0) + #define RGFW_GL_STENCIL_SIZE RGFW_OS_BASED_VALUE(GLX_STENCIL_SIZE, 0x2023, 13, 0) + #define RGFW_GL_SAMPLES RGFW_OS_BASED_VALUE(GLX_SAMPLES, 0x2042, 55, 0) + #define RGFW_GL_STEREO RGFW_OS_BASED_VALUE(GLX_STEREO, 0x2012, 6, 0) + #define RGFW_GL_AUX_BUFFERS RGFW_OS_BASED_VALUE(GLX_AUX_BUFFERS, 0x2024, 7, 0) #if defined(RGFW_X11) || defined(RGFW_WINDOWS) - #define RGFW_GL_DRAW RGFW_OS_BASED_VALUE(GLX_X_RENDERABLE, 0x2001, 0, 0, 0) - #define RGFW_GL_DRAW_TYPE RGFW_OS_BASED_VALUE(GLX_RENDER_TYPE, 0x2013, 0, 0, 0) - #define RGFW_GL_FULL_FORMAT RGFW_OS_BASED_VALUE(GLX_TRUE_COLOR, 0x2027, 0, 0, 0) - #define RGFW_GL_RED_SIZE RGFW_OS_BASED_VALUE(GLX_RED_SIZE, 0x2015, 0, 0, 0) - #define RGFW_GL_GREEN_SIZE RGFW_OS_BASED_VALUE(GLX_GREEN_SIZE, 0x2017, 0, 0, 0) - #define RGFW_GL_BLUE_SIZE RGFW_OS_BASED_VALUE(GLX_BLUE_SIZE, 0x2019, 0, 0, 0) - #define RGFW_GL_USE_RGBA RGFW_OS_BASED_VALUE(GLX_RGBA_BIT, 0x202B, 0, 0, 0) + #define RGFW_GL_DRAW RGFW_OS_BASED_VALUE(GLX_X_RENDERABLE, 0x2001, 0, 0) + #define RGFW_GL_DRAW_TYPE RGFW_OS_BASED_VALUE(GLX_RENDER_TYPE, 0x2013, 0, 0) + #define RGFW_GL_FULL_FORMAT RGFW_OS_BASED_VALUE(GLX_TRUE_COLOR, 0x2027, 0, 0) + #define RGFW_GL_RED_SIZE RGFW_OS_BASED_VALUE(GLX_RED_SIZE, 0x2015, 0, 0) + #define RGFW_GL_GREEN_SIZE RGFW_OS_BASED_VALUE(GLX_GREEN_SIZE, 0x2017, 0, 0) + #define RGFW_GL_BLUE_SIZE RGFW_OS_BASED_VALUE(GLX_BLUE_SIZE, 0x2019, 0, 0) + #define RGFW_GL_USE_RGBA RGFW_OS_BASED_VALUE(GLX_RGBA_BIT, 0x202B, 0, 0) #endif #ifdef RGFW_WINDOWS @@ -1941,47 +2157,47 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { #define WGL_TRANSPARENT_ARB 0x200A #endif - -/* The window'ing api needs to know how to render the data we (or opengl) give it - MacOS and Windows do this using a structure called a "pixel format" + +/* The window'ing api needs to know how to render the data we (or opengl) give it + MacOS and Windows do this using a structure called a "pixel format" X11 calls it a "Visual" This function returns the attributes for the format we want */ - static u32* RGFW_initFormatAttribs(u32 useSoftware) { - RGFW_UNUSED(useSoftware); - static u32 attribs[] = { - #if defined(RGFW_X11) || defined(RGFW_WINDOWS) - RGFW_GL_RENDER_TYPE, - RGFW_GL_FULL_FORMAT, - #endif - RGFW_GL_ALPHA_SIZE , 8, - RGFW_GL_DEPTH_SIZE , 24, - #if defined(RGFW_X11) || defined(RGFW_WINDOWS) - RGFW_GL_DRAW, 1, - RGFW_GL_RED_SIZE , 8, - RGFW_GL_GREEN_SIZE , 8, - RGFW_GL_BLUE_SIZE , 8, - RGFW_GL_DRAW_TYPE , RGFW_GL_USE_RGBA, - #endif +u32* RGFW_initFormatAttribs(u32 useSoftware) { + RGFW_UNUSED(useSoftware); + static u32 attribs[] = { + #if defined(RGFW_X11) || defined(RGFW_WINDOWS) + RGFW_GL_RENDER_TYPE, + RGFW_GL_FULL_FORMAT, + #endif + RGFW_GL_ALPHA_SIZE , 8, + RGFW_GL_DEPTH_SIZE , 24, + #if defined(RGFW_X11) || defined(RGFW_WINDOWS) + RGFW_GL_DRAW, 1, + RGFW_GL_RED_SIZE , 8, + RGFW_GL_GREEN_SIZE , 8, + RGFW_GL_BLUE_SIZE , 8, + RGFW_GL_DRAW_TYPE , RGFW_GL_USE_RGBA, + #endif - #ifdef RGFW_X11 - GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT, - #endif + #ifdef RGFW_X11 + GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT, + #endif - #ifdef RGFW_MACOS - 72, - 8, 24, - #endif + #ifdef RGFW_MACOS + 72, + 8, 24, + #endif - #ifdef RGFW_WINDOWS - WGL_SUPPORT_OPENGL_ARB, 1, - WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, - WGL_COLOR_BITS_ARB, 32, - #endif + #ifdef RGFW_WINDOWS + WGL_SUPPORT_OPENGL_ARB, 1, + WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, + WGL_COLOR_BITS_ARB, 32, + #endif - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; - size_t index = (sizeof(attribs) / sizeof(attribs[0])) - 13; + size_t index = (sizeof(attribs) / sizeof(attribs[0])) - 13; #define RGFW_GL_ADD_ATTRIB(attrib, attVal) \ if (attVal) { \ @@ -1989,27 +2205,27 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { attribs[index + 1] = attVal;\ index += 2;\ } - + RGFW_GL_ADD_ATTRIB(RGFW_GL_DOUBLEBUFFER, 1); - + RGFW_GL_ADD_ATTRIB(RGFW_GL_STENCIL_SIZE, RGFW_STENCIL); RGFW_GL_ADD_ATTRIB(RGFW_GL_STEREO, RGFW_STEREO); RGFW_GL_ADD_ATTRIB(RGFW_GL_AUX_BUFFERS, RGFW_AUX_BUFFERS); -#ifndef RGFW_X11 + #ifndef RGFW_X11 RGFW_GL_ADD_ATTRIB(RGFW_GL_SAMPLES, RGFW_SAMPLES); -#endif + #endif -#ifdef RGFW_MACOS + #ifdef RGFW_MACOS if (useSoftware) { RGFW_GL_ADD_ATTRIB(70, kCGLRendererGenericFloatID); } else { attribs[index] = RGFW_GL_RENDER_TYPE; index += 1; } -#endif + #endif -#ifdef RGFW_MACOS + #ifdef RGFW_MACOS /* macOS has the surface attribs and the opengl attribs connected for some reason maybe this is to give macOS more control to limit openGL/the opengl version? */ @@ -2019,12 +2235,12 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { if (RGFW_majorVersion >= 4 || RGFW_majorVersion >= 3) { attribs[index + 1] = (u32) ((RGFW_majorVersion >= 4) ? 0x4100 : 0x3200); } -#endif + #endif - RGFW_GL_ADD_ATTRIB(0, 0); + RGFW_GL_ADD_ATTRIB(0, 0); - return attribs; - } + return attribs; +} /* EGL only (no OSMesa nor normal OPENGL) */ #elif defined(RGFW_EGL) @@ -2036,7 +2252,7 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { PFNEGLINITIALIZEPROC eglInitializeSource; PFNEGLGETCONFIGSPROC eglGetConfigsSource; - PFNEGLCHOOSECONFIGPROC eglChooseConfigSource; + PFNEGLCHOOSECONFIgamepadROC eglChooseConfigSource; PFNEGLCREATEWINDOWSURFACEPROC eglCreateWindowSurfaceSource; PFNEGLCREATECONTEXTPROC eglCreateContextSource; PFNEGLMAKECURRENTPROC eglMakeCurrentSource; @@ -2048,19 +2264,19 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { PFNEGLTERMINATEPROC eglTerminateSource; PFNEGLDESTROYSURFACEPROC eglDestroySurfaceSource; -#define eglInitialize eglInitializeSource -#define eglGetConfigs eglGetConfigsSource -#define eglChooseConfig eglChooseConfigSource -#define eglCreateWindowSurface eglCreateWindowSurfaceSource -#define eglCreateContext eglCreateContextSource -#define eglMakeCurrent eglMakeCurrentSource -#define eglGetDisplay eglGetDisplaySource -#define eglSwapBuffers eglSwapBuffersSource -#define eglSwapInterval eglSwapIntervalSource -#define eglBindAPI eglBindAPISource -#define eglDestroyContext eglDestroyContextSource -#define eglTerminate eglTerminateSource -#define eglDestroySurface eglDestroySurfaceSource; + #define eglInitialize eglInitializeSource + #define eglGetConfigs eglGetConfigsSource + #define eglChooseConfig eglChooseConfigSource + #define eglCreateWindowSurface eglCreateWindowSurfaceSource + #define eglCreateContext eglCreateContextSource + #define eglMakeCurrent eglMakeCurrentSource + #define eglGetDisplay eglGetDisplaySource + #define eglSwapBuffers eglSwapBuffersSource + #define eglSwapInterval eglSwapIntervalSource + #define eglBindAPI eglBindAPISource + #define eglDestroyContext eglDestroyContextSource + #define eglTerminate eglTerminateSource + #define eglDestroySurface eglDestroySurfaceSource; #endif @@ -2077,180 +2293,169 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { #endif - void RGFW_createOpenGLContext(RGFW_window* win) { +void RGFW_createOpenGLContext(RGFW_window* win) { #if defined(RGFW_LINK_EGL) - eglInitializeSource = (PFNEGLINITIALIZEPROC) eglGetProcAddress("eglInitialize"); - eglGetConfigsSource = (PFNEGLGETCONFIGSPROC) eglGetProcAddress("eglGetConfigs"); - eglChooseConfigSource = (PFNEGLCHOOSECONFIGPROC) eglGetProcAddress("eglChooseConfig"); - eglCreateWindowSurfaceSource = (PFNEGLCREATEWINDOWSURFACEPROC) eglGetProcAddress("eglCreateWindowSurface"); - eglCreateContextSource = (PFNEGLCREATECONTEXTPROC) eglGetProcAddress("eglCreateContext"); - eglMakeCurrentSource = (PFNEGLMAKECURRENTPROC) eglGetProcAddress("eglMakeCurrent"); - eglGetDisplaySource = (PFNEGLGETDISPLAYPROC) eglGetProcAddress("eglGetDisplay"); - eglSwapBuffersSource = (PFNEGLSWAPBUFFERSPROC) eglGetProcAddress("eglSwapBuffers"); - eglSwapIntervalSource = (PFNEGLSWAPINTERVALPROC) eglGetProcAddress("eglSwapInterval"); - eglBindAPISource = (PFNEGLBINDAPIPROC) eglGetProcAddress("eglBindAPI"); - eglDestroyContextSource = (PFNEGLDESTROYCONTEXTPROC) eglGetProcAddress("eglDestroyContext"); - eglTerminateSource = (PFNEGLTERMINATEPROC) eglGetProcAddress("eglTerminate"); - eglDestroySurfaceSource = (PFNEGLDESTROYSURFACEPROC) eglGetProcAddress("eglDestroySurface"); + eglInitializeSource = (PFNEGLINITIALIZEPROC) eglGetProcAddress("eglInitialize"); + eglGetConfigsSource = (PFNEGLGETCONFIGSPROC) eglGetProcAddress("eglGetConfigs"); + eglChooseConfigSource = (PFNEGLCHOOSECONFIgamepadROC) eglGetProcAddress("eglChooseConfig"); + eglCreateWindowSurfaceSource = (PFNEGLCREATEWINDOWSURFACEPROC) eglGetProcAddress("eglCreateWindowSurface"); + eglCreateContextSource = (PFNEGLCREATECONTEXTPROC) eglGetProcAddress("eglCreateContext"); + eglMakeCurrentSource = (PFNEGLMAKECURRENTPROC) eglGetProcAddress("eglMakeCurrent"); + eglGetDisplaySource = (PFNEGLGETDISPLAYPROC) eglGetProcAddress("eglGetDisplay"); + eglSwapBuffersSource = (PFNEGLSWAPBUFFERSPROC) eglGetProcAddress("eglSwapBuffers"); + eglSwapIntervalSource = (PFNEGLSWAPINTERVALPROC) eglGetProcAddress("eglSwapInterval"); + eglBindAPISource = (PFNEGLBINDAPIPROC) eglGetProcAddress("eglBindAPI"); + eglDestroyContextSource = (PFNEGLDESTROYCONTEXTPROC) eglGetProcAddress("eglDestroyContext"); + eglTerminateSource = (PFNEGLTERMINATEPROC) eglGetProcAddress("eglTerminate"); + eglDestroySurfaceSource = (PFNEGLDESTROYSURFACEPROC) eglGetProcAddress("eglDestroySurface"); #endif /* RGFW_LINK_EGL */ - #ifdef RGFW_WINDOWS - win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType) win->src.hdc); - #elif defined(RGFW_MACOS) - win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType)0); - #else + #ifdef RGFW_WINDOWS + win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType) win->src.hdc); + #elif defined(RGFW_MACOS) + win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType)0); + #elif defined(RGFW_WAYLAND) + if (RGFW_useWaylandBool) + win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType) win->src.wl_display); + else win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType) win->src.display); - #endif - - EGLint major, minor; - - eglInitialize(win->src.EGL_display, &major, &minor); - - #ifndef EGL_OPENGL_ES1_BIT - #define EGL_OPENGL_ES1_BIT 0x1 - #endif - - EGLint egl_config[] = { - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_RENDERABLE_TYPE, - #ifdef RGFW_OPENGL_ES1 - EGL_OPENGL_ES1_BIT, - #elif defined(RGFW_OPENGL_ES3) - EGL_OPENGL_ES3_BIT, - #elif defined(RGFW_OPENGL_ES2) - EGL_OPENGL_ES2_BIT, - #else - EGL_OPENGL_BIT, - #endif - EGL_NONE, EGL_NONE - }; - - EGLConfig config; - EGLint numConfigs; - eglChooseConfig(win->src.EGL_display, egl_config, &config, 1, &numConfigs); - - #if defined(RGFW_MACOS) - void* layer = RGFW_cocoaGetLayer(); - - RGFW_window_cocoaSetLayer(win, layer); - - win->src.EGL_surface = eglCreateWindowSurface(win->src.EGL_display, config, (EGLNativeWindowType) layer, NULL); - #else - win->src.EGL_surface = eglCreateWindowSurface(win->src.EGL_display, config, (EGLNativeWindowType) win->src.window, NULL); - #endif - - EGLint attribs[] = { - EGL_CONTEXT_CLIENT_VERSION, - #ifdef RGFW_OPENGL_ES1 - 1, - #else - 2, - #endif - EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE - }; - - size_t index = 4; - RGFW_GL_ADD_ATTRIB(EGL_STENCIL_SIZE, RGFW_STENCIL); - RGFW_GL_ADD_ATTRIB(EGL_SAMPLES, RGFW_SAMPLES); - - if (RGFW_DOUBLE_BUFFER) - RGFW_GL_ADD_ATTRIB(EGL_RENDER_BUFFER, EGL_BACK_BUFFER); - - if (RGFW_majorVersion) { - attribs[1] = RGFW_majorVersion; - - RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_MAJOR_VERSION, RGFW_majorVersion); - RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_MINOR_VERSION, RGFW_minorVersion); - - if (RGFW_profile == RGFW_GL_CORE) { - RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT); - } - else { - RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT); - } - - } - - #if defined(RGFW_OPENGL_ES1) || defined(RGFW_OPENGL_ES2) || defined(RGFW_OPENGL_ES3) - eglBindAPI(EGL_OPENGL_ES_API); - #else - eglBindAPI(EGL_OPENGL_API); - #endif - - win->src.EGL_context = eglCreateContext(win->src.EGL_display, config, EGL_NO_CONTEXT, attribs); - - if (win->src.EGL_context == NULL) - fprintf(stderr, "failed to create an EGL opengl context\n"); - - eglMakeCurrent(win->src.EGL_display, win->src.EGL_surface, win->src.EGL_surface, win->src.EGL_context); - eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface); - } - - void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) { - eglMakeCurrent(win->src.EGL_display, win->src.EGL_surface, win->src.EGL_surface, win->src.EGL_context); - } - - #ifdef RGFW_APPLE - void* RGFWnsglFramework = NULL; - #elif defined(RGFW_WINDOWS) - static HMODULE wglinstance = NULL; + #else + win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType) win->src.display); #endif - void* RGFW_getProcAddress(const char* procname) { - #if defined(RGFW_WINDOWS) - void* proc = (void*) GetProcAddress(wglinstance, procname); + EGLint major, minor; - if (proc) - return proc; + eglInitialize(win->src.EGL_display, &major, &minor); + + #ifndef EGL_OPENGL_ES1_BIT + #define EGL_OPENGL_ES1_BIT 0x1 + #endif + + EGLint egl_config[] = { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RENDERABLE_TYPE, + #ifdef RGFW_OPENGL_ES1 + EGL_OPENGL_ES1_BIT, + #elif defined(RGFW_OPENGL_ES3) + EGL_OPENGL_ES3_BIT, + #elif defined(RGFW_OPENGL_ES2) + EGL_OPENGL_ES2_BIT, + #else + EGL_OPENGL_BIT, #endif + EGL_NONE, EGL_NONE + }; - return (void*) eglGetProcAddress(procname); - } + EGLConfig config; + EGLint numConfigs; + eglChooseConfig(win->src.EGL_display, egl_config, &config, 1, &numConfigs); - void RGFW_closeEGL(RGFW_window* win) { - eglDestroySurface(win->src.EGL_display, win->src.EGL_surface); - eglDestroyContext(win->src.EGL_display, win->src.EGL_context); + #if defined(RGFW_MACOS) + void* layer = RGFW_cocoaGetLayer(); - eglTerminate(win->src.EGL_display); - } - - void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { - assert(win != NULL); - - eglSwapInterval(win->src.EGL_display, swapInterval); + RGFW_window_cocoaSetLayer(win, layer); + + win->src.EGL_surface = eglCreateWindowSurface(win->src.EGL_display, config, (EGLNativeWindowType) layer, NULL); + #elif defined(RGFW_WINDOWS) + win->src.EGL_surface = eglCreateWindowSurface(win->src.EGL_display, config, (EGLNativeWindowType) win->src.hwnd, NULL); + #elif defined(RGFW_WAYLAND) + if (RGFW_useWaylandBool) + win->src.EGL_surface = eglCreateWindowSurface(win->src.EGL_display, config, (EGLNativeWindowType) win->src.eglWindow, NULL); + else + win->src.EGL_surface = eglCreateWindowSurface(win->src.EGL_display, config, (EGLNativeWindowType) win->src.window, NULL); + #else + win->src.EGL_surface = eglCreateWindowSurface(win->src.EGL_display, config, (EGLNativeWindowType) win->src.window, NULL); + #endif + + EGLint attribs[] = { + EGL_CONTEXT_CLIENT_VERSION, + #ifdef RGFW_OPENGL_ES1 + 1, + #else + 2, + #endif + EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE + }; + + size_t index = 4; + RGFW_GL_ADD_ATTRIB(EGL_STENCIL_SIZE, RGFW_STENCIL); + RGFW_GL_ADD_ATTRIB(EGL_SAMPLES, RGFW_SAMPLES); + + if (RGFW_DOUBLE_BUFFER) + RGFW_GL_ADD_ATTRIB(EGL_RENDER_BUFFER, EGL_BACK_BUFFER); + + if (RGFW_majorVersion) { + attribs[1] = RGFW_majorVersion; + + RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_MAJOR_VERSION, RGFW_majorVersion); + RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_MINOR_VERSION, RGFW_minorVersion); + + if (RGFW_profile == RGFW_glCore) { + RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT); + } + else { + RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT); + } } + + #if defined(RGFW_OPENGL_ES1) || defined(RGFW_OPENGL_ES2) || defined(RGFW_OPENGL_ES3) + eglBindAPI(EGL_OPENGL_ES_API); + #else + eglBindAPI(EGL_OPENGL_API); + #endif + + win->src.EGL_context = eglCreateContext(win->src.EGL_display, config, EGL_NO_CONTEXT, attribs); + + if (win->src.EGL_context == NULL) { + #ifdef RGFW_DEBUG + fprintf(stderr, "failed to create an EGL opengl context\n"); + #endif + } + eglMakeCurrent(win->src.EGL_display, win->src.EGL_surface, win->src.EGL_surface, win->src.EGL_context); + eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface); +} + +void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) { + eglMakeCurrent(win->src.EGL_display, win->src.EGL_surface, win->src.EGL_surface, win->src.EGL_context); +} + +#ifdef RGFW_APPLE +void* RGFWnsglFramework = NULL; +#elif defined(RGFW_WINDOWS) +static HMODULE RGFW_wgl_dll = NULL; +#endif + +void* RGFW_getProcAddress(const char* procname) { + #if defined(RGFW_WINDOWS) + void* proc = (void*) GetProcAddress(RGFW_wgl_dll, procname); + + if (proc) + return proc; + #endif + + return (void*) eglGetProcAddress(procname); +} + +void RGFW_closeEGL(RGFW_window* win) { + eglDestroySurface(win->src.EGL_display, win->src.EGL_surface); + eglDestroyContext(win->src.EGL_display, win->src.EGL_context); + + eglTerminate(win->src.EGL_display); +} + +void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { + RGFW_ASSERT(win != NULL); + + eglSwapInterval(win->src.EGL_display, swapInterval); + +} + #endif /* RGFW_EGL */ -/* +/* end of RGFW_EGL defines */ - -/* OPENGL Normal / EGL defines only (no OS MESA) Ends here */ - -#elif defined(RGFW_OSMESA) /* OSmesa only */ -RGFWDEF void RGFW_OSMesa_reorganize(void); - -/* reorganize buffer for osmesa */ -void RGFW_OSMesa_reorganize(void) { - u8* row = (u8*) RGFW_MALLOC(win->r.w * 3); - - i32 half_height = win->r.h / 2; - i32 stride = win->r.w * 3; - - i32 y; - for (y = 0; y < half_height; ++y) { - i32 top_offset = y * stride; - i32 bottom_offset = (win->r.h - y - 1) * stride; - memcpy(row, win->buffer + top_offset, stride); - memcpy(win->buffer + top_offset, win->buffer + bottom_offset, stride); - memcpy(win->buffer + bottom_offset, row, stride); - } - - RGFW_FREE(row); -} -#endif /* RGFW_OSMesa */ - #endif /* RGFW_GL (OpenGL, EGL, OSMesa )*/ /* @@ -2258,1853 +2463,167 @@ This is where OS specific stuff starts */ -#if defined(RGFW_WAYLAND) || defined(RGFW_X11) +#if (defined(RGFW_WAYLAND) || defined(RGFW_X11)) && !defined(RGFW_NO_LINUX) int RGFW_eventWait_forceStop[] = {0, 0, 0}; /* for wait events */ - #ifdef __linux__ + #if defined(__linux__) #include #include #include - - RGFW_Event* RGFW_linux_updateJoystick(RGFW_window* win) { - static int xAxis = 0, yAxis = 0; + #include + + u32 RGFW_linux_updateGamepad(RGFW_window* win) { + /* check for new gamepads */ + static const char* str[] = {"/dev/input/js0", "/dev/input/js1", "/dev/input/js2", "/dev/input/js3", "/dev/input/js4", "/dev/input/js5"}; + static u8 RGFW_rawGamepads[6]; + + for (size_t i = 0; i < 6; i++) { + size_t index = RGFW_gamepadCount; + if (RGFW_rawGamepads[i]) { + struct input_id device_info; + if (ioctl(RGFW_rawGamepads[i], EVIOCGID, &device_info) == -1) { + if (errno == ENODEV) { + RGFW_rawGamepads[i] = 0; + } + } + continue; + } + + i32 js = open(str[i], O_RDONLY); + + if (js <= 0) + break; + + if (RGFW_gamepadCount >= 4) { + close(js); + break; + } + + RGFW_rawGamepads[i] = 1; + + int axes, buttons; + if (ioctl(js, JSIOCGAXES, &axes) < 0 || ioctl(js, JSIOCGBUTTONS, &buttons) < 0) { + close(js); + continue; + } + + if (buttons <= 5 || buttons >= 30) { + close(js); + continue; + } + + RGFW_gamepadCount++; + + RGFW_gamepads[index] = js; + + ioctl(js, JSIOCGNAME(sizeof(RGFW_gamepads_name[index])), RGFW_gamepads_name[index]); + RGFW_gamepads_name[index][sizeof(RGFW_gamepads_name[index]) - 1] = 0; + + u8 j; + for (j = 0; j < 16; j++) + RGFW_gamepadPressed[index][j] = (RGFW_keyState){0, 0}; + + win->event.type = RGFW_gamepadConnected; + + RGFW_gamepads_type[index] = RGFW_gamepadUnknown; + if (strstr(RGFW_gamepads_name[index], "Microsoft") || strstr(RGFW_gamepads_name[index], "X-Box")) + RGFW_gamepads_type[index] = RGFW_gamepadMicrosoft; + else if (strstr(RGFW_gamepads_name[index], "PlayStation") || strstr(RGFW_gamepads_name[index], "PS3") || strstr(RGFW_gamepads_name[index], "PS4") || strstr(RGFW_gamepads_name[index], "PS5")) + RGFW_gamepads_type[index] = RGFW_gamepadSony; + else if (strstr(RGFW_gamepads_name[index], "Nintendo")) + RGFW_gamepads_type[index] = RGFW_gamepadNintendo; + else if (strstr(RGFW_gamepads_name[index], "Logitech")) + RGFW_gamepads_type[index] = RGFW_gamepadLogitech; + + win->event.gamepad = index; + RGFW_gamepadCallback(win, index, 1); + return 1; + } + + /* check gamepad events */ u8 i; - for (i = 0; i < RGFW_joystickCount; i++) { + + for (i = 0; i < RGFW_gamepadCount; i++) { struct js_event e; - - - if (RGFW_joysticks[i] == 0) + if (RGFW_gamepads[i] == 0) continue; - i32 flags = fcntl(RGFW_joysticks[i], F_GETFL, 0); - fcntl(RGFW_joysticks[i], F_SETFL, flags | O_NONBLOCK); + i32 flags = fcntl(RGFW_gamepads[i], F_GETFL, 0); + fcntl(RGFW_gamepads[i], F_SETFL, flags | O_NONBLOCK); ssize_t bytes; - while ((bytes = read(RGFW_joysticks[i], &e, sizeof(e))) > 0) { + while ((bytes = read(RGFW_gamepads[i], &e, sizeof(e))) > 0) { switch (e.type) { - case JS_EVENT_BUTTON: - win->event.type = e.value ? RGFW_jsButtonPressed : RGFW_jsButtonReleased; - win->event.button = e.number; - RGFW_jsPressed[i][e.number] = e.value; - RGFW_jsButtonCallback(win, i, e.number, e.value); - return &win->event; - case JS_EVENT_AXIS: - ioctl(RGFW_joysticks[i], JSIOCGAXES, &win->event.axisesCount); + case JS_EVENT_BUTTON: { + size_t typeIndex = 0; + if (RGFW_gamepads_type[i] == RGFW_gamepadMicrosoft) typeIndex = 1; + else if (RGFW_gamepads_type[i] == RGFW_gamepadLogitech) typeIndex = 2; - if ((e.number == 0 || e.number % 2) && e.number != 1) - xAxis = e.value; - else - yAxis = e.value; + win->event.type = e.value ? RGFW_gamepadButtonPressed : RGFW_gamepadButtonReleased; + u8 RGFW_linux2RGFW[3][RGFW_gamepadR3 + 8] = {{ /* ps */ + RGFW_gamepadA, RGFW_gamepadB, RGFW_gamepadY, RGFW_gamepadX, RGFW_gamepadL1, RGFW_gamepadR1, RGFW_gamepadL2, RGFW_gamepadR2, + RGFW_gamepadSelect, RGFW_gamepadStart, RGFW_gamepadHome, RGFW_gamepadL3, RGFW_gamepadR3, RGFW_gamepadUp, RGFW_gamepadDown, RGFW_gamepadLeft, RGFW_gamepadRight, + },{ /* xbox */ + RGFW_gamepadA, RGFW_gamepadB, RGFW_gamepadX, RGFW_gamepadY, RGFW_gamepadL1, RGFW_gamepadR1, RGFW_gamepadSelect, RGFW_gamepadStart, + RGFW_gamepadHome, RGFW_gamepadL3, RGFW_gamepadR3, 255, 255, RGFW_gamepadUp, RGFW_gamepadDown, RGFW_gamepadLeft, RGFW_gamepadRight + },{ /* Logitech */ + RGFW_gamepadA, RGFW_gamepadB, RGFW_gamepadX, RGFW_gamepadY, RGFW_gamepadL1, RGFW_gamepadR1, RGFW_gamepadL2, RGFW_gamepadR2, + RGFW_gamepadSelect, RGFW_gamepadStart, RGFW_gamepadHome, RGFW_gamepadL3, RGFW_gamepadR3, RGFW_gamepadUp, RGFW_gamepadDown, RGFW_gamepadLeft, RGFW_gamepadRight + } + }; - win->event.axis[e.number / 2].x = xAxis; - win->event.axis[e.number / 2].y = yAxis; - win->event.type = RGFW_jsAxisMove; - win->event.joystick = i; - RGFW_jsAxisCallback(win, i, win->event.axis, win->event.axisesCount); - return &win->event; + win->event.button = RGFW_linux2RGFW[typeIndex][e.number]; + win->event.gamepad = i; + if (win->event.button == 255) break; + RGFW_gamepadPressed[i][win->event.button].prev = RGFW_gamepadPressed[i][win->event.button].current; + RGFW_gamepadPressed[i][win->event.button].current = e.value; + RGFW_gamepadButtonCallback(win, i, win->event.button, e.value); + + return 1; + } + case JS_EVENT_AXIS: { + size_t axis = e.number / 2; + if (axis == 2) axis = 1; + + ioctl(RGFW_gamepads[i], JSIOCGAXES, &win->event.axisesCount); + win->event.axisesCount = 2; + + if (axis < 3) { + if (e.number == 0 || e.number == 3) + RGFW_gamepadAxes[i][axis].x = (e.value / 32767.0f) * 100; + else if (e.number == 1 || e.number == 4) { + RGFW_gamepadAxes[i][axis].y = (e.value / 32767.0f) * 100; + } + } + + win->event.axis[axis] = RGFW_gamepadAxes[i][axis]; + win->event.type = RGFW_gamepadAxisMove; + win->event.gamepad = i; + win->event.whichAxis = axis; + RGFW_gamepadAxisCallback(win, i, win->event.axis, win->event.axisesCount, win->event.whichAxis); + return 1; + } default: break; } } - } - - return NULL; - } - - #endif -#endif - -/* - - -Start of Linux / Unix defines - - -*/ - -#ifdef RGFW_X11 -#ifndef RGFW_NO_X11_CURSOR -#include -#endif -#include - -#ifndef RGFW_NO_DPI -#include -#include -#endif - -#include -#include -#include -#include - -#include /* for converting keycode to string */ -#include /* for hiding */ -#include -#include -#include - -#include /* for data limits (mainly used in drag and drop functions) */ -#include - - -#ifdef __linux__ -#include -#endif - - u8 RGFW_mouseIconSrc[] = { XC_arrow, XC_left_ptr, XC_xterm, XC_crosshair, XC_hand2, XC_sb_h_double_arrow, XC_sb_v_double_arrow, XC_bottom_left_corner, XC_bottom_right_corner, XC_fleur, XC_X_cursor}; - /*atoms needed for drag and drop*/ - Atom XdndAware, XdndTypeList, XdndSelection, XdndEnter, XdndPosition, XdndStatus, XdndLeave, XdndDrop, XdndFinished, XdndActionCopy, XtextPlain, XtextUriList; - - Atom wm_delete_window = 0; - -#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD) - typedef XcursorImage* (*PFN_XcursorImageCreate)(int, int); - typedef void (*PFN_XcursorImageDestroy)(XcursorImage*); - typedef Cursor(*PFN_XcursorImageLoadCursor)(Display*, const XcursorImage*); -#endif -#ifdef RGFW_OPENGL - typedef GLXContext(*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*); -#endif - -#if !defined(RGFW_NO_X11_XI_PRELOAD) - typedef int (* PFN_XISelectEvents)(Display*,Window,XIEventMask*,int); - PFN_XISelectEvents XISelectEventsSrc = NULL; - #define XISelectEvents XISelectEventsSrc - - void* X11Xihandle = NULL; -#endif - -#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD) - PFN_XcursorImageLoadCursor XcursorImageLoadCursorSrc = NULL; - PFN_XcursorImageCreate XcursorImageCreateSrc = NULL; - PFN_XcursorImageDestroy XcursorImageDestroySrc = NULL; - -#define XcursorImageLoadCursor XcursorImageLoadCursorSrc -#define XcursorImageCreate XcursorImageCreateSrc -#define XcursorImageDestroy XcursorImageDestroySrc - - void* X11Cursorhandle = NULL; -#endif - - u32 RGFW_windowsOpen = 0; - -#ifdef RGFW_OPENGL - void* RGFW_getProcAddress(const char* procname) { return (void*) glXGetProcAddress((GLubyte*) procname); } -#endif - - RGFWDEF void RGFW_init_buffer(RGFW_window* win, XVisualInfo* vi); - void RGFW_init_buffer(RGFW_window* win, XVisualInfo* vi) { -#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) - if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0) - RGFW_bufferSize = RGFW_getScreenSize(); - - win->buffer = (u8*)RGFW_MALLOC(RGFW_bufferSize.w * RGFW_bufferSize.h * 4); - - #ifdef RGFW_OSMESA - win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL); - OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h); - #endif - - win->src.bitmap = XCreateImage( - win->src.display, XDefaultVisual(win->src.display, vi->screen), - vi->depth, - ZPixmap, 0, NULL, RGFW_bufferSize.w, RGFW_bufferSize.h, - 32, 0 - ); - - win->src.gc = XCreateGC(win->src.display, win->src.window, 0, NULL); - - #else - RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ - RGFW_UNUSED(vi) - #endif - } - - - - void RGFW_window_setBorder(RGFW_window* win, u8 border) { - static Atom _MOTIF_WM_HINTS = 0; - if (_MOTIF_WM_HINTS == 0 ) - _MOTIF_WM_HINTS = XInternAtom(win->src.display, "_MOTIF_WM_HINTS", False); - - struct __x11WindowHints { - unsigned long flags, functions, decorations, status; - long input_mode; - } hints; - hints.flags = (1L << 1); - hints.decorations = border; - - XChangeProperty( - win->src.display, win->src.window, - _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, - 32, PropModeReplace, (u8*)&hints, 5 - ); - } - - void RGFW_releaseCursor(RGFW_window* win) { - XUngrabPointer(win->src.display, CurrentTime); - - /* disable raw input */ - unsigned char mask[] = { 0 }; - XIEventMask em; - em.deviceid = XIAllMasterDevices; - em.mask_len = sizeof(mask); - em.mask = mask; - - XISelectEvents(win->src.display, XDefaultRootWindow(win->src.display), &em, 1); - } - - void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) { - /* enable raw input */ - unsigned char mask[XIMaskLen(XI_RawMotion)] = { 0 }; - XISetMask(mask, XI_RawMotion); - - XIEventMask em; - em.deviceid = XIAllMasterDevices; - em.mask_len = sizeof(mask); - em.mask = mask; - - XISelectEvents(win->src.display, XDefaultRootWindow(win->src.display), &em, 1); - - XGrabPointer(win->src.display, win->src.window, True, PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); - - RGFW_window_moveMouse(win, RGFW_POINT(win->r.x + (i32)(r.w / 2), win->r.y + (i32)(r.h / 2))); - } - - RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) { -#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD) - if (X11Cursorhandle == NULL) { -#if defined(__CYGWIN__) - X11Cursorhandle = dlopen("libXcursor-1.so", RTLD_LAZY | RTLD_LOCAL); -#elif defined(__OpenBSD__) || defined(__NetBSD__) - X11Cursorhandle = dlopen("libXcursor.so", RTLD_LAZY | RTLD_LOCAL); -#else - X11Cursorhandle = dlopen("libXcursor.so.1", RTLD_LAZY | RTLD_LOCAL); -#endif - - XcursorImageCreateSrc = (PFN_XcursorImageCreate) dlsym(X11Cursorhandle, "XcursorImageCreate"); - XcursorImageDestroySrc = (PFN_XcursorImageDestroy) dlsym(X11Cursorhandle, "XcursorImageDestroy"); - XcursorImageLoadCursorSrc = (PFN_XcursorImageLoadCursor) dlsym(X11Cursorhandle, "XcursorImageLoadCursor"); - } -#endif - -#if !defined(RGFW_NO_X11_XI_PRELOAD) - if (X11Xihandle == NULL) { -#if defined(__CYGWIN__) - X11Xihandle = dlopen("libXi-6.so", RTLD_LAZY | RTLD_LOCAL); -#elif defined(__OpenBSD__) || defined(__NetBSD__) - X11Xihandle = dlopen("libXi.so", RTLD_LAZY | RTLD_LOCAL); -#else - X11Xihandle = dlopen("libXi.so.6", RTLD_LAZY | RTLD_LOCAL); -#endif - - XISelectEventsSrc = (PFN_XISelectEvents) dlsym(X11Xihandle, "XISelectEvents"); - } -#endif - - XInitThreads(); /*!< init X11 threading*/ - - if (args & RGFW_OPENGL_SOFTWARE) - setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1); - - RGFW_window* win = RGFW_window_basic_init(rect, args); - - u64 event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask | FocusChangeMask | LeaveWindowMask | EnterWindowMask | ExposureMask; /*!< X11 events accepted*/ - -#ifdef RGFW_OPENGL - u32* visual_attribs = RGFW_initFormatAttribs(args & RGFW_OPENGL_SOFTWARE); - i32 fbcount; - GLXFBConfig* fbc = glXChooseFBConfig((Display*) win->src.display, DefaultScreen(win->src.display), (i32*) visual_attribs, &fbcount); - - i32 best_fbc = -1; - - if (fbcount == 0) { - printf("Failed to find any valid GLX visual configs\n"); - return NULL; - } - - u32 i; - for (i = 0; i < (u32)fbcount; i++) { - XVisualInfo* vi = glXGetVisualFromFBConfig((Display*) win->src.display, fbc[i]); - if (vi == NULL) - continue; - - XFree(vi); - - i32 samp_buf, samples; - glXGetFBConfigAttrib((Display*) win->src.display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf); - glXGetFBConfigAttrib((Display*) win->src.display, fbc[i], GLX_SAMPLES, &samples); - - if ((!(args & RGFW_TRANSPARENT_WINDOW) || vi->depth == 32) && - (best_fbc < 0 || samp_buf) && (samples == RGFW_SAMPLES || best_fbc == -1)) { - best_fbc = i; - } - } - - if (best_fbc == -1) { - printf("Failed to get a valid GLX visual\n"); - return NULL; - } - - GLXFBConfig bestFbc = fbc[best_fbc]; - - /* Get a visual */ - XVisualInfo* vi = glXGetVisualFromFBConfig((Display*) win->src.display, bestFbc); - - XFree(fbc); -#else - XVisualInfo viNorm; - - viNorm.visual = DefaultVisual((Display*) win->src.display, DefaultScreen((Display*) win->src.display)); - - viNorm.depth = 0; - XVisualInfo* vi = &viNorm; - - XMatchVisualInfo((Display*) win->src.display, DefaultScreen((Display*) win->src.display), 32, TrueColor, vi); /*!< for RGBA backgrounds*/ -#endif - /* make X window attrubutes*/ - XSetWindowAttributes swa; - Colormap cmap; - - swa.colormap = cmap = XCreateColormap((Display*) win->src.display, - DefaultRootWindow(win->src.display), - vi->visual, AllocNone); - - swa.background_pixmap = None; - swa.border_pixel = 0; - swa.event_mask = event_mask; - - swa.background_pixel = 0; - - /* create the window*/ - win->src.window = XCreateWindow((Display*) win->src.display, DefaultRootWindow((Display*) win->src.display), win->r.x, win->r.y, win->r.w, win->r.h, - 0, vi->depth, InputOutput, vi->visual, - CWColormap | CWBorderPixel | CWBackPixel | CWEventMask, &swa); - - XFreeColors((Display*) win->src.display, cmap, NULL, 0, 0); - - #ifdef RGFW_OPENGL - XFree(vi); - #endif - - // In your .desktop app, if you set the property - // StartupWMClass=RGFW that will assoicate the launcher icon - // with your application - robrohan - - if (RGFW_className == NULL) - RGFW_className = (char*)name; - - XClassHint *hint = XAllocClassHint(); - assert(hint != NULL); - hint->res_class = (char*)RGFW_className; - hint->res_name = (char*)name; // just use the window name as the app name - XSetClassHint((Display*) win->src.display, win->src.window, hint); - XFree(hint); - - if ((args & RGFW_NO_INIT_API) == 0) { -#ifdef RGFW_OPENGL /* This is the second part of setting up opengl. This is where we ask OpenGL for a specific version. */ - i32 context_attribs[7] = { 0, 0, 0, 0, 0, 0, 0 }; - context_attribs[0] = GLX_CONTEXT_PROFILE_MASK_ARB; - if (RGFW_profile == RGFW_GL_CORE) - context_attribs[1] = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; - else - context_attribs[1] = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; - - if (RGFW_majorVersion || RGFW_minorVersion) { - context_attribs[2] = GLX_CONTEXT_MAJOR_VERSION_ARB; - context_attribs[3] = RGFW_majorVersion; - context_attribs[4] = GLX_CONTEXT_MINOR_VERSION_ARB; - context_attribs[5] = RGFW_minorVersion; - } - - glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0; - glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) - glXGetProcAddressARB((GLubyte*) "glXCreateContextAttribsARB"); - - GLXContext ctx = NULL; - - if (RGFW_root != NULL) - ctx = RGFW_root->src.ctx; - - win->src.ctx = glXCreateContextAttribsARB((Display*) win->src.display, bestFbc, ctx, True, context_attribs); -#endif - if (RGFW_root == NULL) - RGFW_root = win; - - RGFW_init_buffer(win, vi); - } - - - #ifndef RGFW_NO_MONITOR - if (args & RGFW_SCALE_TO_MONITOR) - RGFW_window_scaleToMonitor(win); - #endif - - if (args & RGFW_CENTER) { - RGFW_area screenR = RGFW_getScreenSize(); - RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2)); - } - - if (args & RGFW_NO_RESIZE) { /* make it so the user can't resize the window*/ - XSizeHints* sh = XAllocSizeHints(); - sh->flags = (1L << 4) | (1L << 5); - sh->min_width = sh->max_width = win->r.w; - sh->min_height = sh->max_height = win->r.h; - - XSetWMSizeHints((Display*) win->src.display, (Drawable) win->src.window, sh, XA_WM_NORMAL_HINTS); - XFree(sh); - } - - if (args & RGFW_NO_BORDER) { - RGFW_window_setBorder(win, 0); - } - - XSelectInput((Display*) win->src.display, (Drawable) win->src.window, event_mask); /*!< tell X11 what events we want*/ - - /* make it so the user can't close the window until the program does*/ - if (wm_delete_window == 0) - wm_delete_window = XInternAtom((Display*) win->src.display, "WM_DELETE_WINDOW", False); - - XSetWMProtocols((Display*) win->src.display, (Drawable) win->src.window, &wm_delete_window, 1); - - /* connect the context to the window*/ -#ifdef RGFW_OPENGL - if ((args & RGFW_NO_INIT_API) == 0) - glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.ctx); -#endif - - /* set the background*/ - XStoreName((Display*) win->src.display, (Drawable) win->src.window, name); /*!< set the name*/ - - XMapWindow((Display*) win->src.display, (Drawable) win->src.window); /* draw the window*/ - XMoveWindow((Display*) win->src.display, (Drawable) win->src.window, win->r.x, win->r.y); /*!< move the window to it's proper cords*/ - - if (args & RGFW_ALLOW_DND) { /* init drag and drop atoms and turn on drag and drop for this window */ - win->_winArgs |= RGFW_ALLOW_DND; - - XdndTypeList = XInternAtom((Display*) win->src.display, "XdndTypeList", False); - XdndSelection = XInternAtom((Display*) win->src.display, "XdndSelection", False); - - /* client messages */ - XdndEnter = XInternAtom((Display*) win->src.display, "XdndEnter", False); - XdndPosition = XInternAtom((Display*) win->src.display, "XdndPosition", False); - XdndStatus = XInternAtom((Display*) win->src.display, "XdndStatus", False); - XdndLeave = XInternAtom((Display*) win->src.display, "XdndLeave", False); - XdndDrop = XInternAtom((Display*) win->src.display, "XdndDrop", False); - XdndFinished = XInternAtom((Display*) win->src.display, "XdndFinished", False); - - /* actions */ - XdndActionCopy = XInternAtom((Display*) win->src.display, "XdndActionCopy", False); - - XtextUriList = XInternAtom((Display*) win->src.display, "text/uri-list", False); - XtextPlain = XInternAtom((Display*) win->src.display, "text/plain", False); - - XdndAware = XInternAtom((Display*) win->src.display, "XdndAware", False); - const u8 version = 5; - - XChangeProperty((Display*) win->src.display, (Window) win->src.window, - XdndAware, 4, 32, - PropModeReplace, &version, 1); /*!< turns on drag and drop */ - } - - #ifdef RGFW_EGL - if ((args & RGFW_NO_INIT_API) == 0) - RGFW_createOpenGLContext(win); - #endif - - RGFW_window_setMouseDefault(win); - - RGFW_windowsOpen++; - - return win; /*return newly created window*/ - } - - RGFW_area RGFW_getScreenSize(void) { - assert(RGFW_root != NULL); - - Screen* scrn = DefaultScreenOfDisplay((Display*) RGFW_root->src.display); - return RGFW_AREA(scrn->width, scrn->height); - } - - RGFW_point RGFW_getGlobalMousePoint(void) { - assert(RGFW_root != NULL); - - RGFW_point RGFWMouse; - - i32 x, y; - u32 z; - Window window1, window2; - XQueryPointer((Display*) RGFW_root->src.display, XDefaultRootWindow((Display*) RGFW_root->src.display), &window1, &window2, &RGFWMouse.x, &RGFWMouse.y, &x, &y, &z); - - return RGFWMouse; - } - - RGFW_point RGFW_window_getMousePoint(RGFW_window* win) { - assert(win != NULL); - - RGFW_point RGFWMouse; - - i32 x, y; - u32 z; - Window window1, window2; - XQueryPointer((Display*) win->src.display, win->src.window, &window1, &window2, &x, &y, &RGFWMouse.x, &RGFWMouse.y, &z); - - return RGFWMouse; - } - - int xAxis = 0, yAxis = 0; - - RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) { - assert(win != NULL); - - static struct { - long source, version; - i32 format; - } xdnd; - - if (win->event.type == 0) - RGFW_resetKey(); - - if (win->event.type == RGFW_quit) { - return NULL; - } - - win->event.type = 0; - -#ifdef __linux__ - RGFW_Event* event = RGFW_linux_updateJoystick(win); - if (event != NULL) - return event; -#endif - - XPending(win->src.display); - - XEvent E; /*!< raw X11 event */ - - /* if there is no unread qued events, get a new one */ - if ((QLength(win->src.display) || XEventsQueued((Display*) win->src.display, QueuedAlready) + XEventsQueued((Display*) win->src.display, QueuedAfterReading)) - && win->event.type != RGFW_quit - ) - XNextEvent((Display*) win->src.display, &E); - else { - return NULL; - } - - u32 i; - win->event.type = 0; - - - switch (E.type) { - case KeyPress: - case KeyRelease: { - win->event.repeat = RGFW_FALSE; - /* check if it's a real key release */ - if (E.type == KeyRelease && XEventsQueued((Display*) win->src.display, QueuedAfterReading)) { /* get next event if there is one*/ - XEvent NE; - XPeekEvent((Display*) win->src.display, &NE); - - if (E.xkey.time == NE.xkey.time && E.xkey.keycode == NE.xkey.keycode) /* check if the current and next are both the same*/ - win->event.repeat = RGFW_TRUE; - } - - /* set event key data */ - KeySym sym = (KeySym)XkbKeycodeToKeysym((Display*) win->src.display, E.xkey.keycode, 0, E.xkey.state & ShiftMask ? 1 : 0); - win->event.keyCode = RGFW_apiKeyCodeToRGFW(E.xkey.keycode); - - char* str = (char*)XKeysymToString(sym); - if (str != NULL) - strncpy(win->event.keyName, str, 16); - - win->event.keyName[15] = '\0'; - - RGFW_keyboard[win->event.keyCode].prev = RGFW_isPressed(win, win->event.keyCode); - - /* get keystate data */ - win->event.type = (E.type == KeyPress) ? RGFW_keyPressed : RGFW_keyReleased; - - XKeyboardState keystate; - XGetKeyboardControl((Display*) win->src.display, &keystate); - - RGFW_updateLockState(win, (keystate.led_mask & 1), (keystate.led_mask & 2)); - RGFW_keyboard[win->event.keyCode].current = (E.type == KeyPress); - RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, (E.type == KeyPress)); - break; - } - case ButtonPress: - case ButtonRelease: - win->event.type = RGFW_mouseButtonPressed + (E.type == ButtonRelease); // the events match - - switch(win->event.button) { - case RGFW_mouseScrollUp: - win->event.scroll = 1; - break; - case RGFW_mouseScrollDown: - win->event.scroll = -1; - break; - default: break; - } - - win->event.button = E.xbutton.button; - RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; - - if (win->event.repeat == RGFW_FALSE) - win->event.repeat = RGFW_isPressed(win, win->event.keyCode); - - RGFW_mouseButtons[win->event.button].current = (E.type == ButtonPress); - RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, (E.type == ButtonPress)); - break; - - case MotionNotify: - win->event.point.x = E.xmotion.x; - win->event.point.y = E.xmotion.y; - - if ((win->_winArgs & RGFW_HOLD_MOUSE)) { - win->event.point.y = E.xmotion.y; - - win->event.point.x = win->_lastMousePoint.x - abs(win->event.point.x); - win->event.point.y = win->_lastMousePoint.y - abs(win->event.point.y); - } - - win->_lastMousePoint = RGFW_POINT(E.xmotion.x, E.xmotion.y); - - win->event.type = RGFW_mousePosChanged; - RGFW_mousePosCallback(win, win->event.point); - break; - - case GenericEvent: { - /* MotionNotify is used for mouse events if the mouse isn't held */ - if (!(win->_winArgs & RGFW_HOLD_MOUSE)) { - XFreeEventData(win->src.display, &E.xcookie); - break; - } - - XGetEventData(win->src.display, &E.xcookie); - if (E.xcookie.evtype == XI_RawMotion) { - XIRawEvent *raw = (XIRawEvent *)E.xcookie.data; - if (raw->valuators.mask_len == 0) { - XFreeEventData(win->src.display, &E.xcookie); - break; + if (bytes == -1 && errno == ENODEV) { + RGFW_gamepadCount--; + close(RGFW_gamepads[i]); + RGFW_gamepads[i] = 0; + + win->event.type = RGFW_gamepadDisconnected; + win->event.gamepad = i; + RGFW_gamepadCallback(win, i, 0); + return 1; } - - double deltaX = 0.0f; - double deltaY = 0.0f; - - /* check if relative motion data exists where we think it does */ - if (XIMaskIsSet(raw->valuators.mask, 0) != 0) - deltaX += raw->raw_values[0]; - if (XIMaskIsSet(raw->valuators.mask, 1) != 0) - deltaY += raw->raw_values[1]; - - win->event.point = RGFW_POINT((i32)deltaX, (i32)deltaY); - - RGFW_window_moveMouse(win, RGFW_POINT(win->r.x + (win->r.w / 2), win->r.y + (win->r.h / 2))); - - win->event.type = RGFW_mousePosChanged; - RGFW_mousePosCallback(win, win->event.point); - } - - XFreeEventData(win->src.display, &E.xcookie); - break; - } - - case Expose: - win->event.type = RGFW_windowRefresh; - RGFW_windowRefreshCallback(win); - break; - - case ClientMessage: - /* if the client closed the window*/ - if (E.xclient.data.l[0] == (i64) wm_delete_window) { - win->event.type = RGFW_quit; - RGFW_windowQuitCallback(win); - break; } - - /* reset DND values */ - if (win->event.droppedFilesCount) { - for (i = 0; i < win->event.droppedFilesCount; i++) - win->event.droppedFiles[i][0] = '\0'; - } - - win->event.droppedFilesCount = 0; - - if ((win->_winArgs & RGFW_ALLOW_DND) == 0) - break; - - XEvent reply = { ClientMessage }; - reply.xclient.window = xdnd.source; - reply.xclient.format = 32; - reply.xclient.data.l[0] = (long) win->src.window; - reply.xclient.data.l[1] = 0; - reply.xclient.data.l[2] = None; - - if (E.xclient.message_type == XdndEnter) { - unsigned long count; - Atom* formats; - Atom real_formats[6]; - - Bool list = E.xclient.data.l[1] & 1; - - xdnd.source = E.xclient.data.l[0]; - xdnd.version = E.xclient.data.l[1] >> 24; - xdnd.format = None; - - if (xdnd.version > 5) - break; - - if (list) { - Atom actualType; - i32 actualFormat; - unsigned long bytesAfter; - - XGetWindowProperty((Display*) win->src.display, - xdnd.source, - XdndTypeList, - 0, - LONG_MAX, - False, - 4, - &actualType, - &actualFormat, - &count, - &bytesAfter, - (u8**) &formats); - } else { - count = 0; - - if (E.xclient.data.l[2] != None) - real_formats[count++] = E.xclient.data.l[2]; - if (E.xclient.data.l[3] != None) - real_formats[count++] = E.xclient.data.l[3]; - if (E.xclient.data.l[4] != None) - real_formats[count++] = E.xclient.data.l[4]; - - formats = real_formats; - } - - unsigned long i; - for (i = 0; i < count; i++) { - if (formats[i] == XtextUriList || formats[i] == XtextPlain) { - xdnd.format = formats[i]; - break; - } - } - - if (list) { - XFree(formats); - } - - break; - } - if (E.xclient.message_type == XdndPosition) { - const i32 xabs = (E.xclient.data.l[2] >> 16) & 0xffff; - const i32 yabs = (E.xclient.data.l[2]) & 0xffff; - Window dummy; - i32 xpos, ypos; - - if (xdnd.version > 5) - break; - - XTranslateCoordinates((Display*) win->src.display, - XDefaultRootWindow((Display*) win->src.display), - (Window) win->src.window, - xabs, yabs, - &xpos, &ypos, - &dummy); - - win->event.point.x = xpos; - win->event.point.y = ypos; - - reply.xclient.window = xdnd.source; - reply.xclient.message_type = XdndStatus; - - if (xdnd.format) { - reply.xclient.data.l[1] = 1; - if (xdnd.version >= 2) - reply.xclient.data.l[4] = XdndActionCopy; - } - - XSendEvent((Display*) win->src.display, xdnd.source, False, NoEventMask, &reply); - XFlush((Display*) win->src.display); - break; - } - - if (E.xclient.message_type != XdndDrop) - break; - - if (xdnd.version > 5) - break; - - win->event.type = RGFW_dnd_init; - - if (xdnd.format) { - Time time = CurrentTime; - - if (xdnd.version >= 1) - time = E.xclient.data.l[2]; - - XConvertSelection((Display*) win->src.display, - XdndSelection, - xdnd.format, - XdndSelection, - (Window) win->src.window, - time); - } else if (xdnd.version >= 2) { - XEvent reply = { ClientMessage }; - - XSendEvent((Display*) win->src.display, xdnd.source, - False, NoEventMask, &reply); - XFlush((Display*) win->src.display); - } - - RGFW_dndInitCallback(win, win->event.point); - break; - case SelectionNotify: { - /* this is only for checking for xdnd drops */ - if (E.xselection.property != XdndSelection || !(win->_winArgs | RGFW_ALLOW_DND)) - break; - - char* data; - unsigned long result; - - Atom actualType; - i32 actualFormat; - unsigned long bytesAfter; - - XGetWindowProperty((Display*) win->src.display, E.xselection.requestor, E.xselection.property, 0, LONG_MAX, False, E.xselection.target, &actualType, &actualFormat, &result, &bytesAfter, (u8**) &data); - - if (result == 0) - break; - - /* - SOURCED FROM GLFW _glfwParseUriList - Copyright (c) 2002-2006 Marcus Geelnard - Copyright (c) 2006-2019 Camilla Löwy - */ - - const char* prefix = (const char*)"file://"; - - char* line; - - win->event.droppedFilesCount = 0; - - win->event.type = RGFW_dnd; - - while ((line = strtok(data, "\r\n"))) { - char path[RGFW_MAX_PATH]; - - data = NULL; - - if (line[0] == '#') - continue; - - char* l; - for (l = line; 1; l++) { - if ((l - line) > 7) - break; - else if (*l != prefix[(l - line)]) - break; - else if (*l == '\0' && prefix[(l - line)] == '\0') { - line += 7; - while (*line != '/') - line++; - break; - } else if (*l == '\0') - break; - } - - win->event.droppedFilesCount++; - - size_t index = 0; - while (*line) { - if (line[0] == '%' && line[1] && line[2]) { - const char digits[3] = { line[1], line[2], '\0' }; - path[index] = (char) strtol(digits, NULL, 16); - line += 2; - } else - path[index] = *line; - - index++; - line++; - } - path[index] = '\0'; - strncpy(win->event.droppedFiles[win->event.droppedFilesCount - 1], path, index + 1); - } - - if (data) - XFree(data); - - if (xdnd.version >= 2) { - reply.xclient.message_type = XdndFinished; - reply.xclient.data.l[1] = result; - reply.xclient.data.l[2] = XdndActionCopy; - - XSendEvent((Display*) win->src.display, xdnd.source, False, NoEventMask, &reply); - XFlush((Display*) win->src.display); - } - - RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount); - break; - } - case FocusIn: - win->event.inFocus = 1; - win->event.type = RGFW_focusIn; - RGFW_focusCallback(win, 1); - break; - - break; - case FocusOut: - win->event.inFocus = 0; - win->event.type = RGFW_focusOut; - RGFW_focusCallback(win, 0); - break; - - case EnterNotify: { - win->event.type = RGFW_mouseEnter; - win->event.point.x = E.xcrossing.x; - win->event.point.y = E.xcrossing.y; - RGFW_mouseNotifyCallBack(win, win->event.point, 1); - break; - } - - case LeaveNotify: { - win->event.type = RGFW_mouseLeave; - RGFW_mouseNotifyCallBack(win, win->event.point, 0); - break; - } - - case ConfigureNotify: { - /* detect resize */ - if (E.xconfigure.width != win->r.w || E.xconfigure.height != win->r.h) { - win->event.type = RGFW_windowResized; - win->r = RGFW_RECT(win->r.x, win->r.y, E.xconfigure.width, E.xconfigure.height); - RGFW_windowResizeCallback(win, win->r); - break; - } - - /* detect move */ - if (E.xconfigure.x != win->r.x || E.xconfigure.y != win->r.y) { - win->event.type = RGFW_windowMoved; - win->r = RGFW_RECT(E.xconfigure.x, E.xconfigure.y, win->r.w, win->r.h); - RGFW_windowMoveCallback(win, win->r); - break; - } - - break; - } - default: { - break; - } - } - - XFlush((Display*) win->src.display); - - if (win->event.type) - return &win->event; - else - return NULL; - } - - void RGFW_window_move(RGFW_window* win, RGFW_point v) { - assert(win != NULL); - win->r.x = v.x; - win->r.y = v.y; - - XMoveWindow((Display*) win->src.display, (Window) win->src.window, v.x, v.y); - } - - - void RGFW_window_resize(RGFW_window* win, RGFW_area a) { - assert(win != NULL); - win->r.w = a.w; - win->r.h = a.h; - - XResizeWindow((Display*) win->src.display, (Window) win->src.window, a.w, a.h); - } - - void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) { - assert(win != NULL); - - if (a.w == 0 && a.h == 0) - return; - - XSizeHints hints; - long flags; - - XGetWMNormalHints(win->src.display, (Window) win->src.window, &hints, &flags); - - hints.flags |= PMinSize; - - hints.min_width = a.w; - hints.min_height = a.h; - - XSetWMNormalHints(win->src.display, (Window) win->src.window, &hints); - } - - void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) { - assert(win != NULL); - - if (a.w == 0 && a.h == 0) - return; - - XSizeHints hints; - long flags; - - XGetWMNormalHints(win->src.display, (Window) win->src.window, &hints, &flags); - - hints.flags |= PMaxSize; - - hints.max_width = a.w; - hints.max_height = a.h; - - XSetWMNormalHints(win->src.display, (Window) win->src.window, &hints); - } - - - void RGFW_window_minimize(RGFW_window* win) { - assert(win != NULL); - - XIconifyWindow(win->src.display, (Window) win->src.window, DefaultScreen(win->src.display)); - XFlush(win->src.display); - } - - void RGFW_window_restore(RGFW_window* win) { - assert(win != NULL); - - XMapWindow(win->src.display, (Window) win->src.window); - XFlush(win->src.display); - } - - void RGFW_window_setName(RGFW_window* win, char* name) { - assert(win != NULL); - - XStoreName((Display*) win->src.display, (Window) win->src.window, name); - } - - void* RGFW_libxshape = NULL; - - #ifndef RGFW_NO_PASSTHROUGH - void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) { - assert(win != NULL); - - #if defined(__CYGWIN__) - RGFW_libxshape = dlopen("libXext-6.so", RTLD_LAZY | RTLD_LOCAL); - #elif defined(__OpenBSD__) || defined(__NetBSD__) - RGFW_libxshape = dlopen("libXext.so", RTLD_LAZY | RTLD_LOCAL); - #else - RGFW_libxshape = dlopen("libXext.so.6", RTLD_LAZY | RTLD_LOCAL); - #endif - - typedef void (* PFN_XShapeCombineMask)(Display*,Window,int,int,int,Pixmap,int); - static PFN_XShapeCombineMask XShapeCombineMask; - - typedef void (* PFN_XShapeCombineRegion)(Display*,Window,int,int,int,Region,int); - static PFN_XShapeCombineRegion XShapeCombineRegion; - - if (XShapeCombineMask != NULL) - XShapeCombineMask = (PFN_XShapeCombineMask) dlsym(RGFW_libxshape, "XShapeCombineMask"); - - if (XShapeCombineRegion != NULL) - XShapeCombineRegion = (PFN_XShapeCombineRegion) dlsym(RGFW_libxshape, "XShapeCombineMask"); - - if (passthrough) { - Region region = XCreateRegion(); - XShapeCombineRegion(win->src.display, win->src.window, ShapeInput, 0, 0, region, ShapeSet); - XDestroyRegion(region); - - return; - } - - XShapeCombineMask(win->src.display, win->src.window, ShapeInput, 0, 0, None, ShapeSet); - } - #endif - - /* - the majority function is sourced from GLFW - */ - - void RGFW_window_setIcon(RGFW_window* win, u8* icon, RGFW_area a, i32 channels) { - assert(win != NULL); - - i32 longCount = 2 + a.w * a.h; - - u64* X11Icon = (u64*) RGFW_MALLOC(longCount * sizeof(u64)); - u64* target = X11Icon; - - *target++ = a.w; - *target++ = a.h; - - u32 i; - - for (i = 0; i < a.w * a.h; i++) { - if (channels == 3) - *target++ = ((icon[i * 3 + 0]) << 16) | - ((icon[i * 3 + 1]) << 8) | - ((icon[i * 3 + 2]) << 0) | - (0xFF << 24); - - else if (channels == 4) - *target++ = ((icon[i * 4 + 0]) << 16) | - ((icon[i * 4 + 1]) << 8) | - ((icon[i * 4 + 2]) << 0) | - ((icon[i * 4 + 3]) << 24); - } - - static Atom NET_WM_ICON = 0; - if (NET_WM_ICON == 0) - NET_WM_ICON = XInternAtom((Display*) win->src.display, "_NET_WM_ICON", False); - - XChangeProperty((Display*) win->src.display, (Window) win->src.window, - NET_WM_ICON, - 6, 32, - PropModeReplace, - (u8*) X11Icon, - longCount); - - RGFW_FREE(X11Icon); - - XFlush((Display*) win->src.display); - } - - void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) { - assert(win != NULL); - -#ifndef RGFW_NO_X11_CURSOR - XcursorImage* native = XcursorImageCreate(a.w, a.h); - native->xhot = 0; - native->yhot = 0; - - u8* source = (u8*) image; - XcursorPixel* target = native->pixels; - - u32 i; - for (i = 0; i < a.w * a.h; i++, target++, source += 4) { - u8 alpha = 0xFF; - if (channels == 4) - alpha = source[3]; - - *target = (alpha << 24) | (((source[0] * alpha) / 255) << 16) | (((source[1] * alpha) / 255) << 8) | (((source[2] * alpha) / 255) << 0); - } - - Cursor cursor = XcursorImageLoadCursor((Display*) win->src.display, native); - XDefineCursor((Display*) win->src.display, (Window) win->src.window, (Cursor) cursor); - - XFreeCursor((Display*) win->src.display, (Cursor) cursor); - XcursorImageDestroy(native); -#else - RGFW_UNUSED(image) RGFW_UNUSED(a.w) RGFW_UNUSED(channels) -#endif - } - - void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v) { - assert(win != NULL); - - XEvent event; - XQueryPointer(win->src.display, DefaultRootWindow(win->src.display), - &event.xbutton.root, &event.xbutton.window, - &event.xbutton.x_root, &event.xbutton.y_root, - &event.xbutton.x, &event.xbutton.y, - &event.xbutton.state); - - if (event.xbutton.x == v.x && event.xbutton.y == v.y) - return; - - XWarpPointer(win->src.display, None, win->src.window, 0, 0, 0, 0, (int) v.x - win->r.x, (int) v.y - win->r.y); - } - - RGFWDEF void RGFW_window_disableMouse(RGFW_window* win) { - RGFW_UNUSED(win); - } - - void RGFW_window_setMouseDefault(RGFW_window* win) { - RGFW_window_setMouseStandard(win, RGFW_MOUSE_ARROW); - } - - void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) { - assert(win != NULL); - - if (mouse > (sizeof(RGFW_mouseIconSrc) / sizeof(u8))) - return; - - mouse = RGFW_mouseIconSrc[mouse]; - - Cursor cursor = XCreateFontCursor((Display*) win->src.display, mouse); - XDefineCursor((Display*) win->src.display, (Window) win->src.window, (Cursor) cursor); - - XFreeCursor((Display*) win->src.display, (Cursor) cursor); - } - - void RGFW_window_hide(RGFW_window* win) { - XMapWindow(win->src.display, win->src.window); - } - - void RGFW_window_show(RGFW_window* win) { - XUnmapWindow(win->src.display, win->src.window); - } - - /* - the majority function is sourced from GLFW - */ - char* RGFW_readClipboard(size_t* size) { - static Atom UTF8 = 0; - if (UTF8 == 0) - UTF8 = XInternAtom(RGFW_root->src.display, "UTF8_STRING", True); - - XEvent event; - int format; - unsigned long N, sizeN; - char* data, * s = NULL; - Atom target; - Atom CLIPBOARD = 0, XSEL_DATA = 0; - - if (CLIPBOARD == 0) { - CLIPBOARD = XInternAtom(RGFW_root->src.display, "CLIPBOARD", 0); - XSEL_DATA = XInternAtom(RGFW_root->src.display, "XSEL_DATA", 0); - } - - XConvertSelection(RGFW_root->src.display, CLIPBOARD, UTF8, XSEL_DATA, RGFW_root->src.window, CurrentTime); - XSync(RGFW_root->src.display, 0); - XNextEvent(RGFW_root->src.display, &event); - - if (event.type != SelectionNotify || event.xselection.selection != CLIPBOARD || event.xselection.property == 0) - return NULL; - - XGetWindowProperty(event.xselection.display, event.xselection.requestor, - event.xselection.property, 0L, (~0L), 0, AnyPropertyType, &target, - &format, &sizeN, &N, (unsigned char**) &data); - - if (target == UTF8 || target == XA_STRING) { - s = (char*)RGFW_MALLOC(sizeof(char) * sizeN); - strncpy(s, data, sizeN); - s[sizeN] = '\0'; - XFree(data); - } - - XDeleteProperty(event.xselection.display, event.xselection.requestor, event.xselection.property); - - if (s != NULL && size != NULL) - *size = sizeN; - - return s; - } - - /* - almost all of this function is sourced from GLFW - */ - void RGFW_writeClipboard(const char* text, u32 textLen) { - static Atom CLIPBOARD = 0, - UTF8_STRING = 0, - SAVE_TARGETS = 0, - TARGETS = 0, - MULTIPLE = 0, - ATOM_PAIR = 0, - CLIPBOARD_MANAGER = 0; - - if (CLIPBOARD == 0) { - CLIPBOARD = XInternAtom((Display*) RGFW_root->src.display, "CLIPBOARD", False); - UTF8_STRING = XInternAtom((Display*) RGFW_root->src.display, "UTF8_STRING", False); - SAVE_TARGETS = XInternAtom((Display*) RGFW_root->src.display, "SAVE_TARGETS", False); - TARGETS = XInternAtom((Display*) RGFW_root->src.display, "TARGETS", False); - MULTIPLE = XInternAtom((Display*) RGFW_root->src.display, "MULTIPLE", False); - ATOM_PAIR = XInternAtom((Display*) RGFW_root->src.display, "ATOM_PAIR", False); - CLIPBOARD_MANAGER = XInternAtom((Display*) RGFW_root->src.display, "CLIPBOARD_MANAGER", False); - } - - XSetSelectionOwner((Display*) RGFW_root->src.display, CLIPBOARD, (Window) RGFW_root->src.window, CurrentTime); - - XConvertSelection((Display*) RGFW_root->src.display, CLIPBOARD_MANAGER, SAVE_TARGETS, None, (Window) RGFW_root->src.window, CurrentTime); - for (;;) { - XEvent event; - - XNextEvent((Display*) RGFW_root->src.display, &event); - if (event.type != SelectionRequest) { - break; - } - - const XSelectionRequestEvent* request = &event.xselectionrequest; - - XEvent reply = { SelectionNotify }; - reply.xselection.property = 0; - - if (request->target == TARGETS) { - const Atom targets[] = { TARGETS, - MULTIPLE, - UTF8_STRING, - XA_STRING }; - - XChangeProperty((Display*) RGFW_root->src.display, - request->requestor, - request->property, - 4, - 32, - PropModeReplace, - (u8*) targets, - sizeof(targets) / sizeof(targets[0])); - - reply.xselection.property = request->property; - } - - if (request->target == MULTIPLE) { - Atom* targets = NULL; - - Atom actualType = 0; - int actualFormat = 0; - unsigned long count = 0, bytesAfter = 0; - - XGetWindowProperty((Display*) RGFW_root->src.display, request->requestor, request->property, 0, LONG_MAX, False, ATOM_PAIR, &actualType, &actualFormat, &count, &bytesAfter, (u8**) &targets); - - unsigned long i; - for (i = 0; i < (u32)count; i += 2) { - if (targets[i] == UTF8_STRING || targets[i] == XA_STRING) { - XChangeProperty((Display*) RGFW_root->src.display, - request->requestor, - targets[i + 1], - targets[i], - 8, - PropModeReplace, - (u8*) text, - textLen); - XFlush(RGFW_root->src.display); - } else { - targets[i + 1] = None; - } - } - - XChangeProperty((Display*) RGFW_root->src.display, - request->requestor, - request->property, - ATOM_PAIR, - 32, - PropModeReplace, - (u8*) targets, - count); - - XFlush(RGFW_root->src.display); - XFree(targets); - - reply.xselection.property = request->property; - } - - reply.xselection.display = request->display; - reply.xselection.requestor = request->requestor; - reply.xselection.selection = request->selection; - reply.xselection.target = request->target; - reply.xselection.time = request->time; - - XSendEvent((Display*) RGFW_root->src.display, request->requestor, False, 0, &reply); - XFlush(RGFW_root->src.display); - } - } - - u8 RGFW_window_isFullscreen(RGFW_window* win) { - assert(win != NULL); - - XWindowAttributes windowAttributes; - XGetWindowAttributes(win->src.display, (Window) win->src.window, &windowAttributes); - - /* check if the window is visable */ - if (windowAttributes.map_state != IsViewable) - return 0; - - /* check if the window covers the full screen */ - return (windowAttributes.x == 0 && windowAttributes.y == 0 && - windowAttributes.width == XDisplayWidth(win->src.display, DefaultScreen(win->src.display)) && - windowAttributes.height == XDisplayHeight(win->src.display, DefaultScreen(win->src.display))); - } - - u8 RGFW_window_isHidden(RGFW_window* win) { - assert(win != NULL); - - XWindowAttributes windowAttributes; - XGetWindowAttributes(win->src.display, (Window) win->src.window, &windowAttributes); - - return (windowAttributes.map_state == IsUnmapped && !RGFW_window_isMinimized(win)); - } - - u8 RGFW_window_isMinimized(RGFW_window* win) { - assert(win != NULL); - - static Atom prop = 0; - if (prop == 0) - prop = XInternAtom(win->src.display, "WM_STATE", False); - - Atom actual_type; - i32 actual_format; - unsigned long nitems, bytes_after; - unsigned char* prop_data; - - i16 status = XGetWindowProperty(win->src.display, (Window) win->src.window, prop, 0, 2, False, - AnyPropertyType, &actual_type, &actual_format, - &nitems, &bytes_after, &prop_data); - - if (status == Success && nitems >= 1 && *((int*) prop_data) == IconicState) { - XFree(prop_data); - return 1; - } - - if (prop_data != NULL) - XFree(prop_data); - - return 0; - } - - u8 RGFW_window_isMaximized(RGFW_window* win) { - assert(win != NULL); - - static Atom net_wm_state = 0; - static Atom net_wm_state_maximized_horz = 0; - static Atom net_wm_state_maximized_vert = 0; - - if (net_wm_state == 0) { - net_wm_state = XInternAtom(win->src.display, "_NET_WM_STATE", False); - net_wm_state_maximized_vert = XInternAtom(win->src.display, "_NET_WM_STATE_MAXIMIZED_VERT", False); - net_wm_state_maximized_horz = XInternAtom(win->src.display, "_NET_WM_STATE_MAXIMIZED_HORZ", False); - } - - Atom actual_type; - i32 actual_format; - unsigned long nitems, bytes_after; - unsigned char* prop_data; - - i16 status = XGetWindowProperty(win->src.display, (Window) win->src.window, net_wm_state, 0, 1024, False, - XA_ATOM, &actual_type, &actual_format, - &nitems, &bytes_after, &prop_data); - - if (status != Success) { - if (prop_data != NULL) - XFree(prop_data); - return 0; } - Atom* atoms = (Atom*) prop_data; - u64 i; - for (i = 0; i < nitems; ++i) { - if (atoms[i] == net_wm_state_maximized_horz || - atoms[i] == net_wm_state_maximized_vert) { - XFree(prop_data); - return 1; - } - } - - return 0; - } - - static void XGetSystemContentScale(Display* display, float* xscale, float* yscale) { - float xdpi = 96.f, ydpi = 96.f; - -#ifndef RGFW_NO_DPI - char* rms = XResourceManagerString(display); - XrmDatabase db = NULL; - - if (rms && db) - db = XrmGetStringDatabase(rms); - - if (db == 0) { - *xscale = xdpi / 96.f; - *yscale = ydpi / 96.f; - return; - } - - XrmValue value; - char* type = NULL; - - if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value) && type && strncmp(type, "String", 7) == 0) - xdpi = ydpi = atof(value.addr); - XrmDestroyDatabase(db); -#endif - - * xscale = xdpi / 96.f; - *yscale = ydpi / 96.f; - } - - RGFW_monitor RGFW_XCreateMonitor(i32 screen) { - RGFW_monitor monitor; - - Display* display = XOpenDisplay(NULL); - - RGFW_area size = RGFW_getScreenSize(); - - monitor.rect = RGFW_RECT(0, 0, size.w, size.h); - monitor.physW = DisplayWidthMM(display, screen); - monitor.physH = DisplayHeightMM(display, screen); - - XGetSystemContentScale(display, &monitor.scaleX, &monitor.scaleY); - XRRScreenResources* sr = XRRGetScreenResourcesCurrent(display, RootWindow(display, screen)); - - XRRCrtcInfo* ci = NULL; - int crtc = screen; - - if (sr->ncrtc > crtc) { - ci = XRRGetCrtcInfo(display, sr, sr->crtcs[crtc]); - } - - if (ci == NULL) { - float dpi_width = round((double)monitor.rect.w/(((double)monitor.physW)/25.4)); - float dpi_height = round((double)monitor.rect.h/(((double)monitor.physH)/25.4)); - - monitor.scaleX = (float) (dpi_width) / (float) 96; - monitor.scaleY = (float) (dpi_height) / (float) 96; - XRRFreeScreenResources(sr); - XCloseDisplay(display); - return monitor; - } - - XRROutputInfo* info = XRRGetOutputInfo (display, sr, sr->outputs[screen]); - monitor.physW = info->mm_width; - monitor.physH = info->mm_height; - - monitor.rect.x = ci->x; - monitor.rect.y = ci->y; - monitor.rect.w = ci->width; - monitor.rect.h = ci->height; - - float dpi_width = round((double)monitor.rect.w/(((double)monitor.physW)/25.4)); - float dpi_height = round((double)monitor.rect.h/(((double)monitor.physH)/25.4)); - - monitor.scaleX = (float) (dpi_width) / (float) 96; - monitor.scaleY = (float) (dpi_height) / (float) 96; - - if (monitor.scaleX > 1 && monitor.scaleX < 1.1) - monitor.scaleX = 1; - - if (monitor.scaleY > 1 && monitor.scaleY < 1.1) - monitor.scaleY = 1; - - XRRFreeCrtcInfo(ci); - XRRFreeScreenResources(sr); - - XCloseDisplay(display); - - return monitor; - } - - RGFW_monitor RGFW_monitors[6]; - RGFW_monitor* RGFW_getMonitors(void) { - size_t i; - for (i = 0; i < (size_t)ScreenCount(RGFW_root->src.display) && i < 6; i++) - RGFW_monitors[i] = RGFW_XCreateMonitor(i); - - return RGFW_monitors; - } - - RGFW_monitor RGFW_getPrimaryMonitor(void) { - assert(RGFW_root != NULL); - - i32 primary = -1; - Window root = DefaultRootWindow(RGFW_root->src.display); - XRRScreenResources* res = XRRGetScreenResources(RGFW_root->src.display, root); - - for (int i = 0; i < res->noutput; i++) { - XRROutputInfo* output_info = XRRGetOutputInfo(RGFW_root->src.display, res, res->outputs[i]); - if (output_info->connection == RR_Connected && output_info->crtc) { - XRRCrtcInfo* crtc_info = XRRGetCrtcInfo(RGFW_root->src.display, res, output_info->crtc); - if (crtc_info->mode != None && crtc_info->x == 0 && crtc_info->y == 0) { - primary = i; - XRRFreeCrtcInfo(crtc_info); - XRRFreeOutputInfo(output_info); - break; - } - XRRFreeCrtcInfo(crtc_info); - } - XRRFreeOutputInfo(output_info); - } - - XRRFreeScreenResources(res); - - return RGFW_XCreateMonitor(primary); - } - - RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { - return RGFW_XCreateMonitor(DefaultScreen(win->src.display)); - } - - #ifdef RGFW_OPENGL - void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) { - if (win == NULL) - glXMakeCurrent((Display*) NULL, (Drawable)NULL, (GLXContext) NULL); - else - glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.ctx); - } #endif - - - void RGFW_window_swapBuffers(RGFW_window* win) { - assert(win != NULL); - - /* clear the window*/ - if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) { -#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) - #ifdef RGFW_OSMESA - RGFW_OSMesa_reorganize(); - #endif - RGFW_area area = RGFW_bufferSize; - -#ifndef RGFW_X11_DONT_CONVERT_BGR - win->src.bitmap->data = (char*) win->buffer; - u32 x, y; - for (y = 0; y < (u32)win->r.h; y++) { - for (x = 0; x < (u32)win->r.w; x++) { - u32 index = (y * 4 * area.w) + x * 4; - - u8 red = win->src.bitmap->data[index]; - win->src.bitmap->data[index] = win->buffer[index + 2]; - win->src.bitmap->data[index + 2] = red; - - } - } -#endif - XPutImage(win->src.display, (Window) win->src.window, win->src.gc, win->src.bitmap, 0, 0, 0, 0, RGFW_bufferSize.w, RGFW_bufferSize.h); -#endif - } - - if (!(win->_winArgs & RGFW_NO_GPU_RENDER)) { - #ifdef RGFW_EGL - eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface); - #elif defined(RGFW_OPENGL) - glXSwapBuffers((Display*) win->src.display, (Window) win->src.window); - #endif - } - } - - #if !defined(RGFW_EGL) - void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { - assert(win != NULL); - - #if defined(RGFW_OPENGL) - ((PFNGLXSWAPINTERVALEXTPROC) glXGetProcAddress((GLubyte*) "glXSwapIntervalEXT"))((Display*) win->src.display, (Window) win->src.window, swapInterval); - #else - RGFW_UNUSED(swapInterval); - #endif - } - #endif - - - void RGFW_window_close(RGFW_window* win) { - /* ungrab pointer if it was grabbed */ - if (win->_winArgs & RGFW_HOLD_MOUSE) - XUngrabPointer(win->src.display, CurrentTime); - - assert(win != NULL); -#ifdef RGFW_EGL - RGFW_closeEGL(win); #endif -#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) - if (win->buffer != NULL) { - XDestroyImage((XImage*) win->src.bitmap); - XFreeGC(win->src.display, win->src.gc); - } -#endif - - if ((Display*) win->src.display) { -#ifdef RGFW_OPENGL - glXDestroyContext((Display*) win->src.display, win->src.ctx); -#endif - - if (win == RGFW_root) - RGFW_root = NULL; - - if ((Drawable) win->src.window) - XDestroyWindow((Display*) win->src.display, (Drawable) win->src.window); /*!< close the window*/ - - XCloseDisplay((Display*) win->src.display); /*!< kill the display*/ - } - -#ifdef RGFW_ALLOC_DROPFILES - { - u32 i; - for (i = 0; i < RGFW_MAX_DROPS; i++) - RGFW_FREE(win->event.droppedFiles[i]); - - - RGFW_FREE(win->event.droppedFiles); - } -#endif - - RGFW_windowsOpen--; -#if !defined(RGFW_NO_X11_CURSOR_PRELOAD) && !defined(RGFW_NO_X11_CURSOR) - if (X11Cursorhandle != NULL && RGFW_windowsOpen <= 0) { - dlclose(X11Cursorhandle); - - X11Cursorhandle = NULL; - } -#endif -#if !defined(RGFW_NO_X11_XI_PRELOAD) - if (X11Xihandle != NULL && RGFW_windowsOpen <= 0) { - dlclose(X11Xihandle); - - X11Xihandle = NULL; - } -#endif - - if (RGFW_libxshape != NULL && RGFW_windowsOpen <= 0) { - dlclose(RGFW_libxshape); - RGFW_libxshape = NULL; - } - - if (RGFW_windowsOpen <= 0) { - if (RGFW_eventWait_forceStop[0] || RGFW_eventWait_forceStop[1]){ - close(RGFW_eventWait_forceStop[0]); - close(RGFW_eventWait_forceStop[1]); - } - - u8 i; - for (i = 0; i < RGFW_joystickCount; i++) - close(RGFW_joysticks[i]); - } - - /* set cleared display / window to NULL for error checking */ - win->src.display = (Display*) 0; - win->src.window = (Window) 0; - - RGFW_FREE(win); /*!< free collected window data */ - } - - -/* - End of X11 linux / unix defines -*/ - -#endif /* RGFW_X11 */ - - -/* wayland or X11 defines*/ -#if defined(RGFW_WAYLAND) || defined(RGFW_X11) -#include -#include -#include - u16 RGFW_registerJoystickF(RGFW_window* win, char* file) { - assert(win != NULL); - -#ifdef __linux__ - - i32 js = open(file, O_RDONLY); - - if (js && RGFW_joystickCount < 4) { - RGFW_joystickCount++; - - RGFW_joysticks[RGFW_joystickCount - 1] = open(file, O_RDONLY); - - u8 i; - for (i = 0; i < 16; i++) - RGFW_jsPressed[RGFW_joystickCount - 1][i] = 0; - - } - - else { -#ifdef RGFW_PRINT_ERRORS - RGFW_error = 1; - fprintf(stderr, "Error RGFW_registerJoystickF : Cannot open file %s\n", file); -#endif - } - - return RGFW_joystickCount - 1; -#endif - } - - u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber) { - assert(win != NULL); - -#ifdef __linux__ - char file[15]; - sprintf(file, "/dev/input/js%i", jsNumber); - - return RGFW_registerJoystickF(win, file); -#endif - } - - void RGFW_stopCheckEvents(void) { - RGFW_eventWait_forceStop[2] = 1; - while (1) { - const char byte = 0; - const ssize_t result = write(RGFW_eventWait_forceStop[1], &byte, 1); - if (result == 1 || result == -1) - break; - } - } - - void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) { - if (waitMS == 0) - return; - - u8 i; - - if (RGFW_eventWait_forceStop[0] == 0 || RGFW_eventWait_forceStop[1] == 0) { - if (pipe(RGFW_eventWait_forceStop) != -1) { - fcntl(RGFW_eventWait_forceStop[0], F_GETFL, 0); - fcntl(RGFW_eventWait_forceStop[0], F_GETFD, 0); - fcntl(RGFW_eventWait_forceStop[1], F_GETFL, 0); - fcntl(RGFW_eventWait_forceStop[1], F_GETFD, 0); - } - } - - struct pollfd fds[] = { - #ifdef RGFW_WAYLAND - { wl_display_get_fd(win->src.display), POLLIN, 0 }, - #else - { ConnectionNumber(win->src.display), POLLIN, 0 }, - #endif - { RGFW_eventWait_forceStop[0], POLLIN, 0 }, - #ifdef __linux__ /* blank space for 4 joystick files*/ - { -1, POLLIN, 0 }, {-1, POLLIN, 0 }, {-1, POLLIN, 0 }, {-1, POLLIN, 0} - #endif - }; - - u8 index = 2; - - #if defined(__linux__) - for (i = 0; i < RGFW_joystickCount; i++) { - if (RGFW_joysticks[i] == 0) - continue; - - fds[index].fd = RGFW_joysticks[i]; - index++; - } - #endif - - - u64 start = RGFW_getTimeNS(); - - #ifdef RGFW_WAYLAND - while (wl_display_dispatch(win->src.display) <= 0 && waitMS >= -1) { - #else - while (XPending(win->src.display) == 0 && waitMS >= -1) { - #endif - if (poll(fds, index, waitMS) <= 0) - break; - - if (waitMS > 0) { - waitMS -= (RGFW_getTimeNS() - start) / 1e+6; - } - } - - /* drain any data in the stop request */ - if (RGFW_eventWait_forceStop[2]) { - char data[64]; - (void)!read(RGFW_eventWait_forceStop[0], data, sizeof(data)); - - RGFW_eventWait_forceStop[2] = 0; - } - } - - u64 RGFW_getTimeNS(void) { - struct timespec ts = { 0 }; - clock_gettime(1, &ts); - unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec; - - return nanoSeconds; - } - - u64 RGFW_getTime(void) { - struct timespec ts = { 0 }; - clock_gettime(1, &ts); - unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec; - - return (double)(nanoSeconds) * 1e-9; - } -#endif /* end of wayland or X11 time defines*/ /* @@ -4123,35 +2642,35 @@ Wayland TODO: RGFW_windowResized the window was resized (by the user), [on webASM this means the browser was resized] RGFW_windowRefresh The window content needs to be refreshed - RGFW_dnd a file has been dropped into the window - RGFW_dnd_init + RGFW_DND a file has been dropped into the window + RGFW_DNDInit - window args: - #define RGFW_NO_RESIZE the window cannot be resized by the user - #define RGFW_ALLOW_DND the window supports drag and drop - #define RGFW_SCALE_TO_MONITOR scale the window to the screen + #define RGFW_windowNoResize the window cannot be resized by the user + #define RGFW_windowAllowDND the window supports drag and drop + #define RGFW_scaleToMonitor scale the window to the screen - other missing functions functions ("TODO wayland") (~30 functions) - fix buffer rendering weird behavior */ - #include - #include - #include - #include - #include - #include - #include - #include +#include +#include +#include +#include +#include +#include +#include +#include RGFW_window* RGFW_key_win = NULL; -void RGFW_eventPipe_push(RGFW_window* win, RGFW_Event event) { +void RGFW_eventPipe_push(RGFW_window* win, RGFW_event event) { if (win == NULL) { win = RGFW_key_win; if (win == NULL) return; } - + if (win->src.eventLen >= (i32)(sizeof(win->src.events) / sizeof(win->src.events[0]))) return; @@ -4159,28 +2678,23 @@ void RGFW_eventPipe_push(RGFW_window* win, RGFW_Event event) { win->src.eventLen += 1; } -RGFW_Event RGFW_eventPipe_pop(RGFW_window* win) { - RGFW_Event ev; +RGFW_event RGFW_eventPipe_pop(RGFW_window* win) { + RGFW_event ev; ev.type = 0; - + if (win->src.eventLen > -1) win->src.eventLen -= 1; - - if (win->src.eventLen >= 0) + + if (win->src.eventLen >= 0) ev = win->src.events[win->src.eventLen]; - return ev; + return ev; } /* wayland global garbage (wayland bad, X11 is fine (ish) (not really)) */ #include "xdg-shell.h" #include "xdg-decoration-unstable-v1.h" -struct xdg_wm_base *xdg_wm_base; -struct wl_compositor* RGFW_compositor = NULL; -struct wl_shm* shm = NULL; -struct wl_shell* RGFW_shell = NULL; -static struct wl_seat *seat = NULL; static struct xkb_context *xkb_context; static struct xkb_keymap *keymap = NULL; static struct xkb_state *xkb_state = NULL; @@ -4206,7 +2720,7 @@ b8 RGFW_wl_configured = 0; static void xdg_surface_configure_handler(void *data, struct xdg_surface *xdg_surface, uint32_t serial) -{ +{ RGFW_UNUSED(data); xdg_surface_ack_configure(xdg_surface, serial); #ifdef RGFW_DEBUG @@ -4223,8 +2737,10 @@ static void xdg_toplevel_configure_handler(void *data, struct xdg_toplevel *toplevel, int32_t width, int32_t height, struct wl_array *states) { - RGFW_UNUSED(data); RGFW_UNUSED(toplevel); RGFW_UNUSED(states) + RGFW_UNUSED(data); RGFW_UNUSED(toplevel); RGFW_UNUSED(states); + #ifdef RGFW_DEBUG fprintf(stderr, "XDG toplevel configure: %dx%d\n", width, height); + #endif } static void xdg_toplevel_close_handler(void *data, @@ -4234,11 +2750,11 @@ static void xdg_toplevel_close_handler(void *data, RGFW_window* win = (RGFW_window*)xdg_toplevel_get_user_data(toplevel); if (win == NULL) win = RGFW_key_win; - - RGFW_Event ev; + + RGFW_event ev; ev.type = RGFW_quit; - RGFW_eventPipe_push(win, ev); + RGFW_eventPipe_push(win, ev); RGFW_windowQuitCallback(win); } @@ -4247,7 +2763,9 @@ static void shm_format_handler(void *data, struct wl_shm *shm, uint32_t format) { RGFW_UNUSED(data); RGFW_UNUSED(shm); + #ifdef RGFW_DEBUG fprintf(stderr, "Format %d\n", format); + #endif } static const struct wl_shm_listener shm_listener = { @@ -4266,11 +2784,11 @@ static void pointer_enter(void *data, struct wl_pointer *pointer, uint32_t seria RGFW_window* win = (RGFW_window*)wl_surface_get_user_data(surface); RGFW_mouse_win = win; - RGFW_Event ev; + RGFW_event ev; ev.type = RGFW_mouseEnter; ev.point = win->event.point; - RGFW_eventPipe_push(win, ev); + RGFW_eventPipe_push(win, ev); RGFW_mouseNotifyCallBack(win, win->event.point, RGFW_TRUE); } @@ -4279,8 +2797,8 @@ static void pointer_leave(void *data, struct wl_pointer *pointer, uint32_t seria RGFW_window* win = (RGFW_window*)wl_surface_get_user_data(surface); if (RGFW_mouse_win == win) RGFW_mouse_win = NULL; - - RGFW_Event ev; + + RGFW_event ev; ev.type = RGFW_mouseLeave; ev.point = win->event.point; RGFW_eventPipe_push(win, ev); @@ -4290,29 +2808,29 @@ static void pointer_leave(void *data, struct wl_pointer *pointer, uint32_t seria static void pointer_motion(void *data, struct wl_pointer *pointer, uint32_t time, wl_fixed_t x, wl_fixed_t y) { RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(time); RGFW_UNUSED(x); RGFW_UNUSED(y); - assert(RGFW_mouse_win != NULL); - - RGFW_Event ev; + RGFW_ASSERT(RGFW_mouse_win != NULL); + + RGFW_event ev; ev.type = RGFW_mousePosChanged; ev.point = RGFW_POINT(wl_fixed_to_double(x), wl_fixed_to_double(y)); RGFW_eventPipe_push(RGFW_mouse_win, ev); - + RGFW_mousePosCallback(RGFW_mouse_win, RGFW_POINT(wl_fixed_to_double(x), wl_fixed_to_double(y))); } static void pointer_button(void *data, struct wl_pointer *pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(time); RGFW_UNUSED(serial); - assert(RGFW_mouse_win != NULL); + RGFW_ASSERT(RGFW_mouse_win != NULL); u32 b = (button - 0x110) + 1; /* flip right and middle button codes */ if (b == 2) b = 3; else if (b == 3) b = 2; - + RGFW_mouseButtons[b].prev = RGFW_mouseButtons[b].current; RGFW_mouseButtons[b].current = state; - RGFW_Event ev; + RGFW_event ev; ev.type = RGFW_mouseButtonPressed + state; ev.button = b; RGFW_eventPipe_push(RGFW_mouse_win, ev); @@ -4321,11 +2839,11 @@ static void pointer_button(void *data, struct wl_pointer *pointer, uint32_t seri } static void pointer_axis(void *data, struct wl_pointer *pointer, uint32_t time, uint32_t axis, wl_fixed_t value) { RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(time); RGFW_UNUSED(axis); - assert(RGFW_mouse_win != NULL); + RGFW_ASSERT(RGFW_mouse_win != NULL); double scroll = wl_fixed_to_double(value); - RGFW_Event ev; + RGFW_event ev; ev.type = RGFW_mouseButtonPressed; ev.button = RGFW_mouseScrollUp + (scroll < 0); RGFW_eventPipe_push(RGFW_mouse_win, ev); @@ -4342,18 +2860,18 @@ static void keyboard_keymap (void *data, struct wl_keyboard *keyboard, uint32_t char *keymap_string = mmap (NULL, size, PROT_READ, MAP_SHARED, fd, 0); xkb_keymap_unref (keymap); keymap = xkb_keymap_new_from_string (xkb_context, keymap_string, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); - + munmap (keymap_string, size); close (fd); xkb_state_unref (xkb_state); xkb_state = xkb_state_new (keymap); } -static void keyboard_enter (void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys) { +static void keyboard_enter (void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys) { RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial); RGFW_UNUSED(keys); RGFW_key_win = (RGFW_window*)wl_surface_get_user_data(surface); - RGFW_Event ev; + RGFW_event ev; ev.type = RGFW_focusIn; ev.inFocus = RGFW_TRUE; RGFW_key_win->event.inFocus = RGFW_TRUE; @@ -4362,14 +2880,14 @@ static void keyboard_enter (void *data, struct wl_keyboard *keyboard, uint32_t s RGFW_focusCallback(RGFW_key_win, RGFW_TRUE); } -static void keyboard_leave (void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface) { +static void keyboard_leave (void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface) { RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial); RGFW_window* win = (RGFW_window*)wl_surface_get_user_data(surface); if (RGFW_key_win == win) - RGFW_key_win = NULL; + RGFW_key_win = NULL; - RGFW_Event ev; + RGFW_event ev; ev.type = RGFW_focusOut; ev.inFocus = RGFW_FALSE; win->event.inFocus = RGFW_FALSE; @@ -4378,30 +2896,29 @@ static void keyboard_leave (void *data, struct wl_keyboard *keyboard, uint32_t s RGFW_focusCallback(win, RGFW_FALSE); } static void keyboard_key (void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) { - RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial); RGFW_UNUSED(time); + RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial); RGFW_UNUSED(time); - assert(RGFW_key_win != NULL); + RGFW_ASSERT(RGFW_key_win != NULL); - xkb_keysym_t keysym = xkb_state_key_get_one_sym (xkb_state, key+8); - char name[16]; - xkb_keysym_get_name(keysym, name, 16); + xkb_keysym_t keysym = xkb_state_key_get_one_sym(xkb_state, key + 8); - u32 RGFW_key = RGFW_apiKeyCodeToRGFW(key); + u32 RGFW_key = RGFW_apiKeyToRGFW(key + 8); RGFW_keyboard[RGFW_key].prev = RGFW_keyboard[RGFW_key].current; RGFW_keyboard[RGFW_key].current = state; - RGFW_Event ev; + RGFW_event ev; ev.type = RGFW_keyPressed + state; - ev.keyCode = RGFW_key; - strcpy(ev.keyName, name); + ev.key = RGFW_key; + ev.keyChar = (u8)keysym; + ev.repeat = RGFW_isHeld(RGFW_key_win, RGFW_key); RGFW_eventPipe_push(RGFW_key_win, ev); - - RGFW_updateLockState(RGFW_key_win, xkb_keymap_mod_get_index(keymap, "Lock"), xkb_keymap_mod_get_index(keymap, "Mod2")); - RGFW_keyCallback(RGFW_key_win, RGFW_key, name, RGFW_key_win->event.lockState, state); + RGFW_updateKeyMods(RGFW_key_win, xkb_keymap_mod_get_index(keymap, "Lock"), xkb_keymap_mod_get_index(keymap, "Mod2")); + + RGFW_keyCallback(RGFW_key_win, RGFW_key, (u8)keysym, RGFW_key_win->event.keyMod, state); } static void keyboard_modifiers (void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) { - RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial); RGFW_UNUSED(time); + RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial); RGFW_UNUSED(time); xkb_state_update_mask (xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group); } static struct wl_keyboard_listener keyboard_listener = {&keyboard_keymap, &keyboard_enter, &keyboard_leave, &keyboard_key, &keyboard_modifiers, (void*)&RGFW_doNothing}; @@ -4424,23 +2941,23 @@ static void wl_global_registry_handler(void *data, struct wl_registry *registry, uint32_t id, const char *interface, uint32_t version) { - RGFW_UNUSED(data); RGFW_UNUSED(version); - - if (strcmp(interface, "wl_compositor") == 0) { - RGFW_compositor = wl_registry_bind(registry, + RGFW_window* win = (RGFW_window*)data; + RGFW_UNUSED(version); + if (RGFW_STRNCMP(interface, "wl_compositor", 16) == 0) { + win->src.compositor = wl_registry_bind(registry, id, &wl_compositor_interface, 4); - } else if (strcmp(interface, "xdg_wm_base") == 0) { - xdg_wm_base = wl_registry_bind(registry, + } else if (RGFW_STRNCMP(interface, "xdg_wm_base", 12) == 0) { + win->src.xdg_wm_base = wl_registry_bind(registry, id, &xdg_wm_base_interface, 1); - } else if (strcmp(interface, zxdg_decoration_manager_v1_interface.name) == 0) { + } else if (RGFW_STRNCMP(interface, zxdg_decoration_manager_v1_interface.name, 255) == 0) { decoration_manager = wl_registry_bind(registry, id, &zxdg_decoration_manager_v1_interface, 1); - } else if (strcmp(interface, "wl_shm") == 0) { - shm = wl_registry_bind(registry, + } else if (RGFW_STRNCMP(interface, "wl_shm", 7) == 0) { + win->src.shm = wl_registry_bind(registry, id, &wl_shm_interface, 1); - wl_shm_add_listener(shm, &shm_listener, NULL); - } else if (strcmp(interface,"wl_seat") == 0) { - seat = wl_registry_bind(registry, id, &wl_seat_interface, 1); - wl_seat_add_listener(seat, &seat_listener, NULL); + wl_shm_add_listener(win->src.shm, &shm_listener, NULL); + } else if (RGFW_STRNCMP(interface,"wl_seat", 8) == 0) { + win->src.seat = wl_registry_bind(registry, id, &wl_seat_interface, 1); + wl_seat_add_listener(win->src.seat, &seat_listener, NULL); } else { @@ -4450,9 +2967,9 @@ static void wl_global_registry_handler(void *data, #endif } - #ifdef RGFW_DEBUG - printf("registered %s\n", interface); - #endif + #ifdef RGFW_DEBUG + printf("registered %s\n", interface); + #endif } static void wl_global_registry_remove(void *data, struct wl_registry *registry, uint32_t name) { RGFW_UNUSED(data); RGFW_UNUSED(registry); RGFW_UNUSED(name); } @@ -4476,7 +2993,9 @@ static void decoration_handle_configure(void *data, struct zxdg_toplevel_decoration_v1 *decoration, enum zxdg_toplevel_decoration_v1_mode mode) { RGFW_UNUSED(data); RGFW_UNUSED(decoration); + #ifdef RGFW_DEBUG printf("Using %s\n", get_mode_name(mode)); + #endif RGFW_current_mode = mode; } @@ -4494,12 +3013,18 @@ static void randname(char *buf) { } } +size_t wl_stringlen(char* name) { + size_t i = 0; + for (i; name[i]; i++); + return i; +} + static int anonymous_shm_open(void) { char name[] = "/RGFW-wayland-XXXXXX"; int retries = 100; do { - randname(name + strlen(name) - 6); + randname(name + wl_stringlen(name) - 6); --retries; // shm_open guarantees that O_CLOEXEC is set @@ -4528,25 +3053,13 @@ int create_shm_file(off_t size) { } static void wl_surface_frame_done(void *data, struct wl_callback *cb, uint32_t time) { + RGFW_UNUSED(data); RGFW_UNUSED(cb); RGFW_UNUSED(time); + #ifdef RGFW_BUFFER RGFW_window* win = (RGFW_window*)data; - if ((win->_winArgs & RGFW_NO_CPU_RENDER)) - return; + if ((win->_flags & RGFW_NO_CPU_RENDER)) + return; - #ifndef RGFW_X11_DONT_CONVERT_BGR - u32 x, y; - for (y = 0; y < (u32)win->r.h; y++) { - for (x = 0; x < (u32)win->r.w; x++) { - u32 index = (y * 4 * win->r.w) + x * 4; - - u8 red = win->buffer[index]; - win->buffer[index] = win->buffer[index + 2]; - win->buffer[index + 2] = red; - - } - } - #endif - wl_surface_attach(win->src.surface, win->src.wl_buffer, 0, 0); wl_surface_damage_buffer(win->src.surface, 0, 0, win->r.w, win->r.h); wl_surface_commit(win->src.surface); @@ -4556,405 +3069,2162 @@ static void wl_surface_frame_done(void *data, struct wl_callback *cb, uint32_t t static const struct wl_callback_listener wl_surface_frame_listener = { .done = wl_surface_frame_done, }; +#endif /* RGFW_WAYLAND */ +#if !defined(RGFW_NO_X11) && defined(RGFW_WAYLAND) +void RGFW_useWayland(b8 wayland) { RGFW_useWaylandBool = wayland; } +#define RGFW_GOTO_WAYLAND(fallback) if (RGFW_useWaylandBool && fallback == 0) goto wayland +#else +#define RGFW_GOTO_WAYLAND(fallback) +void RGFW_useWayland(b8 wayland) { RGFW_UNUSED(wayland); } +#endif + +/* + End of Wayland defines +*/ + +/* - /* normal wayland RGFW stuff */ +Start of Linux / Unix defines + + +*/ + +#ifdef RGFW_UNIX +#if !defined(RGFW_NO_X11_CURSOR) && defined(RGFW_X11) +#include +#endif + +#include + +#ifndef RGFW_NO_DPI +#include +#include +#endif + +#include +#include +#include +#include + +#include /* for converting keycode to string */ +#include /* for hiding */ +#include +#include +#include + +#include /* for data limits (mainly used in drag and drop functions) */ +#include + + +#if defined(__linux__) && !defined(RGFW_NO_LINUX) +#include +#endif + +u8 RGFW_mouseIconSrc[] = { XC_arrow, XC_left_ptr, XC_xterm, XC_crosshair, XC_hand2, XC_sb_h_double_arrow, XC_sb_v_double_arrow, XC_bottom_left_corner, XC_bottom_right_corner, XC_fleur, XC_X_cursor}; +/*atoms needed for drag and drop*/ +Atom XdndAware, XdndTypeList, XdndSelection, XdndEnter, XdndPosition, XdndStatus, XdndLeave, XdndDrop, XdndFinished, XdndActionCopy, XtextPlain, XtextUriList; +Atom RGFW_XUTF8_STRING = 0; + +Atom wm_delete_window = 0, RGFW_XCLIPBOARD = 0; + +#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD) + typedef XcursorImage* (*PFN_XcursorImageCreate)(int, int); + typedef void (*PFN_XcursorImageDestroy)(XcursorImage*); + typedef Cursor(*PFN_XcursorImageLoadCursor)(Display*, const XcursorImage*); +#endif +#ifdef RGFW_OPENGL + typedef GLXContext(*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*); +#endif + +#if !defined(RGFW_NO_X11_XI_PRELOAD) + typedef int (* PFN_XISelectEvents)(Display*,Window,XIEventMask*,int); + PFN_XISelectEvents XISelectEventsSRC = NULL; + #define XISelectEvents XISelectEventsSRC + + void* X11Xihandle = NULL; +#endif + +#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD) + PFN_XcursorImageLoadCursor XcursorImageLoadCursorSRC = NULL; + PFN_XcursorImageCreate XcursorImageCreateSRC = NULL; + PFN_XcursorImageDestroy XcursorImageDestroySRC = NULL; + + #define XcursorImageLoadCursor XcursorImageLoadCursorSRC + #define XcursorImageCreate XcursorImageCreateSRC + #define XcursorImageDestroy XcursorImageDestroySRC + + void* X11Cursorhandle = NULL; +#endif + +u32 RGFW_windowsOpen = 0; + +#if defined(RGFW_OPENGL) && !defined(RGFW_EGL) + void* RGFW_getProcAddress(const char* procname) { return (void*) glXGetProcAddress((GLubyte*) procname); } +#endif + +RGFWDEF void RGFW_init_buffer(RGFW_window* win, XVisualInfo* vi); +void RGFW_init_buffer(RGFW_window* win, XVisualInfo* vi) { + RGFW_GOTO_WAYLAND(0); + + #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) + #ifdef RGFW_X11 + if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0) + RGFW_bufferSize = RGFW_getScreenSize(); + + win->buffer = (u8*)RGFW_alloc(RGFW_bufferSize.w * RGFW_bufferSize.h * 4); + win->_flags |= RGFW_BUFFER_ALLOC; + + #ifdef RGFW_DEBUG + printf("RGFW INFO: createing a 4 channel %i by %i buffer\n", RGFW_bufferSize.w, RGFW_bufferSize.h); + #endif + + #ifdef RGFW_OSMESA + win->src.ctx = OSMesaCreateContext(OSMESA_BGRA, NULL); + OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, RGFW_bufferSize.w, RGFW_bufferSize.h); + #endif + + win->src.bitmap = XCreateImage( + win->src.display, XDefaultVisual(win->src.display, vi->screen), + vi->depth, + ZPixmap, 0, NULL, RGFW_bufferSize.w, RGFW_bufferSize.h, + 32, 0 + ); + + win->src.gc = XCreateGC(win->src.display, win->src.window, 0, NULL); + #endif + #ifdef RGFW_WAYLAND + wayland: + size_t size = win->r.w * win->r.h * 4; + int fd = create_shm_file(size); + if (fd < 0) { + fprintf(stderr, "Failed to create a buffer. size: %ld\n", size); + exit(1); + } + + if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0) + RGFW_bufferSize = RGFW_getScreenSize(); + + win->buffer = (u8*)RGFW_alloc(RGFW_bufferSize.w * RGFW_bufferSize.h * 4); + win->src.buffer = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (win->src.buffer == MAP_FAILED) { + fprintf(stderr, "mmap failed!\n"); + close(fd); + exit(1); + } + + win->_flags |= RGFW_BUFFER_ALLOC; + + struct wl_shm_pool* pool = wl_shm_create_pool(win->src.shm, fd, size); + win->src.wl_buffer = wl_shm_pool_create_buffer(pool, 0, win->r.w, win->r.h, win->r.w * 4, + WL_SHM_FORMAT_ARGB8888); + wl_shm_pool_destroy(pool); + + close(fd); + + wl_surface_attach(win->src.surface, win->src.wl_buffer, 0, 0); + wl_surface_commit(win->src.surface); + + u8 color[] = {0x00, 0x00, 0x00, 0xFF}; + + size_t i; + for (i = 0; i < RGFW_bufferSize.w * RGFW_bufferSize.h * 4; i += 4) { + RGFW_MEMCPY(&win->buffer[i], color, 4); + } + + RGFW_MEMCPY(win->src.buffer, win->buffer, win->r.w * win->r.h * 4); + + #if defined(RGFW_OSMESA) + win->src.ctx = OSMesaCreateContext(OSMESA_BGRA, NULL); + OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, RGFW_bufferSize.w, RGFW_bufferSize.h); + #endif + #endif + #else + wayland: + RGFW_UNUSED(win); + RGFW_UNUSED(vi); + #endif +} + +#define RGFW_LOAD_ATOM(name) \ + static Atom name = 0; \ + if (name == 0) name = XInternAtom(RGFW_root->src.display, #name, False); + +void RGFW_window_setBorder(RGFW_window* win, u8 border) { + RGFW_GOTO_WAYLAND(0); + #ifdef RGFW_X11 + RGFW_LOAD_ATOM(_MOTIF_WM_HINTS); + + struct __x11WindowHints { + unsigned long flags, functions, decorations, status; + long input_mode; + } hints; + hints.flags = (1L << 1); + hints.decorations = border; + + XChangeProperty( + win->src.display, win->src.window, + _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, + 32, PropModeReplace, (u8*)&hints, 5 + ); + #endif + #ifdef RGFW_WAYLAND + wayland: + #endif +} + +void RGFW_releaseCursor(RGFW_window* win) { +RGFW_GOTO_WAYLAND(0); +#ifdef RGFW_X11 + XUngrabPointer(win->src.display, CurrentTime); + + /* disable raw input */ + unsigned char mask[] = { 0 }; + XIEventMask em; + em.deviceid = XIAllMasterDevices; + em.mask_len = sizeof(mask); + em.mask = mask; + + XISelectEvents(win->src.display, XDefaultRootWindow(win->src.display), &em, 1); +#endif +#ifdef RGFW_WAYLAND + wayland: +#endif +} + +void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) { +RGFW_GOTO_WAYLAND(0); +#ifdef RGFW_X11 + /* enable raw input */ + unsigned char mask[XIMaskLen(XI_RawMotion)] = { 0 }; + XISetMask(mask, XI_RawMotion); + + XIEventMask em; + em.deviceid = XIAllMasterDevices; + em.mask_len = sizeof(mask); + em.mask = mask; + + XISelectEvents(win->src.display, XDefaultRootWindow(win->src.display), &em, 1); + + XGrabPointer(win->src.display, win->src.window, True, PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); + RGFW_window_moveMouse(win, RGFW_POINT(win->r.x + (i32)(r.w / 2), win->r.y + (i32)(r.h / 2))); +#endif +#ifdef RGFW_WAYLAND + wayland: +#endif +} + +#define RGFW_LOAD_LIBRARY(x, lib) if (x == NULL) x = dlopen(lib, RTLD_LAZY | RTLD_LOCAL) +#define RGFW_PROC_DEF(proc, name) if (name##SRC == NULL && proc != NULL) name##SRC = (PFN_##name)(void*)dlsym(proc, #name) + +RGFW_window* RGFW_createWindowPtr(const char* name, RGFW_rect rect, RGFW_windowFlags flags, RGFW_window* win) { + #ifdef RGFW_USE_XDL + XDL_init(); + #endif + + #if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD) + #if defined(__CYGWIN__) + RGFW_LOAD_LIBRARY(X11Cursorhandle, "libXcursor-1.so"); + #elif defined(__OpenBSD__) || defined(__NetBSD__) + RGFW_LOAD_LIBRARY(X11Cursorhandle, "libXcursor.so"); + #else + RGFW_LOAD_LIBRARY(X11Cursorhandle, "libXcursor.so.1"); + #endif + RGFW_PROC_DEF(X11Cursorhandle, XcursorImageCreate); + RGFW_PROC_DEF(X11Cursorhandle, XcursorImageDestroy); + RGFW_PROC_DEF(X11Cursorhandle, XcursorImageLoadCursor); + #endif + + #if !defined(RGFW_NO_X11_XI_PRELOAD) + #if defined(__CYGWIN__) + RGFW_LOAD_LIBRARY(X11Xihandle, "libXi-6.so"); + #elif defined(__OpenBSD__) || defined(__NetBSD__) + RGFW_LOAD_LIBRARY(X11Xihandle, "libXi.so"); + #else + RGFW_LOAD_LIBRARY(X11Xihandle, "libXi.so.6"); + #endif + RGFW_PROC_DEF(X11Xihandle, XISelectEvents); + #endif + + XInitThreads(); /*!< init X11 threading*/ + + if (flags & RGFW_windowOpenglSoftware) + setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1); + + RGFW_window_basic_init(win, rect, flags); + +#ifdef RGFW_WAYLAND + win->src.compositor = NULL; +#endif + RGFW_GOTO_WAYLAND(0); +#ifdef RGFW_X11 + u64 event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask | FocusChangeMask | LeaveWindowMask | EnterWindowMask | ExposureMask; /*!< X11 events accepted*/ + + #if defined(RGFW_OPENGL) && !defined(RGFW_EGL) + u32* visual_attribs = (u32*)RGFW_initFormatAttribs(flags & RGFW_windowOpenglSoftware); + i32 fbcount; + GLXFBConfig* fbc = glXChooseFBConfig(win->src.display, DefaultScreen(win->src.display), (i32*) visual_attribs, &fbcount); + + i32 best_fbc = -1; + + if (fbcount == 0) { + #ifdef RGFW_DEBUG + fprintf(stderr, "Failed to find any valid GLX visual configs\n"); + #endif + return NULL; + } + + u32 i; + for (i = 0; i < (u32)fbcount; i++) { + XVisualInfo* vi = glXGetVisualFromFBConfig(win->src.display, fbc[i]); + if (vi == NULL) + continue; + + XFree(vi); + + i32 samp_buf, samples; + glXGetFBConfigAttrib(win->src.display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf); + glXGetFBConfigAttrib(win->src.display, fbc[i], GLX_SAMPLES, &samples); + + if ((!(flags & RGFW_windowTransparent) || vi->depth == 32) && + (best_fbc < 0 || samp_buf) && (samples == RGFW_SAMPLES || best_fbc == -1)) { + best_fbc = i; + } + } + + if (best_fbc == -1) { + #ifdef RGFW_DEBUG + fprintf(stderr, "Failed to get a valid GLX visual\n"); + #endif + return NULL; + } + + GLXFBConfig bestFbc = fbc[best_fbc]; + + /* Get a visual */ + XVisualInfo* vi = glXGetVisualFromFBConfig(win->src.display, bestFbc); + + XFree(fbc); + #else + XVisualInfo viNorm; + + viNorm.visual = DefaultVisual(win->src.display, DefaultScreen(win->src.display)); + + viNorm.depth = 0; + XVisualInfo* vi = &viNorm; + + XMatchVisualInfo(win->src.display, DefaultScreen(win->src.display), 32, TrueColor, vi); /*!< for RGBA backgrounds*/ + #endif + /* make X window attrubutes*/ + XSetWindowAttributes swa; + Colormap cmap; + + swa.colormap = cmap = XCreateColormap(win->src.display, + DefaultRootWindow(win->src.display), + vi->visual, AllocNone); + + swa.background_pixmap = None; + swa.border_pixel = 0; + swa.event_mask = event_mask; + + swa.background_pixel = 0; + + /* create the window*/ + win->src.window = XCreateWindow(win->src.display, DefaultRootWindow(win->src.display), win->r.x, win->r.y, win->r.w, win->r.h, + 0, vi->depth, InputOutput, vi->visual, + CWColormap | CWBorderPixel | CWBackPixel | CWEventMask, &swa); + + XFreeColors(win->src.display, cmap, NULL, 0, 0); + + #if defined(RGFW_OPENGL) && !defined(RGFW_EGL) + XFree(vi); + #endif - RGFW_area RGFW_getScreenSize(void) { - RGFW_area area = {}; + // In your .desktop app, if you set the property + // StartupWMClass=RGFW that will assoicate the launcher icon + // with your application - robrohan + + if (RGFW_className == NULL) + RGFW_className = (char*)name; + + XClassHint hint; + hint.res_class = (char*)RGFW_className; + hint.res_name = (char*)name; // just use the window name as the app name + XSetClassHint(win->src.display, win->src.window, &hint); + + if ((flags & RGFW_windowNoInitAPI) == 0) { + #if defined(RGFW_OPENGL) && !defined(RGFW_EGL) /* This is the second part of setting up opengl. This is where we ask OpenGL for a specific version. */ + i32 context_attribs[7] = { 0, 0, 0, 0, 0, 0, 0 }; + context_attribs[0] = GLX_CONTEXT_PROFILE_MASK_ARB; + if (RGFW_profile == RGFW_glCore) + context_attribs[1] = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; + else + context_attribs[1] = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; + + if (RGFW_majorVersion || RGFW_minorVersion) { + context_attribs[2] = GLX_CONTEXT_MAJOR_VERSION_ARB; + context_attribs[3] = RGFW_majorVersion; + context_attribs[4] = GLX_CONTEXT_MINOR_VERSION_ARB; + context_attribs[5] = RGFW_minorVersion; + } + + glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0; + glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) + glXGetProcAddressARB((GLubyte*) "glXCreateContextAttribsARB"); + + GLXContext ctx = NULL; if (RGFW_root != NULL) - /* this isn't right but it's here for buffers */ - area = RGFW_AREA(RGFW_root->r.w, RGFW_root->r.h); - - /* TODO wayland */ - return area; - } - - void RGFW_releaseCursor(RGFW_window* win) { - RGFW_UNUSED(win); + ctx = RGFW_root->src.ctx; + + win->src.ctx = glXCreateContextAttribsARB(win->src.display, bestFbc, ctx, True, context_attribs); + #endif + + RGFW_init_buffer(win, vi); } - void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) { - RGFW_UNUSED(win); RGFW_UNUSED(r); + #ifndef RGFW_NO_MONITOR + if (flags & RGFW_windowScaleToMonitor) + RGFW_window_scaleToMonitor(win); + #endif - /* TODO wayland */ + if (flags & RGFW_windowCenter) { + RGFW_area screenR = RGFW_getScreenSize(); + RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2)); } + if (flags & RGFW_windowNoResize) { /* make it so the user can't resize the window*/ + XSizeHints sh; + sh.flags = (1L << 4) | (1L << 5); + sh.min_width = sh.max_width = win->r.w; + sh.min_height = sh.max_height = win->r.h; - RGFWDEF void RGFW_init_buffer(RGFW_window* win); - void RGFW_init_buffer(RGFW_window* win) { - #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) - size_t size = win->r.w * win->r.h * 4; - int fd = create_shm_file(size); - if (fd < 0) { - fprintf(stderr, "Failed to create a buffer. size: %ld\n", size); - exit(1); - } + XSetWMSizeHints(win->src.display, (Drawable) win->src.window, &sh, XA_WM_NORMAL_HINTS); - win->buffer = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (win->buffer == MAP_FAILED) { - fprintf(stderr, "mmap failed!\n"); - close(fd); - exit(1); - } + win->_flags |= RGFW_windowNoResize; + } - struct wl_shm_pool* pool = wl_shm_create_pool(shm, fd, size); - win->src.wl_buffer = wl_shm_pool_create_buffer(pool, 0, win->r.w, win->r.h, win->r.w * 4, - WL_SHM_FORMAT_ARGB8888); - wl_shm_pool_destroy(pool); + if (flags & RGFW_windowNoBorder) { + RGFW_window_setBorder(win, 0); + } - close(fd); - - wl_surface_attach(win->src.surface, win->src.wl_buffer, 0, 0); - wl_surface_commit(win->src.surface); + XSelectInput(win->src.display, (Drawable) win->src.window, event_mask); /*!< tell X11 what events we want*/ - u8 color[] = {0x00, 0x00, 0x00, 0xFF}; + /* make it so the user can't close the window until the program does*/ + if (wm_delete_window == 0) { + wm_delete_window = XInternAtom(win->src.display, "WM_DELETE_WINDOW", False); + RGFW_XUTF8_STRING = XInternAtom(win->src.display, "UTF8_STRING", False); + RGFW_XCLIPBOARD = XInternAtom(win->src.display, "CLIPBOARD", False); + } - size_t i; - for (i = 0; i < size; i += 4) { - memcpy(&win->buffer[i], color, 4); - } - - #if defined(RGFW_OSMESA) - win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL); - OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h); - #endif - #else - RGFW_UNUSED(win); + XSetWMProtocols(win->src.display, (Drawable) win->src.window, &wm_delete_window, 1); + + /* connect the context to the window*/ + #if defined(RGFW_OPENGL) && !defined(RGFW_EGL) + if ((flags & RGFW_windowNoInitAPI) == 0) + glXMakeCurrent(win->src.display, (Drawable) win->src.window, (GLXContext) win->src.ctx); + #endif + + /* set the background*/ + RGFW_window_setName(win, name); + + XMapWindow(win->src.display, (Drawable) win->src.window); /* draw the window*/ + XMoveWindow(win->src.display, (Drawable) win->src.window, win->r.x, win->r.y); /*!< move the window to it's proper cords*/ + + if (flags & RGFW_windowAllowDND) { /* init drag and drop atoms and turn on drag and drop for this window */ + win->_flags |= RGFW_windowAllowDND; + + XdndTypeList = XInternAtom(win->src.display, "XdndTypeList", False); + XdndSelection = XInternAtom(win->src.display, "XdndSelection", False); + + /* client messages */ + XdndEnter = XInternAtom(win->src.display, "XdndEnter", False); + XdndPosition = XInternAtom(win->src.display, "XdndPosition", False); + XdndStatus = XInternAtom(win->src.display, "XdndStatus", False); + XdndLeave = XInternAtom(win->src.display, "XdndLeave", False); + XdndDrop = XInternAtom(win->src.display, "XdndDrop", False); + XdndFinished = XInternAtom(win->src.display, "XdndFinished", False); + + /* actions */ + XdndActionCopy = XInternAtom(win->src.display, "XdndActionCopy", False); + + XtextUriList = XInternAtom(win->src.display, "text/uri-list", False); + XtextPlain = XInternAtom(win->src.display, "text/plain", False); + + XdndAware = XInternAtom(win->src.display, "XdndAware", False); + const u8 version = 5; + + XChangeProperty(win->src.display, win->src.window, + XdndAware, 4, 32, + PropModeReplace, &version, 1); /*!< turns on drag and drop */ + } + + #ifdef RGFW_EGL + if ((flags & RGFW_windowNoInitAPI) == 0) + RGFW_createOpenGLContext(win); + #endif + #ifdef RGFW_DEBUG + printf("RGFW INFO: a window with a rect of {%i, %i, %i, %i} \n", win->r.x, win->r.y, win->r.w, win->r.h); + #endif + RGFW_window_setMouseDefault(win); + RGFW_windowsOpen++; + return win; /*return newly created window*/ +#endif +#ifdef RGFW_WAYLAND + wayland: + fprintf(stderr, "Warning: RGFW Wayland support is experimental\n"); + + win->src.wl_display = wl_display_connect(NULL); + if (win->src.wl_display == NULL) { + #ifdef RGFW_DEBUG + fprintf(stderr, "Failed to load Wayland display\n"); #endif - } - - - RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) { - RGFW_window* win = RGFW_window_basic_init(rect, args); - - fprintf(stderr, "Warning: RGFW Wayland support is experimental\n"); - - win->src.display = wl_display_connect(NULL); - if (win->src.display == NULL) { - #ifdef RGFW_DEBUG - fprintf(stderr, "Failed to load Wayland display\n"); - #endif - return NULL; - } - - struct wl_registry *registry = wl_display_get_registry(win->src.display); - wl_registry_add_listener(registry, ®istry_listener, NULL); - - wl_display_dispatch(win->src.display); - wl_display_roundtrip(win->src.display); - - if (RGFW_compositor == NULL) { - #ifdef RGFW_DEBUG - fprintf(stderr, "Can't find compositor.\n"); - #endif - - return NULL; - } - - if (RGFW_wl_cursor_theme == NULL) { - RGFW_wl_cursor_theme = wl_cursor_theme_load(NULL, 24, shm); - RGFW_cursor_surface = wl_compositor_create_surface(RGFW_compositor); - - struct wl_cursor* cursor = wl_cursor_theme_get_cursor(RGFW_wl_cursor_theme, "left_ptr"); - RGFW_cursor_image = cursor->images[0]; - struct wl_buffer* cursor_buffer = wl_cursor_image_get_buffer(RGFW_cursor_image); - - wl_surface_attach(RGFW_cursor_surface, cursor_buffer, 0, 0); - wl_surface_commit(RGFW_cursor_surface); - } - - if (RGFW_root == NULL) - xdg_wm_base_add_listener(xdg_wm_base, &xdg_wm_base_listener, NULL); - - xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); - - win->src.surface = wl_compositor_create_surface(RGFW_compositor); - wl_surface_set_user_data(win->src.surface, win); - - win->src.xdg_surface = xdg_wm_base_get_xdg_surface(xdg_wm_base, win->src.surface); - xdg_surface_add_listener(win->src.xdg_surface, &xdg_surface_listener, NULL); - - xdg_wm_base_set_user_data(xdg_wm_base, win); - - win->src.xdg_toplevel = xdg_surface_get_toplevel(win->src.xdg_surface); - xdg_toplevel_set_user_data(win->src.xdg_toplevel, win); - xdg_toplevel_set_title(win->src.xdg_toplevel, name); - xdg_toplevel_add_listener(win->src.xdg_toplevel, &xdg_toplevel_listener, NULL); - - xdg_surface_set_window_geometry(win->src.xdg_surface, 0, 0, win->r.w, win->r.h); - - if (!(args & RGFW_NO_BORDER)) { - win->src.decoration = zxdg_decoration_manager_v1_get_toplevel_decoration( - decoration_manager, win->src.xdg_toplevel); - } - - if (args & RGFW_CENTER) { - RGFW_area screenR = RGFW_getScreenSize(); - RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2)); - } - - if (args & RGFW_OPENGL_SOFTWARE) - setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1); - - wl_display_roundtrip(win->src.display); - - wl_surface_commit(win->src.surface); - - /* wait for the surface to be configured */ - while (wl_display_dispatch(win->src.display) != -1 && !RGFW_wl_configured) { } - - - #ifdef RGFW_OPENGL - if ((args & RGFW_NO_INIT_API) == 0) { - win->src.window = wl_egl_window_create(win->src.surface, win->r.w, win->r.h); - RGFW_createOpenGLContext(win); - } - #endif - - RGFW_init_buffer(win); - - struct wl_callback* callback = wl_surface_frame(win->src.surface); - wl_callback_add_listener(callback, &wl_surface_frame_listener, win); - wl_surface_commit(win->src.surface); - - if (args & RGFW_HIDE_MOUSE) { - RGFW_window_showMouse(win, 0); - } - - if (RGFW_root == NULL) { - RGFW_root = win; - } - - win->src.eventIndex = 0; - win->src.eventLen = 0; - - return win; - } - - RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) { - if (win->_winArgs & RGFW_WINDOW_HIDE) - return NULL; - - if (win->src.eventIndex == 0) { - if (wl_display_roundtrip(win->src.display) == -1) { - return NULL; - } - RGFW_resetKey(); - } - - #ifdef __linux__ - RGFW_Event* event = RGFW_linux_updateJoystick(win); - if (event != NULL) - return event; + #ifdef RGFW_X11 + fprintf(stderr, "Falling back to X11\n"); + RGFW_useWayland(0); + return RGFW_createWindowPtr(name, rect, flags, win); #endif - - if (win->src.eventLen == 0) { - return NULL; + return NULL; + } + + + #ifdef RGFW_X11 + XSetWindowAttributes attributes; + attributes.background_pixel = 0; + attributes.override_redirect = True; + + win->src.window = XCreateWindow(win->src.display, DefaultRootWindow(win->src.display), 0, 0, 1, 1, 0, CopyFromParent, InputOutput, CopyFromParent, + CWBackPixel | CWOverrideRedirect, &attributes); + + XMapWindow(win->src.display, win->src.window); + XFlush(win->src.display); + if (wm_delete_window == 0) { + wm_delete_window = XInternAtom(win->src.display, "WM_DELETE_WINDOW", False); + RGFW_XUTF8_STRING = XInternAtom(win->src.display, "UTF8_STRING", False); + RGFW_XCLIPBOARD = XInternAtom(win->src.display, "CLIPBOARD", False); } + #endif - RGFW_Event ev = RGFW_eventPipe_pop(win); - - if (ev.type == 0 || win->event.type == RGFW_quit) { - return NULL; - } - - ev.frameTime = win->event.frameTime; - ev.frameTime2 = win->event.frameTime2; - ev.inFocus = win->event.inFocus; - win->event = ev; - - return &win->event; + struct wl_registry *registry = wl_display_get_registry(win->src.wl_display); + wl_registry_add_listener(registry, ®istry_listener, win); + + wl_display_roundtrip(win->src.wl_display); + wl_display_dispatch(win->src.wl_display); + + if (win->src.compositor == NULL) { + #ifdef RGFW_DEBUG + fprintf(stderr, "Can't find compositor.\n"); + #endif + + return NULL; } + if (RGFW_wl_cursor_theme == NULL) { + RGFW_wl_cursor_theme = wl_cursor_theme_load(NULL, 24, win->src.shm); + RGFW_cursor_surface = wl_compositor_create_surface(win->src.compositor); - void RGFW_window_resize(RGFW_window* win, RGFW_area a) { - RGFW_UNUSED(win); RGFW_UNUSED(a); - - /* TODO wayland */ - } - - void RGFW_window_move(RGFW_window* win, RGFW_point v) { - RGFW_UNUSED(win); RGFW_UNUSED(v); - - /* TODO wayland */ - } - - void RGFW_window_setIcon(RGFW_window* win, u8* src, RGFW_area a, i32 channels) { - RGFW_UNUSED(win); RGFW_UNUSED(src); RGFW_UNUSED(a); RGFW_UNUSED(channels) - /* TODO wayland */ - } - - void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v) { - RGFW_UNUSED(win); RGFW_UNUSED(v); - - /* TODO wayland */ - } - - void RGFW_window_showMouse(RGFW_window* win, i8 show) { - RGFW_UNUSED(win); - - if (show) { - - } - else { - - } - - /* TODO wayland */ - } - - b8 RGFW_window_isMaximized(RGFW_window* win) { - RGFW_UNUSED(win); - /* TODO wayland */ - return 0; - } - - b8 RGFW_window_isMinimized(RGFW_window* win) { - RGFW_UNUSED(win); - /* TODO wayland */ - return 0; - } - - b8 RGFW_window_isHidden(RGFW_window* win) { - RGFW_UNUSED(win); - /* TODO wayland */ - return 0; - } - - b8 RGFW_window_isFullscreen(RGFW_window* win) { - RGFW_UNUSED(win); - /* TODO wayland */ - return 0; - } - - RGFW_point RGFW_window_getMousePoint(RGFW_window* win) { - RGFW_UNUSED(win); - /* TODO wayland */ - return RGFW_POINT(0, 0); - } - - RGFW_point RGFW_getGlobalMousePoint(void) { - /* TODO wayland */ - return RGFW_POINT(0, 0); - } - - void RGFW_window_show(RGFW_window* win) { - //wl_surface_attach(win->src.surface, win->rc., 0, 0); - wl_surface_commit(win->src.surface); - - if (win->_winArgs & RGFW_WINDOW_HIDE) - win->_winArgs ^= RGFW_WINDOW_HIDE; - } - - void RGFW_window_hide(RGFW_window* win) { - wl_surface_attach(win->src.surface, NULL, 0, 0); - wl_surface_commit(win->src.surface); - win->_winArgs |= RGFW_WINDOW_HIDE; - } - - void RGFW_window_setMouseDefault(RGFW_window* win) { - RGFW_UNUSED(win); - - RGFW_window_setMouseStandard(win, RGFW_MOUSE_NORMAL); - } - - void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) { - RGFW_UNUSED(win); - - static const char* iconStrings[] = { "left_ptr", "left_ptr", "text", "cross", "pointer", "e-resize", "n-resize", "nw-resize", "ne-resize", "all-resize", "not-allowed" }; - - struct wl_cursor* cursor = wl_cursor_theme_get_cursor(RGFW_wl_cursor_theme, iconStrings[mouse]); + struct wl_cursor* cursor = wl_cursor_theme_get_cursor(RGFW_wl_cursor_theme, "left_ptr"); RGFW_cursor_image = cursor->images[0]; struct wl_buffer* cursor_buffer = wl_cursor_image_get_buffer(RGFW_cursor_image); wl_surface_attach(RGFW_cursor_surface, cursor_buffer, 0, 0); - wl_surface_commit(RGFW_cursor_surface); - } - - void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) { - RGFW_UNUSED(win); RGFW_UNUSED(image); RGFW_UNUSED(a); RGFW_UNUSED(channels) - //struct wl_cursor* cursor = wl_cursor_theme_get_cursor(RGFW_wl_cursor_theme, iconStrings[mouse]); - //RGFW_cursor_image = image; - struct wl_buffer* cursor_buffer = wl_cursor_image_get_buffer(RGFW_cursor_image); - - wl_surface_attach(RGFW_cursor_surface, cursor_buffer, 0, 0); - wl_surface_commit(RGFW_cursor_surface); - } - - void RGFW_window_setName(RGFW_window* win, char* name) { - xdg_toplevel_set_title(win->src.xdg_toplevel, name); - } - - void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) { - RGFW_UNUSED(win); RGFW_UNUSED(passthrough); - - /* TODO wayland */ - } - - void RGFW_window_setBorder(RGFW_window* win, b8 border) { - RGFW_UNUSED(win); RGFW_UNUSED(border); - - /* TODO wayland */ - } - - void RGFW_window_restore(RGFW_window* win) { - RGFW_UNUSED(win); - - /* TODO wayland */ - } - - void RGFW_window_minimize(RGFW_window* win) { - RGFW_UNUSED(win); - - /* TODO wayland */ - } - - void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) { - RGFW_UNUSED(win); RGFW_UNUSED(a); - - /* TODO wayland */ - } - - void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) { - RGFW_UNUSED(win); RGFW_UNUSED(a); - - /* TODO wayland */ + wl_surface_commit(RGFW_cursor_surface); } - RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { - RGFW_monitor m = {}; - RGFW_UNUSED(win); - RGFW_UNUSED(m); - /* TODO wayland */ + xdg_wm_base_add_listener(win->src.xdg_wm_base, &xdg_wm_base_listener, NULL); - return m; + xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + + win->src.surface = wl_compositor_create_surface(win->src.compositor); + wl_surface_set_user_data(win->src.surface, win); + + win->src.xdg_surface = xdg_wm_base_get_xdg_surface(win->src.xdg_wm_base, win->src.surface); + xdg_surface_add_listener(win->src.xdg_surface, &xdg_surface_listener, NULL); + + xdg_wm_base_set_user_data(win->src.xdg_wm_base, win); + + win->src.xdg_toplevel = xdg_surface_get_toplevel(win->src.xdg_surface); + xdg_toplevel_set_user_data(win->src.xdg_toplevel, win); + xdg_toplevel_set_title(win->src.xdg_toplevel, name); + xdg_toplevel_add_listener(win->src.xdg_toplevel, &xdg_toplevel_listener, NULL); + + xdg_surface_set_window_geometry(win->src.xdg_surface, 0, 0, win->r.w, win->r.h); + + if (!(flags & RGFW_windowNoBorder)) { + win->src.decoration = zxdg_decoration_manager_v1_get_toplevel_decoration( + decoration_manager, win->src.xdg_toplevel); } + if (flags & RGFW_windowCenter) { + RGFW_area screenR = RGFW_getScreenSize(); + RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2)); + } - #ifndef RGFW_EGL - void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { RGFW_UNUSED(win); RGFW_UNUSED(swapInterval); } + if (flags & RGFW_windowOpenglSoftware) + setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1); + + wl_display_roundtrip(win->src.wl_display); + + wl_surface_commit(win->src.surface); + + /* wait for the surface to be configured */ + while (wl_display_dispatch(win->src.wl_display) != -1 && !RGFW_wl_configured) { } + + #ifdef RGFW_OPENGL + if ((flags & RGFW_windowNoInitAPI) == 0) { + win->src.eglWindow = wl_egl_window_create(win->src.surface, win->r.w, win->r.h); + RGFW_createOpenGLContext(win); + } #endif - void RGFW_window_swapBuffers(RGFW_window* win) { - assert(win != NULL); + RGFW_init_buffer(win, NULL); - /* clear the window*/ - #ifdef RGFW_BUFFER - wl_surface_frame_done(win, NULL, 0); - if (!(win->_winArgs & RGFW_NO_GPU_RENDER)) - #endif - { - #ifdef RGFW_OPENGL - eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface); - #endif - } - - wl_display_flush(win->src.display); + struct wl_callback* callback = wl_surface_frame(win->src.surface); + wl_callback_add_listener(callback, &wl_surface_frame_listener, win); + wl_surface_commit(win->src.surface); + + if (flags & RGFW_windowHideMouse) { + RGFW_window_showMouse(win, 0); } - void RGFW_window_close(RGFW_window* win) { + win->src.eventIndex = 0; + win->src.eventLen = 0; + + #ifdef RGFW_DEBUG + printf("RGFW INFO: a window with a rect of {%i, %i, %i, %i} \n", win->r.x, win->r.y, win->r.w, win->r.h); + #endif + + #ifndef RGFW_NO_MONITOR + if (flags & RGFW_windowScaleToMonitor) + RGFW_window_scaleToMonitor(win); + #endif + + RGFW_window_setMouseDefault(win); + RGFW_windowsOpen++; + return win; /*return newly created window*/ +#endif +} + +RGFW_area RGFW_getScreenSize(void) { + RGFW_GOTO_WAYLAND(1); + RGFW_ASSERT(RGFW_root != NULL); + + #ifdef RGFW_X11 + Screen* scrn = DefaultScreenOfDisplay(RGFW_root->src.display); + return RGFW_AREA(scrn->width, scrn->height); + #endif + #ifdef RGFW_WAYLAND + wayland: return RGFW_AREA(RGFW_root->r.w, RGFW_root->r.h); // TODO + #endif +} + +RGFW_point RGFW_getGlobalMousePoint(void) { + RGFW_ASSERT(RGFW_root != NULL); + + RGFW_point RGFWMouse; + + i32 x, y; + u32 z; + Window window1, window2; + XQueryPointer(RGFW_root->src.display, XDefaultRootWindow(RGFW_root->src.display), &window1, &window2, &RGFWMouse.x, &RGFWMouse.y, &x, &y, &z); + + return RGFWMouse; +} + +RGFW_point RGFW_window_getMousePoint(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + + RGFW_point RGFWMouse; + + i32 x, y; + u32 z; + Window window1, window2; + XQueryPointer(win->src.display, win->src.window, &window1, &window2, &x, &y, &RGFWMouse.x, &RGFWMouse.y, &z); + + return RGFWMouse; +} + +char* RGFW_strtok(char* str, const char* delimStr) { + static char* static_str = NULL; + + if (str != NULL) + static_str = str; + + if (static_str == NULL) { + return NULL; + } + + while (*static_str != '\0') { + b8 delim = 0; + for (const char* d = delimStr; *d != '\0'; d++) { + if (*static_str == *d) { + delim = 1; + break; + } + } + if (!delim) + break; + static_str++; + } + + if (*static_str == '\0') + return NULL; + + char* token_start = static_str; + while (*static_str != '\0') { + int delim = 0; + for (const char* d = delimStr; *d != '\0'; d++) { + if (*static_str == *d) { + delim = 1; + break; + } + } + + if (delim) { + *static_str = '\0'; + static_str++; + break; + } + static_str++; + } + + return token_start; +} +int xAxis = 0, yAxis = 0; + +RGFW_event* RGFW_window_checkEvent(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + + if (win->event.type == 0) + RGFW_resetKey(); + + if (win->event.type == RGFW_quit) { + return NULL; + } + + win->event.type = 0; + + #if defined(__linux__) && !defined(RGFW_NO_LINUX) + if (RGFW_linux_updateGamepad(win)) return &win->event; + #endif + RGFW_GOTO_WAYLAND(0); +#ifdef RGFW_X11 + XPending(win->src.display); + + XEvent E; /*!< raw X11 event */ + + /* if there is no unread qued events, get a new one */ + if ((QLength(win->src.display) || XEventsQueued(win->src.display, QueuedAlready) + XEventsQueued(win->src.display, QueuedAfterReading)) + && win->event.type != RGFW_quit + ) + XNextEvent(win->src.display, &E); + else { + return NULL; + } + + win->event.type = 0; + + /* xdnd data */ + Window source = 0; + long version = 0; + i32 format = 0; + + XEvent reply = { ClientMessage }; + + switch (E.type) { + case KeyPress: + case KeyRelease: { + win->event.repeat = RGFW_FALSE; + /* check if it's a real key release */ + if (E.type == KeyRelease && XEventsQueued(win->src.display, QueuedAfterReading)) { /* get next event if there is one*/ + XEvent NE; + XPeekEvent(win->src.display, &NE); + + if (E.xkey.time == NE.xkey.time && E.xkey.keycode == NE.xkey.keycode) /* check if the current and next are both the same*/ + win->event.repeat = RGFW_TRUE; + } + + /* set event key data */ + win->event.key = RGFW_apiKeyToRGFW(E.xkey.keycode); + + KeySym sym = (KeySym)XkbKeycodeToKeysym(win->src.display, E.xkey.keycode, 0, E.xkey.state & ShiftMask ? 1 : 0); + + if ((E.xkey.state & LockMask) && sym >= XK_a && sym <= XK_z) + sym = (E.xkey.state & ShiftMask) ? sym + 32 : sym - 32; + if ((u8)sym != (u32)sym) + sym = 0; + + win->event.keyChar = (u8)sym; + + RGFW_keyboard[win->event.key].prev = RGFW_isPressed(win, win->event.key); + + /* get keystate data */ + win->event.type = (E.type == KeyPress) ? RGFW_keyPressed : RGFW_keyReleased; + + XKeyboardState keystate; + XGetKeyboardControl(win->src.display, &keystate); + + RGFW_keyboard[win->event.key].current = (E.type == KeyPress); + RGFW_updateKeyMods(win, (keystate.led_mask & 1), (keystate.led_mask & 2)); + RGFW_keyCallback(win, win->event.key, win->event.keyChar, win->event.keyMod, (E.type == KeyPress)); + break; + } + case ButtonPress: + case ButtonRelease: + win->event.type = RGFW_mouseButtonPressed + (E.type == ButtonRelease); // the events match + + win->event.button = E.xbutton.button; + switch(win->event.button) { + case RGFW_mouseScrollUp: + win->event.scroll = 1; + break; + case RGFW_mouseScrollDown: + win->event.scroll = -1; + break; + default: break; + } + + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + + if (win->event.repeat == RGFW_FALSE) + win->event.repeat = RGFW_isPressed(win, win->event.key); + + RGFW_mouseButtons[win->event.button].current = (E.type == ButtonPress); + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, (E.type == ButtonPress)); + break; + + case MotionNotify: + win->event.point.x = E.xmotion.x; + win->event.point.y = E.xmotion.y; + + if ((win->_flags & RGFW_HOLD_MOUSE)) { + win->event.point.y = E.xmotion.y; + + win->event.point.x = win->event.point.x - win->_lastMousePoint.x; + win->event.point.y = win->event.point.y - win->_lastMousePoint.y; + } + + win->_lastMousePoint = RGFW_POINT(E.xmotion.x, E.xmotion.y); + + win->event.type = RGFW_mousePosChanged; + RGFW_mousePosCallback(win, win->event.point); + break; + + case GenericEvent: { + /* MotionNotify is used for mouse events if the mouse isn't held */ + if (!(win->_flags & RGFW_HOLD_MOUSE)) { + XFreeEventData(win->src.display, &E.xcookie); + break; + } + + XGetEventData(win->src.display, &E.xcookie); + if (E.xcookie.evtype == XI_RawMotion) { + XIRawEvent *raw = (XIRawEvent *)E.xcookie.data; + if (raw->valuators.mask_len == 0) { + XFreeEventData(win->src.display, &E.xcookie); + break; + } + + double deltaX = 0.0f; + double deltaY = 0.0f; + + /* check if relative motion data exists where we think it does */ + if (XIMaskIsSet(raw->valuators.mask, 0) != 0) + deltaX += raw->raw_values[0]; + if (XIMaskIsSet(raw->valuators.mask, 1) != 0) + deltaY += raw->raw_values[1]; + + win->event.point = RGFW_POINT((i32)deltaX, (i32)deltaY); + + RGFW_window_moveMouse(win, RGFW_POINT(win->r.x + (win->r.w / 2), win->r.y + (win->r.h / 2))); + + win->event.type = RGFW_mousePosChanged; + RGFW_mousePosCallback(win, win->event.point); + } + + XFreeEventData(win->src.display, &E.xcookie); + break; + } + + case Expose: + win->event.type = RGFW_windowRefresh; + RGFW_windowRefreshCallback(win); + break; + + case ClientMessage: { + /* if the client closed the window*/ + if (E.xclient.data.l[0] == (long)wm_delete_window) { + win->event.type = RGFW_quit; + RGFW_windowQuitCallback(win); + break; + } + + for (size_t i = 0; i < win->event.droppedFilesCount; i++) { + win->event.droppedFiles[i][0] = '\0'; + } + win->event.droppedFilesCount = 0; + + if ((win->_flags & RGFW_windowAllowDND) == 0) + break; + + reply.xclient.window = source; + reply.xclient.format = 32; + reply.xclient.data.l[0] = (long)win->src.window; + reply.xclient.data.l[1] = 0; + reply.xclient.data.l[2] = None; + + if (E.xclient.message_type == XdndEnter) { + if (version > 5) + break; + + unsigned long count; + Atom* formats; + Atom real_formats[6]; + Bool list = E.xclient.data.l[1] & 1; + + source = E.xclient.data.l[0]; + version = E.xclient.data.l[1] >> 24; + format = None; + + if (list) { + Atom actualType; + i32 actualFormat; + unsigned long bytesAfter; + + XGetWindowProperty( + win->src.display, source, XdndTypeList, + 0, LONG_MAX, False, 4, + &actualType, &actualFormat, &count, &bytesAfter, (u8**)&formats + ); + } else { + count = 0; + + for (size_t i = 2; i < 5; i++) { + Window format = E.xclient.data.l[i]; + if (format != None) { + real_formats[count] = format; + count += 1; + } + } + + formats = real_formats; + } + + for (size_t i = 0; i < count; i++) { + if (formats[i] == XtextUriList || formats[i] == XtextPlain) { + format = (int)formats[i]; + break; + } + } + + if (list) { + XFree(formats); + } + + break; + } + + if (E.xclient.message_type == XdndPosition) { + const i32 xabs = (E.xclient.data.l[2] >> 16) & 0xffff; + const i32 yabs = (E.xclient.data.l[2]) & 0xffff; + Window dummy; + i32 xpos, ypos; + + if (version > 5) + break; + + XTranslateCoordinates( + win->src.display, XDefaultRootWindow(win->src.display), win->src.window, + xabs, yabs, &xpos, &ypos, &dummy + ); + + win->event.point.x = xpos; + win->event.point.y = ypos; + + reply.xclient.window = source; + reply.xclient.message_type = XdndStatus; + + if (format) { + reply.xclient.data.l[1] = 1; + if (version >= 2) + reply.xclient.data.l[4] = (long)XdndActionCopy; + } + + XSendEvent(win->src.display, source, False, NoEventMask, &reply); + XFlush(win->src.display); + break; + } + + if (E.xclient.message_type != XdndDrop) + break; + + if (version > 5) + break; + + win->event.type = RGFW_DNDInit; + + if (format) { + Time time = (version >= 1) + ? (Time)E.xclient.data.l[2] + : CurrentTime; + + XConvertSelection( + win->src.display, XdndSelection, (Atom)format, + XdndSelection, win->src.window, time + ); + } else if (version >= 2) { + XEvent reply = { ClientMessage }; + + XSendEvent(win->src.display, source, False, NoEventMask, &reply); + XFlush(win->src.display); + } + + RGFW_dndInitCallback(win, win->event.point); + } break; + case SelectionNotify: { + /* this is only for checking for xdnd drops */ + if (E.xselection.property != XdndSelection || !(win->_flags & RGFW_windowAllowDND)) + break; + + char* data; + unsigned long result; + + Atom actualType; + i32 actualFormat; + unsigned long bytesAfter; + + XGetWindowProperty(win->src.display, E.xselection.requestor, E.xselection.property, 0, LONG_MAX, False, E.xselection.target, &actualType, &actualFormat, &result, &bytesAfter, (u8**) &data); + + if (result == 0) + break; + + const char* prefix = (const char*)"file://"; + + char* line; + + win->event.droppedFilesCount = 0; + + win->event.type = RGFW_DND; + + while ((line = (char*)RGFW_strtok(data, "\r\n"))) { + char path[RGFW_MAX_PATH]; + + data = NULL; + + if (line[0] == '#') + continue; + + char* l; + for (l = line; 1; l++) { + if ((l - line) > 7) + break; + else if (*l != prefix[(l - line)]) + break; + else if (*l == '\0' && prefix[(l - line)] == '\0') { + line += 7; + while (*line != '/') + line++; + break; + } else if (*l == '\0') + break; + } + + win->event.droppedFilesCount++; + + size_t index = 0; + while (*line) { + if (line[0] == '%' && line[1] && line[2]) { + const char digits[3] = { line[1], line[2], '\0' }; + path[index] = (char) RGFW_STRTOL(digits, NULL, 16); + line += 2; + } else + path[index] = *line; + + index++; + line++; + } + path[index] = '\0'; + RGFW_MEMCPY(win->event.droppedFiles[win->event.droppedFilesCount - 1], path, index + 1); + } + + if (data) + XFree(data); + + if (version >= 2) { + XEvent reply = { ClientMessage }; + reply.xclient.format = 32; + reply.xclient.message_type = XdndFinished; + reply.xclient.data.l[1] = result; + reply.xclient.data.l[2] = XdndActionCopy; + + XSendEvent(win->src.display, source, False, NoEventMask, &reply); + XFlush(win->src.display); + } + + RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount); + break; + } + case FocusIn: + win->event.inFocus = 1; + win->event.type = RGFW_focusIn; + RGFW_focusCallback(win, 1); + break; + case FocusOut: + win->event.inFocus = 0; + win->event.type = RGFW_focusOut; + RGFW_focusCallback(win, 0); + break; + case EnterNotify: { + win->event.type = RGFW_mouseEnter; + win->event.point.x = E.xcrossing.x; + win->event.point.y = E.xcrossing.y; + RGFW_mouseNotifyCallBack(win, win->event.point, 1); + break; + } + + case LeaveNotify: { + win->event.type = RGFW_mouseLeave; + RGFW_mouseNotifyCallBack(win, win->event.point, 0); + break; + } + + case ConfigureNotify: { + /* detect resize */ + if (E.xconfigure.width != win->r.w || E.xconfigure.height != win->r.h) { + win->event.type = RGFW_windowResized; + win->r = RGFW_RECT(win->r.x, win->r.y, E.xconfigure.width, E.xconfigure.height); + RGFW_windowResizeCallback(win, win->r); + break; + } + + /* detect move */ + if (E.xconfigure.x != win->r.x || E.xconfigure.y != win->r.y) { + win->event.type = RGFW_windowMoved; + win->r = RGFW_RECT(E.xconfigure.x, E.xconfigure.y, win->r.w, win->r.h); + RGFW_windowMoveCallback(win, win->r); + break; + } + + break; + } + default: + XFlush(win->src.display); + return RGFW_window_checkEvent(win); + } + + XFlush(win->src.display); + if (win->event.type) return &win->event; + else return NULL; +#endif +#ifdef RGFW_WAYLAND + wayland: + if (win->_flags & RGFW_windowHide) + return NULL; + + if (win->src.eventIndex == 0) { + if (wl_display_roundtrip(win->src.wl_display) == -1) { + return NULL; + } + } + + if (win->src.eventLen == 0) { + return NULL; + } + + RGFW_event ev = RGFW_eventPipe_pop(win); + + if (ev.type == 0 || win->event.type == RGFW_quit) { + return NULL; + } + + ev.frameTime = win->event.frameTime; + ev.frameTime2 = win->event.frameTime2; + ev.inFocus = win->event.inFocus; + win->event = ev; + if (win->event.type) return &win->event; + else return NULL; +#endif +} + +void RGFW_window_move(RGFW_window* win, RGFW_point v) { + RGFW_ASSERT(win != NULL); + win->r.x = v.x; + win->r.y = v.y; + RGFW_GOTO_WAYLAND(0); +#ifdef RGFW_X11 + XMoveWindow(win->src.display, win->src.window, v.x, v.y); +#endif +#ifdef RGFW_WAYLAND + wayland: + RGFW_ASSERT(win != NULL); + + if (win->src.compositor) { + struct wl_pointer *pointer = wl_seat_get_pointer(win->src.seat); + if (!pointer) { + return; + } + + wl_display_flush(win->src.wl_display); + } +#endif +} + + +void RGFW_window_resize(RGFW_window* win, RGFW_area a) { + RGFW_ASSERT(win != NULL); + win->r.w = a.w; + win->r.h = a.h; + RGFW_GOTO_WAYLAND(0); +#ifdef RGFW_X11 + XResizeWindow(win->src.display, win->src.window, a.w, a.h); + + if (!(win->_flags & RGFW_windowNoResize)) + return; + + XSizeHints sh; + sh.flags = (1L << 4) | (1L << 5); + sh.min_width = sh.max_width = a.w; + sh.min_height = sh.max_height = a.h; + + XSetWMSizeHints(win->src.display, (Drawable) win->src.window, &sh, XA_WM_NORMAL_HINTS); +#endif +#ifdef RGFW_WAYLAND + wayland: + if (win->src.compositor) { + xdg_surface_set_window_geometry(win->src.xdg_surface, 0, 0, win->r.w, win->r.h); + #ifdef RGFW_OPENGL + wl_egl_window_resize(win->src.eglWindow, a.w, a.h, 0, 0); + #endif + } +#endif +} + +void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) { + RGFW_ASSERT(win != NULL); + + if (a.w == 0 && a.h == 0) + return; + + XSizeHints hints; + long flags; + + XGetWMNormalHints(win->src.display, win->src.window, &hints, &flags); + + hints.flags |= PMinSize; + + hints.min_width = a.w; + hints.min_height = a.h; + + XSetWMNormalHints(win->src.display, win->src.window, &hints); +} + +void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) { + RGFW_ASSERT(win != NULL); + + if (a.w == 0 && a.h == 0) + return; + + XSizeHints hints; + long flags; + + XGetWMNormalHints(win->src.display, win->src.window, &hints, &flags); + + hints.flags |= PMaxSize; + + hints.max_width = a.w; + hints.max_height = a.h; + + XSetWMNormalHints(win->src.display, win->src.window, &hints); +} + + +void RGFW_window_minimize(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + + XIconifyWindow(win->src.display, win->src.window, DefaultScreen(win->src.display)); + XFlush(win->src.display); +} + +void RGFW_window_restore(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + + XMapWindow(win->src.display, win->src.window); + XFlush(win->src.display); +} + +void RGFW_window_setName(RGFW_window* win, const char* name) { + RGFW_ASSERT(win); + RGFW_GOTO_WAYLAND(0); + #ifdef RGFW_X11 + XStoreName(win->src.display, win->src.window, name); + + RGFW_LOAD_ATOM(_NET_WM_NAME); + XChangeProperty( + win->src.display, win->src.window, _NET_WM_NAME, RGFW_XUTF8_STRING, + 8, PropModeReplace, (u8*)name, 256 + ); + #endif + #ifdef RGFW_WAYLAND + wayland: + if (win->src.compositor) + xdg_toplevel_set_title(win->src.xdg_toplevel, name); + #endif +} + +void* RGFW_libxshape = NULL; + +#ifndef RGFW_NO_PASSTHROUGH + +void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) { + RGFW_ASSERT(win != NULL); + + #if defined(__CYGWIN__) + RGFW_LOAD_LIBRARY(RGFW_libxshape, "libXext-6.so"); + #elif defined(__OpenBSD__) || defined(__NetBSD__) + RGFW_LOAD_LIBRARY(RGFW_libxshape, "libXext.so"); + #else + RGFW_LOAD_LIBRARY(RGFW_libxshape, "libXext.so.6"); + #endif + + typedef void (* PFN_XShapeCombineMask)(Display*,Window,int,int,int,Pixmap,int); + static PFN_XShapeCombineMask XShapeCombineMaskSRC; + + typedef void (* PFN_XShapeCombineRegion)(Display*,Window,int,int,int,Region,int); + static PFN_XShapeCombineRegion XShapeCombineRegionSRC; + + RGFW_PROC_DEF(RGFW_libxshape, XShapeCombineRegion); + RGFW_PROC_DEF(RGFW_libxshape, XShapeCombineMask); + + if (passthrough) { + Region region = XCreateRegion(); + XShapeCombineRegionSRC(win->src.display, win->src.window, ShapeInput, 0, 0, region, ShapeSet); + XDestroyRegion(region); + + return; + } + + XShapeCombineMaskSRC(win->src.display, win->src.window, ShapeInput, 0, 0, None, ShapeSet); +} + +#endif /* RGFW_NO_PASSTHROUGH */ + +b32 RGFW_window_setIcon(RGFW_window* win, u8* icon, RGFW_area a, i32 channels) { + RGFW_ASSERT(win != NULL); RGFW_ASSERT(icon != NULL); + RGFW_ASSERT(channels == 3 || channels == 4); + RGFW_GOTO_WAYLAND(0); +#ifdef RGFW_X11 + i32 count = 2 + (a.w * a.h); + + unsigned long* data = (unsigned long*) RGFW_alloc(count * sizeof(unsigned long)); + data[0] = (unsigned long)a.w; + data[1] = (unsigned long)a.h; + + unsigned long* target = &data[2]; + + u32 x, y; + + for (x = 0; x < a.w; x++) { + for (y = 0; y < a.h; y++) { + size_t i = y * a.w + x; + u32 alpha = (channels == 4) ? icon[i * 4 + 3] : 0xFF; + + target[i] = (unsigned long)((icon[i * 4 + 0]) << 16) | + (unsigned long)((icon[i * 4 + 1]) << 8) | + (unsigned long)((icon[i * 4 + 2]) << 0) | + (unsigned long)(alpha << 24); + } + } + + RGFW_LOAD_ATOM(_NET_WM_ICON); + + b32 res = (b32)XChangeProperty( + win->src.display, win->src.window, _NET_WM_ICON, XA_CARDINAL, 32, + PropModeReplace, (u8*)data, count + ); + + RGFW_free(data); + + XFlush(win->src.display); + return res; +#endif +#ifdef RGFW_WAYLAND + wayland: + return 0; +#endif +} + +RGFW_mouse* RGFW_loadMouse(u8* icon, RGFW_area a, i32 channels) { + RGFW_ASSERT(icon); + RGFW_ASSERT(channels == 3 || channels == 4); + RGFW_GOTO_WAYLAND(0); + +#ifdef RGFW_X11 +#ifndef RGFW_NO_X11_CURSOR + XcursorImage* native = XcursorImageCreate(a.w, a.h); + native->xhot = 0; + native->yhot = 0; + + XcursorPixel* target = native->pixels; + for (size_t x = 0; x < a.w; x++) { + for (size_t y = 0; y < a.h; y++) { + size_t i = y * a.w + x; + u32 alpha = (channels == 4) ? icon[i * 4 + 3] : 0xFF; + + target[i] = (u32)((icon[i * 4 + 0]) << 16) + | (u32)((icon[i * 4 + 1]) << 8) + | (u32)((icon[i * 4 + 2]) << 0) + | (u32)(alpha << 24); + } + } + + Cursor cursor = XcursorImageLoadCursor(RGFW_root->src.display, native); + XcursorImageDestroy(native); + + return (void*)cursor; +#else + RGFW_UNUSED(image); RGFW_UNUSED(a.w); RGFW_UNUSED(channels); + return NULL; +#endif +#endif +#ifdef RGFW_WAYLAND + wayland: + RGFW_UNUSED(icon); RGFW_UNUSED(a); RGFW_UNUSED(channels); + return NULL; // TODO +#endif +} + +void RGFW_window_setMouse(RGFW_window* win, RGFW_mouse* mouse) { +RGFW_GOTO_WAYLAND(0); +#ifdef RGFW_X11 + RGFW_ASSERT(win && mouse); + XDefineCursor(win->src.display, win->src.window, (Cursor)mouse); +#endif +#ifdef RGFW_WAYLAND + wayland: +#endif +} + +void RGFW_freeMouse(RGFW_mouse* mouse) { +RGFW_GOTO_WAYLAND(0); +#ifdef RGFW_X11 + RGFW_ASSERT(mouse); + XFreeCursor(RGFW_root->src.display, (Cursor)mouse); +#endif +#ifdef RGFW_WAYLAND + wayland: +#endif +} + +void RGFW_window_moveMouse(RGFW_window* win, RGFW_point p) { +RGFW_GOTO_WAYLAND(1); +#ifdef RGFW_X11 + RGFW_ASSERT(win != NULL); + + XEvent event; + XQueryPointer(win->src.display, DefaultRootWindow(win->src.display), + &event.xbutton.root, &event.xbutton.window, + &event.xbutton.x_root, &event.xbutton.y_root, + &event.xbutton.x, &event.xbutton.y, + &event.xbutton.state); + + win->_lastMousePoint = RGFW_POINT(p.x - win->r.x, p.y - win->r.y); + if (event.xbutton.x == p.x && event.xbutton.y == p.y) + return; + + XWarpPointer(win->src.display, None, win->src.window, 0, 0, 0, 0, (int) p.x - win->r.x, (int) p.y - win->r.y); +#endif +#ifdef RGFW_WAYLAND + wayland: +#endif +} + +b32 RGFW_window_setMouseDefault(RGFW_window* win) { + return RGFW_window_setMouseStandard(win, RGFW_mouseArrow); +} + +b32 RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) { + RGFW_ASSERT(win != NULL); + RGFW_GOTO_WAYLAND(0); +#ifdef RGFW_X11 + if (mouse > (sizeof(RGFW_mouseIconSrc) / sizeof(u8))) + return 0; + + mouse = RGFW_mouseIconSrc[mouse]; + + Cursor cursor = XCreateFontCursor(win->src.display, mouse); + XDefineCursor(win->src.display, win->src.window, (Cursor) cursor); + + XFreeCursor(win->src.display, (Cursor) cursor); + return 1; +#endif +#ifdef RGFW_WAYLAND + wayland: + static const char* iconStrings[] = { "left_ptr", "left_ptr", "text", "cross", "pointer", "e-resize", "n-resize", "nw-resize", "ne-resize", "all-resize", "not-allowed" }; + + struct wl_cursor* wlcursor = wl_cursor_theme_get_cursor(RGFW_wl_cursor_theme, iconStrings[mouse]); + RGFW_cursor_image = wlcursor->images[0]; + struct wl_buffer* cursor_buffer = wl_cursor_image_get_buffer(RGFW_cursor_image); + + wl_surface_attach(RGFW_cursor_surface, cursor_buffer, 0, 0); + wl_surface_commit(RGFW_cursor_surface); + return 1; +#endif +} + +void RGFW_window_hide(RGFW_window* win) { + RGFW_GOTO_WAYLAND(0); +#ifdef RGFW_X11 + XMapWindow(win->src.display, win->src.window); +#endif +#ifdef RGFW_WAYLAND + wayland: + wl_surface_attach(win->src.surface, NULL, 0, 0); + wl_surface_commit(win->src.surface); + win->_flags |= RGFW_windowHide; +#endif +} + +void RGFW_window_show(RGFW_window* win) { + if (win->_flags & RGFW_windowHide) + win->_flags ^= RGFW_windowHide; + RGFW_GOTO_WAYLAND(0); +#ifdef RGFW_X11 + XUnmapWindow(win->src.display, win->src.window); +#endif +#ifdef RGFW_WAYLAND + wayland: + //wl_surface_attach(win->src.surface, win->rc., 0, 0); + wl_surface_commit(win->src.surface); +#endif +} + +RGFW_ssize_t RGFW_readClipboardPtr(char* str, size_t strCapacity) { + RGFW_GOTO_WAYLAND(1); + #ifdef RGFW_X11 + XEvent event; + int format; + unsigned long N, sizeN; + char* data; + Atom target; + + RGFW_LOAD_ATOM(XSEL_DATA); + + XConvertSelection(RGFW_root->src.display, RGFW_XCLIPBOARD, RGFW_XUTF8_STRING, XSEL_DATA, RGFW_root->src.window, CurrentTime); + XSync(RGFW_root->src.display, 0); + XNextEvent(RGFW_root->src.display, &event); + + if (event.type != SelectionNotify || event.xselection.selection != RGFW_XCLIPBOARD || event.xselection.property == 0) + return -1; + + XGetWindowProperty(event.xselection.display, event.xselection.requestor, + event.xselection.property, 0L, (~0L), 0, AnyPropertyType, &target, + &format, &sizeN, &N, (unsigned char**) &data); + + RGFW_ssize_t size; + if (sizeN > strCapacity && str != NULL) + size = -1; + + if ((target == RGFW_XUTF8_STRING || target == XA_STRING) && str != NULL) { + RGFW_MEMCPY(str, data, sizeN); + str[sizeN] = '\0'; + XFree(data); + } else if (str != NULL) size = -1; + + XDeleteProperty(event.xselection.display, event.xselection.requestor, event.xselection.property); + size = sizeN; + return size; + #endif + #if defined(RGFW_WAYLAND) + wayland: return 0; + #endif +} + +void RGFW_writeClipboard(const char* text, u32 textLen) { + RGFW_GOTO_WAYLAND(1); + #ifdef RGFW_X11 + RGFW_LOAD_ATOM(SAVE_TARGETS); + RGFW_LOAD_ATOM(TARGETS); + RGFW_LOAD_ATOM(MULTIPLE); + RGFW_LOAD_ATOM(ATOM_PAIR); + RGFW_LOAD_ATOM(CLIPBOARD_MANAGER); + + XSetSelectionOwner(RGFW_root->src.display, RGFW_XCLIPBOARD, RGFW_root->src.window, CurrentTime); + + XConvertSelection(RGFW_root->src.display, CLIPBOARD_MANAGER, SAVE_TARGETS, None, RGFW_root->src.window, CurrentTime); + for (;;) { + XEvent event; + + XNextEvent(RGFW_root->src.display, &event); + if (event.type != SelectionRequest) { + break; + } + + const XSelectionRequestEvent* request = &event.xselectionrequest; + + XEvent reply = { SelectionNotify }; + reply.xselection.property = 0; + + if (request->target == TARGETS) { + const Atom targets[] = { TARGETS, + MULTIPLE, + RGFW_XUTF8_STRING, + XA_STRING }; + + XChangeProperty(RGFW_root->src.display, + request->requestor, + request->property, + 4, + 32, + PropModeReplace, + (u8*) targets, + sizeof(targets) / sizeof(targets[0])); + + reply.xselection.property = request->property; + } + + if (request->target == MULTIPLE) { + Atom* targets = NULL; + + Atom actualType = 0; + int actualFormat = 0; + unsigned long count = 0, bytesAfter = 0; + + XGetWindowProperty(RGFW_root->src.display, request->requestor, request->property, 0, LONG_MAX, False, ATOM_PAIR, &actualType, &actualFormat, &count, &bytesAfter, (u8**) &targets); + + unsigned long i; + for (i = 0; i < (u32)count; i += 2) { + if (targets[i] == RGFW_XUTF8_STRING || targets[i] == XA_STRING) { + XChangeProperty(RGFW_root->src.display, + request->requestor, + targets[i + 1], + targets[i], + 8, + PropModeReplace, + (u8*) text, + textLen); + XFlush(RGFW_root->src.display); + } else { + targets[i + 1] = None; + } + } + + XChangeProperty(RGFW_root->src.display, + request->requestor, + request->property, + ATOM_PAIR, + 32, + PropModeReplace, + (u8*) targets, + count); + + XFlush(RGFW_root->src.display); + XFree(targets); + + reply.xselection.property = request->property; + } + + reply.xselection.display = request->display; + reply.xselection.requestor = request->requestor; + reply.xselection.selection = request->selection; + reply.xselection.target = request->target; + reply.xselection.time = request->time; + + XSendEvent(RGFW_root->src.display, request->requestor, False, 0, &reply); + XFlush(RGFW_root->src.display); + } + #endif + #if defined(RGFW_WAYLAND) + wayland: + #endif +} + +u8 RGFW_window_isFullscreen(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + + XWindowAttributes windowAttributes; + XGetWindowAttributes(win->src.display, win->src.window, &windowAttributes); + + /* check if the window is visable */ + if (windowAttributes.map_state != IsViewable) + return 0; + + /* check if the window covers the full screen */ + return (windowAttributes.x == 0 && windowAttributes.y == 0 && + windowAttributes.width == XDisplayWidth(win->src.display, DefaultScreen(win->src.display)) && + windowAttributes.height == XDisplayHeight(win->src.display, DefaultScreen(win->src.display))); +} + +u8 RGFW_window_isHidden(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + + XWindowAttributes windowAttributes; + XGetWindowAttributes(win->src.display, win->src.window, &windowAttributes); + + return (windowAttributes.map_state == IsUnmapped && !RGFW_window_isMinimized(win)); +} + +u8 RGFW_window_isMinimized(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + + RGFW_LOAD_ATOM(WM_STATE); + + Atom actual_type; + i32 actual_format; + unsigned long nitems, bytes_after; + unsigned char* prop_data; + + i16 status = XGetWindowProperty(win->src.display, win->src.window, WM_STATE, 0, 2, False, + AnyPropertyType, &actual_type, &actual_format, + &nitems, &bytes_after, &prop_data); + + if (status == Success && nitems >= 1 && *((int*) prop_data) == IconicState) { + XFree(prop_data); + return 1; + } + + if (prop_data != NULL) + XFree(prop_data); + + return 0; +} + +u8 RGFW_window_isMaximized(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + RGFW_LOAD_ATOM(_NET_WM_STATE); + RGFW_LOAD_ATOM(_NET_WM_STATE_MAXIMIZED_VERT); + RGFW_LOAD_ATOM(_NET_WM_STATE_MAXIMIZED_HORZ); + + Atom actual_type; + i32 actual_format; + unsigned long nitems, bytes_after; + unsigned char* prop_data; + + i16 status = XGetWindowProperty(win->src.display, win->src.window, _NET_WM_STATE, 0, 1024, False, + XA_ATOM, &actual_type, &actual_format, + &nitems, &bytes_after, &prop_data); + + if (status != Success) { + if (prop_data != NULL) + XFree(prop_data); + + return 0; + } + + Atom* atoms = (Atom*) prop_data; + u64 i; + for (i = 0; i < nitems; ++i) { + if (atoms[i] == _NET_WM_STATE_MAXIMIZED_VERT || + atoms[i] == _NET_WM_STATE_MAXIMIZED_HORZ) { + XFree(prop_data); + return 1; + } + } + + return 0; +} + +static float XGetSystemContentDPI(Display* display, i32 screen) { + float dpi = 96.0f; + + #ifndef RGFW_NO_DPI + RGFW_UNUSED(screen); + char* rms = XResourceManagerString(display); + XrmDatabase db = NULL; + + if (rms && db) { + db = XrmGetStringDatabase(rms); + XrmValue value; + char* type = NULL; + + if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value) && type && RGFW_STRNCMP(type, "String", 7) == 0) { + dpi = (float)atof(value.addr); + } + XrmDestroyDatabase(db); + } + #else + dpi = RGFW_ROUND(DisplayWidth(display, screen) / (DisplayWidthMM(display, screen) / 25.4)); + #endif + + return dpi; +} + +RGFW_monitor RGFW_XCreateMonitor(i32 screen) { + RGFW_monitor monitor; + + Display* display = XOpenDisplay(NULL); + + RGFW_area size = RGFW_getScreenSize(); + + monitor.rect = RGFW_RECT(0, 0, size.w, size.h); + monitor.physW = DisplayWidthMM(display, screen) / 25.4; + monitor.physH = DisplayHeightMM(display, screen) / 25.4; + + char* name = XDisplayName((const char*)display); + RGFW_MEMCPY(monitor.name, name, 128); + + float dpi = XGetSystemContentDPI(display, screen); + monitor.pixelRatio = dpi / 96.0f; + + #ifndef RGFW_NO_DPI + XRRScreenResources* sr = XRRGetScreenResourcesCurrent(display, RootWindow(display, screen)); + + XRRCrtcInfo* ci = NULL; + int crtc = screen; + + if (sr->ncrtc > crtc) { + ci = XRRGetCrtcInfo(display, sr, sr->crtcs[crtc]); + } + #endif + + float ppi_width = RGFW_ROUND((float)monitor.rect.w/(float)monitor.physW); + float ppi_height = RGFW_ROUND((float)monitor.rect.h/(float)monitor.physH); + + monitor.scaleX = (float) (ppi_width) / dpi; + monitor.scaleY = (float) (ppi_height) / dpi; + + #ifndef RGFW_NO_DPI + XRROutputInfo* info = XRRGetOutputInfo (display, sr, sr->outputs[screen]); + + if (info == NULL || ci == NULL) { + XRRFreeScreenResources(sr); + XCloseDisplay(display); + + #ifdef RGFW_DEBUG + printf("RGFW INFO: monitor found: scale (%s):\n rect: {%i, %i, %i, %i}\n physical size:%f %f\n scale: %f %f\n pixelRatio: %f\n", monitor.name, monitor.rect.x, monitor.rect.y, monitor.rect.w, monitor.rect.h, monitor.physW, monitor.physH, monitor.scaleX, monitor.scaleY, monitor.pixelRatio); + #endif + return monitor; + } + + + float physW = info->mm_width / 25.4; + float physH = info->mm_height / 25.4; + + RGFW_MEMCPY(monitor.name, info->name, 128); + + if (physW && physH) { + monitor.physW = physW; + monitor.physH = physH; + } + + monitor.rect.x = ci->x; + monitor.rect.y = ci->y; + + float w = ci->width; + float h = ci->height; + + if (w && h) { + monitor.rect.w = w; + monitor.rect.h = h; + } + #endif + + if (monitor.physW == 0 || monitor.physH == 0) { + monitor.scaleX = 0; + monitor.scaleY = 0; + } else { + float ppi_width = RGFW_ROUND((float)monitor.rect.w/(float)monitor.physW); + float ppi_height = RGFW_ROUND((float)monitor.rect.h/(float)monitor.physH); + + monitor.scaleX = (float) (ppi_width) / (float) dpi; + monitor.scaleY = (float) (ppi_height) / (float) dpi; + + if ((monitor.scaleX > 1 && monitor.scaleX < 1.1)) + monitor.scaleX = 1; + + if ((monitor.scaleY > 1 && monitor.scaleY < 1.1)) + monitor.scaleY = 1; + } + + #ifndef RGFW_NO_DPI + XRRFreeCrtcInfo(ci); + XRRFreeScreenResources(sr); + #endif + + XCloseDisplay(display); + + #ifdef RGFW_DEBUG + printf("RGFW INFO: monitor found: scale (%s):\n rect: {%i, %i, %i, %i}\n physical size:%f %f\n scale: %f %f\n pixelRatio: %f\n", monitor.name, monitor.rect.x, monitor.rect.y, monitor.rect.w, monitor.rect.h, monitor.physW, monitor.physH, monitor.scaleX, monitor.scaleY, monitor.pixelRatio); + #endif + + return monitor; +} + +RGFW_monitor RGFW_monitors[6]; +RGFW_monitor* RGFW_getMonitors(void) { + RGFW_GOTO_WAYLAND(1); + #ifdef RGFW_X11 + size_t i; + for (i = 0; i < (size_t)ScreenCount(RGFW_root->src.display) && i < 6; i++) + RGFW_monitors[i] = RGFW_XCreateMonitor(i); + + return RGFW_monitors; + #endif + #ifdef RGFW_WAYLAND + wayland: return RGFW_monitors; // TODO WAYLAND + #endif +} + +RGFW_monitor RGFW_getPrimaryMonitor(void) { + RGFW_GOTO_WAYLAND(1); + #ifdef RGFW_X11 + RGFW_ASSERT(RGFW_root != NULL); + return RGFW_XCreateMonitor(DefaultScreen(RGFW_root->src.display)); + #endif + #ifdef RGFW_WAYLAND + wayland: return (RGFW_monitor){ }; // TODO WAYLAND + #endif +} + +RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + RGFW_GOTO_WAYLAND(1); +#ifdef RGFW_X11 + XWindowAttributes attrs; + if (!XGetWindowAttributes(win->src.display, win->src.window, &attrs)) { + return (RGFW_monitor){}; + } + + #ifndef RGFW_NO_DPI + XRRScreenResources* screenRes = XRRGetScreenResources(win->src.display, DefaultRootWindow(win->src.display)); + if (screenRes == NULL) { + return (RGFW_monitor){}; + } + + for (int i = 0; i < screenRes->ncrtc; i++) { + XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(win->src.display, screenRes, screenRes->crtcs[i]); + if (!crtcInfo) continue; + + int monitorX = crtcInfo->x; + int monitorY = crtcInfo->y; + int monitorWidth = crtcInfo->width; + int monitorHeight = crtcInfo->height; + + if (attrs.x >= monitorX && + attrs.x < monitorX + monitorWidth && + attrs.y >= monitorY && + attrs.y < monitorY + monitorHeight) { + XRRFreeCrtcInfo(crtcInfo); + XRRFreeScreenResources(screenRes); + return RGFW_XCreateMonitor(i); + } + + XRRFreeCrtcInfo(crtcInfo); + } + + XRRFreeScreenResources(screenRes); + #else + size_t i; + for (i = 0; i < (size_t)ScreenCount(RGFW_root->src.display) && i < 6; i++) { + Screen* screen = ScreenOfDisplay(RGFW_root->src.display, i); + if (attrs.x >= 0 && attrs.x < 0 + XWidthOfScreen(screen) && + attrs.y >= 0 && attrs.y < 0 + XHeightOfScreen(screen)) + return RGFW_XCreateMonitor(i); + } + #endif +#endif +wayland: + return (RGFW_monitor){}; + +} + +#if defined(RGFW_OPENGL) && !defined(RGFW_EGL) + +void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) { + if (win == NULL) + glXMakeCurrent(NULL, (Drawable)NULL, (GLXContext) NULL); + else + glXMakeCurrent(win->src.display, (Drawable) win->src.window, (GLXContext) win->src.ctx); +} +#endif + + +void RGFW_window_swapBuffers(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + RGFW_GOTO_WAYLAND(0); +#ifdef RGFW_X11 + /* clear the window*/ + if (!(win->_flags & RGFW_NO_CPU_RENDER)) { + #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) + RGFW_area area = RGFW_bufferSize; + win->src.bitmap->data = (char*) win->buffer; + #if !defined(RGFW_X11_DONT_CONVERT_BGR) && !defined(RGFW_OSMESA) + u32 x, y; + for (y = 0; y < (u32)win->r.h; y++) { + for (x = 0; x < (u32)win->r.w; x++) { + u32 index = (y * 4 * area.w) + x * 4; + + u8 red = win->src.bitmap->data[index]; + win->src.bitmap->data[index] = win->buffer[index + 2]; + win->src.bitmap->data[index + 2] = red; + + } + } + #endif + XPutImage(win->src.display, win->src.window, win->src.gc, win->src.bitmap, 0, 0, 0, 0, RGFW_bufferSize.w, RGFW_bufferSize.h); + win->src.bitmap->data = NULL; + #endif + } + + if (!(win->_flags & RGFW_NO_GPU_RENDER)) { + #ifdef RGFW_EGL + eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface); + #elif defined(RGFW_OPENGL) + glXSwapBuffers(win->src.display, win->src.window); + #endif + } + return; +#endif +#ifdef RGFW_WAYLAND + wayland: + #if defined(RGFW_BUFFER) || defined(RGFW_OSMESA) + #if !defined(RGFW_X11_DONT_CONVERT_BGR) && !defined(RGFW_OSMESA) + for (u32 y = 0; y < (u32)win->r.h; y++) { + for (u32 x = 0; x < (u32)win->r.w; x++) { + u32 index = (y * 4 * win->r.w) + x * 4; + u32 index2 = (y * 4 * RGFW_bufferSize.w) + x * 4; + + u8 red = win->buffer[index2]; + win->src.buffer[index] = win->buffer[index2 + 2]; + win->src.buffer[index + 1] = win->buffer[index2 + 1]; + win->src.buffer[index + 2] = red; + } + } + #else + for (size_t y = 0; y < win->r.h; y++) { + u32 index = (y * 4 * win->r.w); + u32 index2 = (y * 4 * RGFW_bufferSize.w); + RGFW_MEMCPY(&win->src.buffer[index], &win->buffer[index2], win->r.w * 4); + } + #endif + + wl_surface_frame_done(win, NULL, 0); + if (!(win->_flags & RGFW_NO_GPU_RENDER)) + #endif + { + #ifdef RGFW_OPENGL + eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface); + #endif + } + + wl_surface_commit(win->src.surface); +#endif +} + +#if !defined(RGFW_EGL) + +void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { + RGFW_ASSERT(win != NULL); + + #if defined(RGFW_OPENGL) + ((PFNGLXSWAPINTERVALEXTPROC) glXGetProcAddress((GLubyte*) "glXSwapIntervalEXT"))(win->src.display, win->src.window, swapInterval); + #else + RGFW_UNUSED(swapInterval); + #endif +} +#endif + + +void RGFW_window_close(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + RGFW_GOTO_WAYLAND(0); + #ifdef RGFW_X11 + /* ungrab pointer if it was grabbed */ + if (win->_flags & RGFW_HOLD_MOUSE) + XUngrabPointer(win->src.display, CurrentTime); + + #ifdef RGFW_EGL + RGFW_closeEGL(win); + #endif + + if (RGFW_hiddenMouse != NULL && (RGFW_windowsOpen - 1) <= 0) { + RGFW_freeMouse(RGFW_hiddenMouse); + RGFW_hiddenMouse = 0; + } + + #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) + if (win->buffer != NULL) { + if ((win->_flags & RGFW_BUFFER_ALLOC)) + win->_mem.free(win->_mem.userdata, win->buffer); + XDestroyImage((XImage*) win->src.bitmap); + XFreeGC(win->src.display, win->src.gc); + } + #endif + + if (win->src.display) { + #if defined(RGFW_OPENGL) && !defined(RGFW_EGL) + glXDestroyContext(win->src.display, win->src.ctx); + #endif + + if (win == RGFW_root) + RGFW_root = NULL; + + if ((Drawable) win->src.window) + XDestroyWindow(win->src.display, (Drawable) win->src.window); /*!< close the window*/ + + XCloseDisplay(win->src.display); /*!< kill the display*/ + } + + #ifdef RGFW_ALLOC_DROPFILES + { + u32 i; + for (i = 0; i < RGFW_MAX_DROPS; i++) + win->_mem.free(win->_mem.userdata, win->event.droppedFiles[i]); + + + win->_mem.free(win->_mem.userdata, win->event.droppedFiles); + } + #endif + + /* set cleared display / window to NULL for error checking */ + win->src.display = 0; + win->src.window = 0; + + RGFW_windowsOpen--; + + #define RGFW_FREE_LIBRARY(x) if (x != NULL) dlclose(x); x = NULL; + if (RGFW_windowsOpen <= 0) { + #if !defined(RGFW_NO_X11_CURSOR_PRELOAD) && !defined(RGFW_NO_X11_CURSOR) + RGFW_FREE_LIBRARY(X11Cursorhandle); + #endif + #if !defined(RGFW_NO_X11_XI_PRELOAD) + RGFW_FREE_LIBRARY(X11Xihandle); + #endif + + #ifdef RGFW_USE_XDL + XDL_close(); + #endif + + #ifndef RGFW_NO_PASSTHROUGH + RGFW_FREE_LIBRARY(RGFW_libxshape); + #endif + + #ifndef RGFW_NO_LINUX + if (RGFW_eventWait_forceStop[0] || RGFW_eventWait_forceStop[1]){ + close(RGFW_eventWait_forceStop[0]); + close(RGFW_eventWait_forceStop[1]); + } + + u8 i; + for (i = 0; i < RGFW_gamepadCount; i++) { + if(RGFW_gamepads[i]) + close(RGFW_gamepads[i]); + } + #endif + } + RGFW_clipboard_switch(NULL); + if ((win->_flags & RGFW_WINDOW_ALLOC)) + win->_mem.free(win->_mem.userdata, win); + return; + #endif + + #ifdef RGFW_WAYLAND + wayland: + + #ifdef RGFW_X11 + XDestroyWindow(win->src.display, (Drawable) win->src.window); + XCloseDisplay(win->src.display); /*!< kill the display*/ + #endif + #ifdef RGFW_EGL RGFW_closeEGL(win); #endif @@ -4967,45 +5237,126 @@ static const struct wl_callback_listener wl_surface_frame_listener = { xdg_surface_destroy(win->src.xdg_surface); wl_surface_destroy(win->src.surface); - #ifdef RGFW_BUFFER - wl_buffer_destroy(win->src.wl_buffer); + #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) + wl_buffer_destroy(win->src.wl_buffer); + if ((win->_flags & RGFW_BUFFER_ALLOC)) + win->_mem.free(win->_mem.userdata, win->buffer); + + munmap(win->src.buffer, win->r.w * win->r.h * 4); #endif - - wl_display_disconnect(win->src.display); - RGFW_FREE(win); - } - RGFW_monitor RGFW_getPrimaryMonitor(void) { - /* TODO wayland */ + wl_display_disconnect(win->src.wl_display); + RGFW_clipboard_switch(NULL); + if ((win->_flags & RGFW_WINDOW_ALLOC)) + win->_mem.free(win->_mem.userdata, win); + #endif +} - return (RGFW_monitor){}; - } - - RGFW_monitor* RGFW_getMonitors(void) { - /* TODO wayland */ - return NULL; - } - - void RGFW_writeClipboard(const char* text, u32 textLen) { - RGFW_UNUSED(text); RGFW_UNUSED(textLen); - - /* TODO wayland */ - } - - char* RGFW_readClipboard(size_t* size) { - RGFW_UNUSED(size); - - /* TODO wayland */ - - return NULL; - } -#endif /* RGFW_WAYLAND */ - -/* - End of Wayland defines +/* + End of X11 linux / wayland / unix defines */ +#include +#include +#include + +void RGFW_stopCheckEvents(void) { + + RGFW_eventWait_forceStop[2] = 1; + while (1) { + const char byte = 0; + const ssize_t result = write(RGFW_eventWait_forceStop[1], &byte, 1); + if (result == 1 || result == -1) + break; + } +} + +void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) { + if (waitMS == 0) + return; + + u8 i; + if (RGFW_eventWait_forceStop[0] == 0 || RGFW_eventWait_forceStop[1] == 0) { + if (pipe(RGFW_eventWait_forceStop) != -1) { + fcntl(RGFW_eventWait_forceStop[0], F_GETFL, 0); + fcntl(RGFW_eventWait_forceStop[0], F_GETFD, 0); + fcntl(RGFW_eventWait_forceStop[1], F_GETFL, 0); + fcntl(RGFW_eventWait_forceStop[1], F_GETFD, 0); + } + } + + struct pollfd fds[] = { + #ifdef RGFW_WAYLAND + { wl_display_get_fd(win->src.wl_display), POLLIN, 0 }, + #else + { ConnectionNumber(win->src.display), POLLIN, 0 }, + #endif + { RGFW_eventWait_forceStop[0], POLLIN, 0 }, + #if defined(__linux__) + { -1, POLLIN, 0 }, {-1, POLLIN, 0 }, {-1, POLLIN, 0 }, {-1, POLLIN, 0} + #endif + }; + + u8 index = 2; + + #if defined(__linux__) + for (i = 0; i < RGFW_gamepadCount; i++) { + if (RGFW_gamepads[i] == 0) + continue; + + fds[index].fd = RGFW_gamepads[i]; + index++; + } + #endif + + + u64 start = RGFW_getTimeNS(); + + + #ifdef RGFW_WAYLAND + while (wl_display_dispatch(win->src.wl_display) <= 0 && waitMS >= -1) { + #else + while (XPending(win->src.display) == 0 && waitMS >= -1) { + #endif + if (poll(fds, index, waitMS) <= 0) + break; + + if (waitMS > 0) { + waitMS -= (RGFW_getTimeNS() - start) / 1e+6; + } + } + + /* drain any data in the stop request */ + if (RGFW_eventWait_forceStop[2]) { + char data[64]; + (void)!read(RGFW_eventWait_forceStop[0], data, sizeof(data)); + + RGFW_eventWait_forceStop[2] = 0; + } +} + +u64 RGFW_getTimeNS(void) { + struct timespec ts = { 0, 0 }; + #ifndef RGFW_NO_UNIX_CLOCK + clock_gettime(1, &ts); + #endif + unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec; + + return nanoSeconds; +} + +u64 RGFW_getTime(void) { + struct timespec ts = { 0, 0 }; + #ifndef RGFW_NO_UNIX_CLOCK + clock_gettime(1, &ts); + #endif + unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec; + + return (double)(nanoSeconds) * 1e-9; +} +#endif /* end of wayland or X11 defines*/ + /* @@ -5015,22 +5366,21 @@ static const struct wl_callback_listener wl_surface_frame_listener = { */ #ifdef RGFW_WINDOWS - #define WIN32_LEAN_AND_MEAN - #define OEMRESOURCE - #include - - #include - #include - #include - #include - #include - #include +#define WIN32_LEAN_AND_MEAN +#define OEMRESOURCE +#include - #include +#include +#include +#include +#include +#include +#include +#include - __declspec(dllimport) int __stdcall WideCharToMultiByte( UINT CodePage, DWORD dwFlags, const WCHAR* lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCCH lpDefaultChar, LPBOOL lpUsedDefaultChar); - - #ifndef RGFW_NO_XINPUT +__declspec(dllimport) int __stdcall WideCharToMultiByte( UINT CodePage, DWORD dwFlags, const WCHAR* lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCCH lpDefaultChar, LPBOOL lpUsedDefaultChar); + +#ifndef RGFW_NO_XINPUT typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*); PFN_XInputGetState XInputGetStateSRC = NULL; #define XInputGetState XInputGetStateSRC @@ -5040,89 +5390,40 @@ static const struct wl_callback_listener wl_surface_frame_listener = { #define XInputGetKeystroke XInputGetKeystrokeSRC static HMODULE RGFW_XInput_dll = NULL; - #endif +#endif - u32 RGFW_mouseIconSrc[] = {OCR_NORMAL, OCR_NORMAL, OCR_IBEAM, OCR_CROSS, OCR_HAND, OCR_SIZEWE, OCR_SIZENS, OCR_SIZENWSE, OCR_SIZENESW, OCR_SIZEALL, OCR_NO}; +u32 RGFW_mouseIconSrc[] = {OCR_NORMAL, OCR_NORMAL, OCR_IBEAM, OCR_CROSS, OCR_HAND, OCR_SIZEWE, OCR_SIZENS, OCR_SIZENWSE, OCR_SIZENESW, OCR_SIZEALL, OCR_NO}; - char* createUTF8FromWideStringWin32(const WCHAR* source); +char* RGFW_createUTF8FromWideStringWin32(const WCHAR* source); #define GL_FRONT 0x0404 #define GL_BACK 0x0405 #define GL_LEFT 0x0406 #define GL_RIGHT 0x0407 -#if defined(RGFW_OSMESA) && defined(RGFW_LINK_OSMESA) - - typedef void (GLAPIENTRY* PFN_OSMesaDestroyContext)(OSMesaContext); - typedef i32(GLAPIENTRY* PFN_OSMesaMakeCurrent)(OSMesaContext, void*, int, int, int); - typedef OSMesaContext(GLAPIENTRY* PFN_OSMesaCreateContext)(GLenum, OSMesaContext); - - PFN_OSMesaMakeCurrent OSMesaMakeCurrentSource; - PFN_OSMesaCreateContext OSMesaCreateContextSource; - PFN_OSMesaDestroyContext OSMesaDestroyContextSource; - -#define OSMesaCreateContext OSMesaCreateContextSource -#define OSMesaMakeCurrent OSMesaMakeCurrentSource -#define OSMesaDestroyContext OSMesaDestroyContextSource -#endif - - typedef int (*PFN_wglGetSwapIntervalEXT)(void); - PFN_wglGetSwapIntervalEXT wglGetSwapIntervalEXTSrc = NULL; +typedef int (*PFN_wglGetSwapIntervalEXT)(void); +PFN_wglGetSwapIntervalEXT wglGetSwapIntervalEXTSrc = NULL; #define wglGetSwapIntervalEXT wglGetSwapIntervalEXTSrc - void* RGFWjoystickApi = NULL; +void* RGFWgamepadApi = NULL; - /* these two wgl functions need to be preloaded */ - typedef HGLRC (WINAPI *PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC hdc, HGLRC hglrc, const int *attribList); - PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL; - - /* defines for creating ARB attributes */ -#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 -#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 -#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 -#define WGL_DRAW_TO_WINDOW_ARB 0x2001 -#define WGL_ACCELERATION_ARB 0x2003 -#define WGL_NO_ACCELERATION_ARB 0x2025 -#define WGL_DOUBLE_BUFFER_ARB 0x2011 -#define WGL_COLOR_BITS_ARB 0x2014 -#define WGL_RED_BITS_ARB 0x2015 -#define WGL_RED_SHIFT_ARB 0x2016 -#define WGL_GREEN_BITS_ARB 0x2017 -#define WGL_GREEN_SHIFT_ARB 0x2018 -#define WGL_BLUE_BITS_ARB 0x2019 -#define WGL_BLUE_SHIFT_ARB 0x201a -#define WGL_ALPHA_BITS_ARB 0x201b -#define WGL_ALPHA_SHIFT_ARB 0x201c -#define WGL_ACCUM_BITS_ARB 0x201d -#define WGL_ACCUM_RED_BITS_ARB 0x201e -#define WGL_ACCUM_GREEN_BITS_ARB 0x201f -#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 -#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 -#define WGL_DEPTH_BITS_ARB 0x2022 -#define WGL_AUX_BUFFERS_ARB 0x2024 -#define WGL_STEREO_ARB 0x2012 -#define WGL_DEPTH_BITS_ARB 0x2022 -#define WGL_STENCIL_BITS_ARB 0x2023 -#define WGL_FULL_ACCELERATION_ARB 0x2027 -#define WGL_CONTEXT_FLAGS_ARB 0x2094 -#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 -#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 -#define WGL_SAMPLE_BUFFERS_ARB 0x2041 -#define WGL_SAMPLES_ARB 0x2042 -#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20a9 +/* these two wgl functions need to be preloaded */ +typedef HGLRC (WINAPI *PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC hdc, HGLRC hglrc, const int *attribList); +PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL; #ifndef RGFW_EGL -static HMODULE wglinstance = NULL; + static HMODULE RGFW_wgl_dll = NULL; #endif -#ifdef RGFW_WGL_LOAD +#ifndef RGFW_NO_LOAD_WGL typedef HGLRC(WINAPI* PFN_wglCreateContext)(HDC); typedef BOOL(WINAPI* PFN_wglDeleteContext)(HGLRC); typedef PROC(WINAPI* PFN_wglGetProcAddress)(LPCSTR); typedef BOOL(WINAPI* PFN_wglMakeCurrent)(HDC, HGLRC); - typedef HDC(WINAPI* PFN_wglGetCurrentDC)(); - typedef HGLRC(WINAPI* PFN_wglGetCurrentContext)(); + typedef HDC(WINAPI* PFN_wglGetCurrentDC)(void); + typedef HGLRC(WINAPI* PFN_wglGetCurrentContext)(void); + typedef BOOL(WINAPI* PFN_wglShareLists)(HGLRC, HGLRC); PFN_wglCreateContext wglCreateContextSRC; PFN_wglDeleteContext wglDeleteContextSRC; @@ -5130,87 +5431,100 @@ static HMODULE wglinstance = NULL; PFN_wglMakeCurrent wglMakeCurrentSRC; PFN_wglGetCurrentDC wglGetCurrentDCSRC; PFN_wglGetCurrentContext wglGetCurrentContextSRC; + PFN_wglShareLists wglShareListsSRC; #define wglCreateContext wglCreateContextSRC #define wglDeleteContext wglDeleteContextSRC #define wglGetProcAddress wglGetProcAddressSRC #define wglMakeCurrent wglMakeCurrentSRC - #define wglGetCurrentDC wglGetCurrentDCSRC #define wglGetCurrentContext wglGetCurrentContextSRC + #define wglShareLists wglShareListsSRC #endif #ifdef RGFW_OPENGL - void* RGFW_getProcAddress(const char* procname) { + void* RGFW_getProcAddress(const char* procname) { void* proc = (void*) wglGetProcAddress(procname); if (proc) return proc; - return (void*) GetProcAddress(wglinstance, procname); + return (void*) GetProcAddress(RGFW_wgl_dll, procname); } typedef HRESULT (APIENTRY* PFNWGLCHOOSEPIXELFORMATARBPROC)(HDC hdc, const int* piAttribIList, const FLOAT* pfAttribFList, UINT nMaxFormats, int* piFormats, UINT* nNumFormats); static PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = NULL; #endif - RGFW_window RGFW_eventWindow; +RGFW_window RGFW_eventWindow; - LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { - switch (message) { - case WM_MOVE: - RGFW_eventWindow.r.x = LOWORD(lParam); - RGFW_eventWindow.r.y = HIWORD(lParam); - RGFW_eventWindow.src.window = hWnd; - return DefWindowProcA(hWnd, message, wParam, lParam); - case WM_SIZE: - RGFW_eventWindow.r.w = LOWORD(lParam); - RGFW_eventWindow.r.h = HIWORD(lParam); - RGFW_eventWindow.src.window = hWnd; - return DefWindowProcA(hWnd, message, wParam, lParam); // Call DefWindowProc after handling - default: - return DefWindowProcA(hWnd, message, wParam, lParam); - } +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + switch (message) { + case WM_MOVE: + RGFW_eventWindow.r.x = LOWORD(lParam); + RGFW_eventWindow.r.y = HIWORD(lParam); + RGFW_eventWindow.src.window = hWnd; + return DefWindowProcA(hWnd, message, wParam, lParam); + case WM_SIZE: + RGFW_eventWindow.r.w = LOWORD(lParam); + RGFW_eventWindow.r.h = HIWORD(lParam); + RGFW_eventWindow.src.window = hWnd; + return DefWindowProcA(hWnd, message, wParam, lParam); // Call DefWindowProc after handling + default: + return DefWindowProcA(hWnd, message, wParam, lParam); } - - #ifndef RGFW_NO_DPI +} + +#ifndef RGFW_NO_DPI static HMODULE RGFW_Shcore_dll = NULL; typedef HRESULT (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,UINT*); PFN_GetDpiForMonitor GetDpiForMonitorSRC = NULL; #define GetDpiForMonitor GetDpiForMonitorSRC - #endif +#endif +#ifndef RGFW_NO_DWM +static HMODULE RGFW_dwm_dll = NULL; +typedef struct { DWORD dwFlags; int fEnable; HRGN hRgnBlur; int fTransitionOnMaximized;} DWM_BLURBEHIND; +typedef HRESULT (WINAPI * PFN_DwmEnableBlurBehindWindow)(HWND, const DWM_BLURBEHIND*); +PFN_DwmEnableBlurBehindWindow DwmEnableBlurBehindWindowSRC = NULL; +#endif + +#if !defined(RGFW_NO_LOAD_WINMM) && !defined(RGFW_NO_WINMM) + static HMODULE RGFW_winmm_dll = NULL; + typedef u32 (WINAPI * PFN_timeBeginPeriod)(u32); + PFN_timeBeginPeriod timeBeginPeriodSRC = NULL; + #define timeBeginPeriod timeBeginPeriodSRC +#elif !defined(RGFW_NO_WINMM) __declspec(dllimport) u32 __stdcall timeBeginPeriod(u32 uPeriod); - - #ifndef RGFW_NO_XINPUT - void RGFW_loadXInput(void) { - u32 i; - static const char* names[] = { - "xinput1_4.dll", - "xinput1_3.dll", - "xinput9_1_0.dll", - "xinput1_2.dll", - "xinput1_1.dll" - }; +#endif - for (i = 0; i < sizeof(names) / sizeof(const char*); i++) { - RGFW_XInput_dll = LoadLibraryA(names[i]); +#define RGFW_PROC_DEF(proc, name) if (name##SRC == NULL && proc != NULL) name##SRC = (PFN_##name)(void*)GetProcAddress(proc, #name) - if (RGFW_XInput_dll) { - XInputGetStateSRC = (PFN_XInputGetState)(void*)GetProcAddress(RGFW_XInput_dll, "XInputGetState"); - - if (XInputGetStateSRC == NULL) - printf("Failed to load XInputGetState"); - } - } +#ifndef RGFW_NO_XINPUT +void RGFW_loadXInput(void) { + u32 i; + static const char* names[] = {"xinput1_4.dll", "xinput9_1_0.dll", "xinput1_2.dll", "xinput1_1.dll"}; + + for (i = 0; i < sizeof(names) / sizeof(const char*) && (XInputGetStateSRC == NULL || XInputGetStateSRC != NULL); i++) { + RGFW_XInput_dll = LoadLibraryA(names[i]); + RGFW_PROC_DEF(RGFW_XInput_dll, XInputGetState); + RGFW_PROC_DEF(RGFW_XInput_dll, XInputGetKeystroke); } - #endif - RGFWDEF void RGFW_init_buffer(RGFW_window* win); - void RGFW_init_buffer(RGFW_window* win) { + #ifdef RGFW_DEBUG + if (XInputGetStateSRC == NULL) + printf("RGFW ERR: Failed to load XInputGetState\n"); + if (XInputGetKeystrokeSRC == NULL) + printf("RGFW ERR: Failed to load XInputGetKeystroke\n"); + #endif +} +#endif + +RGFWDEF void RGFW_init_buffer(RGFW_window* win); +void RGFW_init_buffer(RGFW_window* win) { #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0) RGFW_bufferSize = RGFW_getScreenSize(); - + BITMAPV5HEADER bi = { 0 }; ZeroMemory(&bi, sizeof(bi)); bi.bV5Size = sizeof(bi); @@ -5230,129 +5544,149 @@ static HMODULE wglinstance = NULL; (void**) &win->buffer, NULL, (DWORD) 0); - + win->src.hdcMem = CreateCompatibleDC(win->src.hdc); #if defined(RGFW_OSMESA) win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL); OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h); #endif -#else -RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ -#endif - } + #else + RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ + #endif +} - void RGFW_window_setDND(RGFW_window* win, b8 allow) { - DragAcceptFiles(win->src.window, allow); - } +void RGFW_window_setDND(RGFW_window* win, b8 allow) { + DragAcceptFiles(win->src.window, allow); +} - void RGFW_releaseCursor(RGFW_window* win) { - RGFW_UNUSED(win); - ClipCursor(NULL); - const RAWINPUTDEVICE id = { 0x01, 0x02, RIDEV_REMOVE, NULL }; - RegisterRawInputDevices(&id, 1, sizeof(id)); - } +void RGFW_releaseCursor(RGFW_window* win) { + RGFW_UNUSED(win); + ClipCursor(NULL); + const RAWINPUTDEVICE id = { 0x01, 0x02, RIDEV_REMOVE, NULL }; + RegisterRawInputDevices(&id, 1, sizeof(id)); +} - void RGFW_captureCursor(RGFW_window* win, RGFW_rect rect) { - RGFW_UNUSED(win); RGFW_UNUSED(rect); +void RGFW_captureCursor(RGFW_window* win, RGFW_rect rect) { + RGFW_UNUSED(win); RGFW_UNUSED(rect); - RECT clipRect; - GetClientRect(win->src.window, &clipRect); - ClientToScreen(win->src.window, (POINT*) &clipRect.left); - ClientToScreen(win->src.window, (POINT*) &clipRect.right); - ClipCursor(&clipRect); + RECT clipRect; + GetClientRect(win->src.window, &clipRect); + ClientToScreen(win->src.window, (POINT*) &clipRect.left); + ClientToScreen(win->src.window, (POINT*) &clipRect.right); + ClipCursor(&clipRect); - const RAWINPUTDEVICE id = { 0x01, 0x02, 0, win->src.window }; - RegisterRawInputDevices(&id, 1, sizeof(id)); - } + const RAWINPUTDEVICE id = { 0x01, 0x02, 0, win->src.window }; + RegisterRawInputDevices(&id, 1, sizeof(id)); +} - RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) { - #ifndef RGFW_NO_XINPUT +#define RGFW_LOAD_LIBRARY(x, lib) if (x == NULL) x = LoadLibraryA(lib) + +u32 RGFW_windowsOpen = 0; + +RGFW_window* RGFW_createWindowPtr(const char* name, RGFW_rect rect, RGFW_windowFlags flags, RGFW_window* win) { + #ifndef RGFW_NO_XINPUT if (RGFW_XInput_dll == NULL) RGFW_loadXInput(); - #endif + #endif - #ifndef RGFW_NO_DPI - if (RGFW_Shcore_dll == NULL) { - RGFW_Shcore_dll = LoadLibraryA("shcore.dll"); - GetDpiForMonitorSRC = (PFN_GetDpiForMonitor)(void*)GetProcAddress(RGFW_Shcore_dll, "GetDpiForMonitor"); + #ifndef RGFW_NO_DPI + RGFW_LOAD_LIBRARY(RGFW_Shcore_dll, "shcore.dll"); + RGFW_PROC_DEF(RGFW_Shcore_dll, GetDpiForMonitor); + #if (_WIN32_WINNT >= 0x0600) SetProcessDPIAware(); - } #endif + #endif - if (wglinstance == NULL) { - wglinstance = LoadLibraryA("opengl32.dll"); -#ifdef RGFW_WGL_LOAD - wglCreateContextSRC = (PFN_wglCreateContext) GetProcAddress(wglinstance, "wglCreateContext"); - wglDeleteContextSRC = (PFN_wglDeleteContext) GetProcAddress(wglinstance, "wglDeleteContext"); - wglGetProcAddressSRC = (PFN_wglGetProcAddress) GetProcAddress(wglinstance, "wglGetProcAddress"); - wglMakeCurrentSRC = (PFN_wglMakeCurrent) GetProcAddress(wglinstance, "wglMakeCurrent"); - wglGetCurrentDCSRC = (PFN_wglGetCurrentDC) GetProcAddress(wglinstance, "wglGetCurrentDC"); - wglGetCurrentContextSRC = (PFN_wglGetCurrentContext) GetProcAddress(wglinstance, "wglGetCurrentContext"); -#endif - } + #if !defined(RGFW_NO_LOAD_WINMM) && !defined(RGFW_NO_WINMM) + RGFW_LOAD_LIBRARY(RGFW_winmm_dll, "winmm.dll"); + RGFW_PROC_DEF(RGFW_winmm_dll, timeBeginPeriod); + #endif + + #ifndef RGFW_NO_DWM + RGFW_LOAD_LIBRARY(RGFW_dwm_dll, "dwmapi.dll"); + RGFW_PROC_DEF(RGFW_dwm_dll, DwmEnableBlurBehindWindow); + #endif + + RGFW_LOAD_LIBRARY(RGFW_wgl_dll, "opengl32.dll"); + #ifndef RGFW_NO_LOAD_WGL + RGFW_PROC_DEF(RGFW_wgl_dll, wglCreateContext); + RGFW_PROC_DEF(RGFW_wgl_dll, wglDeleteContext); + RGFW_PROC_DEF(RGFW_wgl_dll, wglDeleteContext); + RGFW_PROC_DEF(RGFW_wgl_dll, wglGetProcAddress); + RGFW_PROC_DEF(RGFW_wgl_dll, wglMakeCurrent); + RGFW_PROC_DEF(RGFW_wgl_dll, wglGetCurrentDC); + RGFW_PROC_DEF(RGFW_wgl_dll, wglGetCurrentContext); + RGFW_PROC_DEF(RGFW_wgl_dll, wglShareLists); + #endif + + if (name[0] == 0) name = (char*) " "; + + RGFW_eventWindow.r = RGFW_RECT(-1, -1, -1, -1); + RGFW_eventWindow.src.window = NULL; + + RGFW_window_basic_init(win, rect, flags); + + win->src.maxSize = RGFW_AREA(0, 0); + win->src.minSize = RGFW_AREA(0, 0); + + + HINSTANCE inh = GetModuleHandleA(NULL); + + #ifndef __cplusplus + WNDCLASSA Class = { 0 }; /*!< Setup the Window class. */ + #else + WNDCLASSA Class = { }; + #endif + + if (RGFW_className == NULL) + RGFW_className = (char*)name; + + Class.lpszClassName = RGFW_className; + Class.hInstance = inh; + Class.hCursor = LoadCursor(NULL, IDC_ARROW); + Class.lpfnWndProc = WndProc; + + Class.hIcon = (HICON)LoadImageA(GetModuleHandleW(NULL), "RGFW_ICON", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); + if (Class.hIcon == NULL) { + Class.hIcon = (HICON)LoadImageA(NULL, (LPCSTR)IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); + } + + RegisterClassA(&Class); + + DWORD window_style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN; + + RECT windowRect, clientRect; + + if (!(flags & RGFW_windowNoBorder)) { + window_style |= WS_CAPTION | WS_SYSMENU | WS_BORDER | WS_MINIMIZEBOX; + + if (!(flags & RGFW_windowNoResize)) + window_style |= WS_SIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME; + } else + window_style |= WS_POPUP | WS_VISIBLE | WS_SYSMENU | WS_MINIMIZEBOX; + + HWND dummyWin = CreateWindowA(Class.lpszClassName, name, window_style, win->r.x, win->r.y, win->r.w, win->r.h, 0, 0, inh, 0); + GetWindowRect(dummyWin, &windowRect); + GetClientRect(dummyWin, &clientRect); + + win->src.hOffset = (windowRect.bottom - windowRect.top) - (clientRect.bottom - clientRect.top); + win->src.window = CreateWindowA(Class.lpszClassName, name, window_style, win->r.x, win->r.y, win->r.w, win->r.h + win->src.hOffset, 0, 0, inh, 0); - if (name[0] == 0) name = (char*) " "; + if (flags & RGFW_windowAllowDND) { + win->_flags |= RGFW_windowAllowDND; + RGFW_window_setDND(win, 1); + } + win->src.hdc = GetDC(win->src.window); - RGFW_eventWindow.r = RGFW_RECT(-1, -1, -1, -1); - RGFW_eventWindow.src.window = NULL; - - RGFW_window* win = RGFW_window_basic_init(rect, args); - - win->src.maxSize = RGFW_AREA(0, 0); - win->src.minSize = RGFW_AREA(0, 0); - - - HINSTANCE inh = GetModuleHandleA(NULL); - - #ifndef __cplusplus - WNDCLASSA Class = { 0 }; /*!< Setup the Window class. */ - #else - WNDCLASSA Class = { }; - #endif - - if (RGFW_className == NULL) - RGFW_className = (char*)name; - - Class.lpszClassName = RGFW_className; - Class.hInstance = inh; - Class.hCursor = LoadCursor(NULL, IDC_ARROW); - Class.lpfnWndProc = WndProc; - - RegisterClassA(&Class); - - DWORD window_style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN; - - RECT windowRect, clientRect; - - if (!(args & RGFW_NO_BORDER)) { - window_style |= WS_CAPTION | WS_SYSMENU | WS_BORDER | WS_MINIMIZEBOX; - - if (!(args & RGFW_NO_RESIZE)) - window_style |= WS_SIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME; - } else - window_style |= WS_POPUP | WS_VISIBLE | WS_SYSMENU | WS_MINIMIZEBOX; - - HWND dummyWin = CreateWindowA(Class.lpszClassName, name, window_style, win->r.x, win->r.y, win->r.w, win->r.h, 0, 0, inh, 0); - - GetWindowRect(dummyWin, &windowRect); - GetClientRect(dummyWin, &clientRect); - - win->src.hOffset = (windowRect.bottom - windowRect.top) - (clientRect.bottom - clientRect.top); - win->src.window = CreateWindowA(Class.lpszClassName, name, window_style, win->r.x, win->r.y, win->r.w, win->r.h + win->src.hOffset, 0, 0, inh, 0); - - if (args & RGFW_ALLOW_DND) { - win->_winArgs |= RGFW_ALLOW_DND; - RGFW_window_setDND(win, 1); - } - win->src.hdc = GetDC(win->src.window); - - if ((args & RGFW_NO_INIT_API) == 0) { -#ifdef RGFW_DIRECTX - assert(FAILED(CreateDXGIFactory(&__uuidof(IDXGIFactory), (void**) &RGFW_dxInfo.pFactory)) == 0); + if ((flags & RGFW_windowNoInitAPI) == 0) { + #ifdef RGFW_DIRECTX + RGFW_ASSERT(FAILED(CreateDXGIFactory(&__uuidof(IDXGIFactory), (void**) &RGFW_dxInfo.pFactory)) == 0); if (FAILED(RGFW_dxInfo.pFactory->lpVtbl->EnumAdapters(RGFW_dxInfo.pFactory, 0, &RGFW_dxInfo.pAdapter))) { - fprintf(stderr, "Failed to enumerate DXGI adapters\n"); + #ifdef RGFW_DEBUG + fprintf(stderr, "Failed to enumerate DXGI adapters\n"); + #endif RGFW_dxInfo.pFactory->lpVtbl->Release(RGFW_dxInfo.pFactory); return NULL; } @@ -5360,7 +5694,9 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0 }; if (FAILED(D3D11CreateDevice(RGFW_dxInfo.pAdapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, 0, featureLevels, 1, D3D11_SDK_VERSION, &RGFW_dxInfo.pDevice, NULL, &RGFW_dxInfo.pDeviceContext))) { - fprintf(stderr, "Failed to create Direct3D device\n"); + #ifdef RGFW_DEBUG + fprintf(stderr, "Failed to create Direct3D device\n"); + #endif RGFW_dxInfo.pAdapter->lpVtbl->Release(RGFW_dxInfo.pAdapter); RGFW_dxInfo.pFactory->lpVtbl->Release(RGFW_dxInfo.pFactory); return NULL; @@ -5407,32 +5743,34 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ pDepthStencilTexture->lpVtbl->Release(pDepthStencilTexture); RGFW_dxInfo.pDeviceContext->lpVtbl->OMSetRenderTargets(RGFW_dxInfo.pDeviceContext, 1, &win->src.renderTargetView, win->src.pDepthStencilView); -#endif + #endif -#ifdef RGFW_OPENGL + #ifdef RGFW_OPENGL HDC dummy_dc = GetDC(dummyWin); - - u32 pfd_flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; - - //if (RGFW_DOUBLE_BUFFER) + + u32 pfd_flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; + + //if (RGFW_DOUBLE_BUFFER) pfd_flags |= PFD_DOUBLEBUFFER; - - PIXELFORMATDESCRIPTOR pfd = { - sizeof(pfd), - 1, /* version */ - pfd_flags, - PFD_TYPE_RGBA, /* ipixel type */ - 24, /* color bits */ - 0, 0, 0, 0, 0, 0, - 8, /* alpha bits */ - 0, 0, 0, 0, 0, 0, - 32, /* depth bits */ - 8, /* stencil bits */ - 0, - PFD_MAIN_PLANE, /* Layer type */ - 0, 0, 0, 0 + + PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), // Size of the descriptor + 1, // Version + pfd_flags, // Flags to specify what the pixel format supports (e.g., PFD_SUPPORT_OPENGL) + PFD_TYPE_RGBA, // Pixel type is RGBA + 32, // Color bits (red, green, blue channels) + 0, 0, 0, 0, 0, 0, // No color bits for unused channels + 8, // Alpha bits (important for transparency) + 0, // No accumulation buffer bits needed + 0, 0, 0, 0, // No accumulation bits + 32, // Depth buffer bits + 8, // Stencil buffer bits + 0, // Auxiliary buffer bits (unused) + PFD_MAIN_PLANE, // Use the main plane for rendering + 0, 0, 0, 0, 0 // Reserved fields }; + int pixel_format = ChoosePixelFormat(dummy_dc, &pfd); SetPixelFormat(dummy_dc, pixel_format, &pfd); @@ -5447,41 +5785,45 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ wglMakeCurrent(dummy_dc, 0); wglDeleteContext(dummy_context); ReleaseDC(dummyWin, dummy_dc); - - /* try to create the pixel format we want for opengl and then try to create an opengl context for the specified version */ + + /* try to create the pixel format we want for opengl and then try to create an opengl context for the specified version */ if (wglCreateContextAttribsARB != NULL) { PIXELFORMATDESCRIPTOR pfd = {sizeof(pfd), 1, pfd_flags, PFD_TYPE_RGBA, 32, 8, PFD_MAIN_PLANE, 24, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - if (args & RGFW_OPENGL_SOFTWARE) + if (flags & RGFW_windowOpenglSoftware) pfd.dwFlags |= PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED; if (wglChoosePixelFormatARB != NULL) { - i32* pixel_format_attribs = (i32*)RGFW_initFormatAttribs(args & RGFW_OPENGL_SOFTWARE); + i32* pixel_format_attribs = (i32*)RGFW_initFormatAttribs(flags & RGFW_windowOpenglSoftware); int pixel_format; UINT num_formats; wglChoosePixelFormatARB(win->src.hdc, pixel_format_attribs, 0, 1, &pixel_format, &num_formats); if (!num_formats) { + #ifdef RGFW_DEBUG printf("Failed to create a pixel format for WGL.\n"); + #endif } DescribePixelFormat(win->src.hdc, pixel_format, sizeof(pfd), &pfd); if (!SetPixelFormat(win->src.hdc, pixel_format, &pfd)) { + #ifdef RGFW_DEBUG printf("Failed to set the WGL pixel format.\n"); + #endif } } - - /* create opengl/WGL context for the specified version */ + + /* create opengl/WGL context for the specified version */ u32 index = 0; i32 attribs[40]; - if (RGFW_profile == RGFW_GL_CORE) { + if (RGFW_profile == RGFW_glCore) { SET_ATTRIB(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB); } else { SET_ATTRIB(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB); } - + if (RGFW_majorVersion || RGFW_minorVersion) { SET_ATTRIB(WGL_CONTEXT_MAJOR_VERSION_ARB, RGFW_majorVersion); SET_ATTRIB(WGL_CONTEXT_MINOR_VERSION_ARB, RGFW_minorVersion); @@ -5491,1158 +5833,1260 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ win->src.ctx = (HGLRC)wglCreateContextAttribsARB(win->src.hdc, NULL, attribs); } else { /* fall back to a default context (probably opengl 2 or something) */ + #ifdef RGFW_DEBUG fprintf(stderr, "Failed to create an accelerated OpenGL Context\n"); + #endif int pixel_format = ChoosePixelFormat(win->src.hdc, &pfd); SetPixelFormat(win->src.hdc, pixel_format, &pfd); win->src.ctx = wglCreateContext(win->src.hdc); } - + wglMakeCurrent(win->src.hdc, win->src.ctx); -#endif + #endif } -#ifdef RGFW_OSMESA -#ifdef RGFW_LINK_OSM ESA - OSMesaMakeCurrentSource = (PFN_OSMesaMakeCurrent) GetProcAddress(win->src.hdc, "OSMesaMakeCurrent"); - OSMesaCreateContextSource = (PFN_OSMesaCreateContext) GetProcAddress(win->src.hdc, "OSMesaCreateContext"); - OSMesaDestroyContextSource = (PFN_OSMesaDestroyContext) GetProcAddress(win->src.hdc, "OSMesaDestroyContext"); -#endif -#endif - -#ifdef RGFW_OPENGL - if ((args & RGFW_NO_INIT_API) == 0) { + #ifdef RGFW_OPENGL + if ((flags & RGFW_windowNoInitAPI) == 0) { ReleaseDC(win->src.window, win->src.hdc); win->src.hdc = GetDC(win->src.window); wglMakeCurrent(win->src.hdc, win->src.ctx); } -#endif + #endif - DestroyWindow(dummyWin); - RGFW_init_buffer(win); + DestroyWindow(dummyWin); + RGFW_init_buffer(win); - #ifndef RGFW_NO_MONITOR - if (args & RGFW_SCALE_TO_MONITOR) - RGFW_window_scaleToMonitor(win); - #endif - - if (args & RGFW_CENTER) { - RGFW_area screenR = RGFW_getScreenSize(); - RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2)); - } + #ifndef RGFW_NO_MONITOR + if (flags & RGFW_windowScaleToMonitor) + RGFW_window_scaleToMonitor(win); + #endif -#ifdef RGFW_EGL - if ((args & RGFW_NO_INIT_API) == 0) + if (flags & RGFW_windowCenter) { + RGFW_area screenR = RGFW_getScreenSize(); + RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2)); + } + + #ifdef RGFW_EGL + if ((flags & RGFW_windowNoInitAPI) == 0) RGFW_createOpenGLContext(win); -#endif + #endif - if (args & RGFW_HIDE_MOUSE) - RGFW_window_showMouse(win, 0); + if (flags & RGFW_windowHideMouse) + RGFW_window_showMouse(win, 0); - if (args & RGFW_TRANSPARENT_WINDOW) { - SetWindowLong(win->src.window, GWL_EXSTYLE, GetWindowLong(win->src.window, GWL_EXSTYLE) | WS_EX_LAYERED); - SetLayeredWindowAttributes(win->src.window, RGB(255, 255, 255), RGFW_ALPHA, LWA_ALPHA); - } - - ShowWindow(win->src.window, SW_SHOWNORMAL); - - if (RGFW_root == NULL) - RGFW_root = win; - - #ifdef RGFW_OPENGL - else - wglShareLists(RGFW_root->src.ctx, win->src.ctx); + if (flags & RGFW_windowTransparent) { + if (DwmEnableBlurBehindWindowSRC != NULL) { + #ifndef RGFW_NO_DWM + DWM_BLURBEHIND bb = {0, 0, 0, 0}; + bb.dwFlags = 0x1; + bb.fEnable = TRUE; + bb.hRgnBlur = NULL; + DwmEnableBlurBehindWindowSRC(win->src.window, &bb); #endif - - return win; - } - - void RGFW_window_setBorder(RGFW_window* win, u8 border) { - DWORD style = GetWindowLong(win->src.window, GWL_STYLE); - - if (border == 0) { - SetWindowLong(win->src.window, GWL_STYLE, style & ~WS_OVERLAPPEDWINDOW); - SetWindowPos( - win->src.window, HWND_TOP, 0, 0, 0, 0, - SWP_NOZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE - ); - } - else { - SetWindowLong(win->src.window, GWL_STYLE, style | WS_OVERLAPPEDWINDOW); - SetWindowPos( - win->src.window, HWND_TOP, 0, 0, 0, 0, - SWP_NOZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE - ); + } else { + SetWindowLong(win->src.window, GWL_EXSTYLE, WS_EX_LAYERED); + SetLayeredWindowAttributes(win->src.window, 0, 128, LWA_ALPHA); } } + ShowWindow(win->src.window, SW_SHOWNORMAL); - RGFW_area RGFW_getScreenSize(void) { - return RGFW_AREA(GetDeviceCaps(GetDC(NULL), HORZRES), GetDeviceCaps(GetDC(NULL), VERTRES)); + #ifdef RGFW_OPENGL + if (RGFW_root != win) + wglShareLists(RGFW_root->src.ctx, win->src.ctx); + #endif + + #ifdef RGFW_DEBUG + printf("RGFW INFO: a window with a rect of {%i, %i, %i, %i} \n", win->r.x, win->r.y, win->r.w, win->r.h); + #endif + + RGFW_windowsOpen++; + + return win; +} + +void RGFW_window_setBorder(RGFW_window* win, u8 border) { + DWORD style = GetWindowLong(win->src.window, GWL_STYLE); + + if (border == 0) { + SetWindowLong(win->src.window, GWL_STYLE, style & ~WS_OVERLAPPEDWINDOW); + SetWindowPos( + win->src.window, HWND_TOP, 0, 0, 0, 0, + SWP_NOZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE + ); } - - RGFW_point RGFW_getGlobalMousePoint(void) { - POINT p; - GetCursorPos(&p); - - return RGFW_POINT(p.x, p.y); - } - - RGFW_point RGFW_window_getMousePoint(RGFW_window* win) { - POINT p; - GetCursorPos(&p); - ScreenToClient(win->src.window, &p); - - return RGFW_POINT(p.x, p.y); - } - - void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) { - assert(win != NULL); - win->src.minSize = a; - } - - void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) { - assert(win != NULL); - win->src.maxSize = a; + else { + SetWindowLong(win->src.window, GWL_STYLE, style | WS_OVERLAPPEDWINDOW); + SetWindowPos( + win->src.window, HWND_TOP, 0, 0, 0, 0, + SWP_NOZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE + ); } +} - void RGFW_window_minimize(RGFW_window* win) { - assert(win != NULL); +RGFW_area RGFW_getScreenSize(void) { + HDC dc = GetDC(NULL); + RGFW_area area = RGFW_AREA(GetDeviceCaps(dc, HORZRES), GetDeviceCaps(dc, VERTRES)); + ReleaseDC(NULL, dc); + return area; +} - ShowWindow(win->src.window, SW_MINIMIZE); - } +RGFW_point RGFW_getGlobalMousePoint(void) { + POINT p; + GetCursorPos(&p); - void RGFW_window_restore(RGFW_window* win) { - assert(win != NULL); + return RGFW_POINT(p.x, p.y); +} - ShowWindow(win->src.window, SW_RESTORE); - } +RGFW_point RGFW_window_getMousePoint(RGFW_window* win) { + POINT p; + GetCursorPos(&p); + ScreenToClient(win->src.window, &p); + + return RGFW_POINT(p.x, p.y); +} + +void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) { + RGFW_ASSERT(win != NULL); + win->src.minSize = a; +} + +void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) { + RGFW_ASSERT(win != NULL); + win->src.maxSize = a; +} - u8 RGFW_xinput2RGFW[] = { - RGFW_JS_A, /* or PS X button */ - RGFW_JS_B, /* or PS circle button */ - RGFW_JS_X, /* or PS square button */ - RGFW_JS_Y, /* or PS triangle button */ - RGFW_JS_R1, /* right bumper */ - RGFW_JS_L1, /* left bump */ - RGFW_JS_L2, /* left trigger*/ - RGFW_JS_R2, /* right trigger */ - 0, 0, 0, 0, 0, 0, 0, 0, - RGFW_JS_UP, /* dpad up */ - RGFW_JS_DOWN, /* dpad down*/ - RGFW_JS_LEFT, /* dpad left */ - RGFW_JS_RIGHT, /* dpad right */ - RGFW_JS_START, /* start button */ - RGFW_JS_SELECT/* select button */ - }; +void RGFW_window_minimize(RGFW_window* win) { + RGFW_ASSERT(win != NULL); - static i32 RGFW_checkXInput(RGFW_window* win, RGFW_Event* e) { - RGFW_UNUSED(win) - - size_t i; - for (i = 0; i < 4; i++) { - XINPUT_KEYSTROKE keystroke; + ShowWindow(win->src.window, SW_MINIMIZE); +} - if (XInputGetKeystroke == NULL) +void RGFW_window_restore(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + + ShowWindow(win->src.window, SW_RESTORE); +} + +u8 RGFW_xinput2RGFW[] = { + RGFW_gamepadA, /* or PS X button */ + RGFW_gamepadB, /* or PS circle button */ + RGFW_gamepadX, /* or PS square button */ + RGFW_gamepadY, /* or PS triangle button */ + RGFW_gamepadR1, /* right bumper */ + RGFW_gamepadL1, /* left bump */ + RGFW_gamepadL2, /* left trigger*/ + RGFW_gamepadR2, /* right trigger */ + 0, 0, 0, 0, 0, 0, 0, 0, + RGFW_gamepadUp, /* dpad up */ + RGFW_gamepadDown, /* dpad down*/ + RGFW_gamepadLeft, /* dpad left */ + RGFW_gamepadRight, /* dpad right */ + RGFW_gamepadStart, /* start button */ + RGFW_gamepadSelect,/* select button */ + RGFW_gamepadL3, + RGFW_gamepadR3, +}; + +static i32 RGFW_checkXInput(RGFW_window* win, RGFW_event* e) { + #ifndef RGFW_NO_XINPUT + + RGFW_UNUSED(win); + size_t i; + for (i = 0; i < 4; i++) { + XINPUT_KEYSTROKE keystroke; + + if (XInputGetKeystroke == NULL) + return 0; + + DWORD result = XInputGetKeystroke((DWORD)i, 0, &keystroke); + + if ((keystroke.Flags & XINPUT_KEYSTROKE_REPEAT) == 0 && result != ERROR_EMPTY) { + if (result != ERROR_SUCCESS) return 0; - DWORD result = XInputGetKeystroke((DWORD)i, 0, &keystroke); + if (keystroke.VirtualKey > VK_PAD_RTHUMB_PRESS) + continue; - if ((keystroke.Flags & XINPUT_KEYSTROKE_REPEAT) == 0 && result != ERROR_EMPTY) { - if (result != ERROR_SUCCESS) - return 0; + //gamepad + 1 = RGFW_gamepadButtonReleased + e->type = RGFW_gamepadButtonPressed + !(keystroke.Flags & XINPUT_KEYSTROKE_KEYDOWN); + e->button = RGFW_xinput2RGFW[keystroke.VirtualKey - 0x5800]; + RGFW_gamepadPressed[i][e->button].prev = RGFW_gamepadPressed[i][e->button].current; + RGFW_gamepadPressed[i][e->button].current = (keystroke.Flags & XINPUT_KEYSTROKE_KEYDOWN); - if (keystroke.VirtualKey > VK_PAD_BACK) - continue; + RGFW_gamepadButtonCallback(win, i, e->button, e->type == RGFW_gamepadButtonPressed); + return 1; + } - // RGFW_jsButtonPressed + 1 = RGFW_jsButtonReleased - e->type = RGFW_jsButtonPressed + !(keystroke.Flags & XINPUT_KEYSTROKE_KEYDOWN); - e->button = RGFW_xinput2RGFW[keystroke.VirtualKey - 0x5800]; - RGFW_jsPressed[i][e->button] = !(keystroke.Flags & XINPUT_KEYSTROKE_KEYDOWN); + XINPUT_STATE state; + if (XInputGetState == NULL || + XInputGetState((DWORD) i, &state) == ERROR_DEVICE_NOT_CONNECTED + ) { + if (RGFW_gamepads[i] == 0) + continue; - return 1; - } + RGFW_gamepads[i] = 0; + RGFW_gamepadCount--; + + win->event.type = RGFW_gamepadDisconnected; + win->event.gamepad = i; + RGFW_gamepadCallback(win, i, 0); + return 1; + } + + if (RGFW_gamepads[i] == 0) { + RGFW_gamepads[i] = 1; + RGFW_gamepadCount++; + + char str[] = "Microsoft X-Box (XInput device)"; + RGFW_MEMCPY(RGFW_gamepads_name[i], str, sizeof(str)); + RGFW_gamepads_name[i][sizeof(RGFW_gamepads_name[i]) - 1] = '\0'; + win->event.type = RGFW_gamepadConnected; + win->event.gamepad = i; + RGFW_gamepads_type[i] = RGFW_gamepadMicrosoft; + + RGFW_gamepadCallback(win, i, 1); + return 1; + } - XINPUT_STATE state; - if (XInputGetState == NULL || - XInputGetState((DWORD) i, &state) == ERROR_DEVICE_NOT_CONNECTED - ) - return 0; #define INPUT_DEADZONE ( 0.24f * (float)(0x7FFF) ) // Default to 24% of the +/- 32767 range. This is a reasonable default value but can be altered if needed. - if ((state.Gamepad.sThumbLX < INPUT_DEADZONE && - state.Gamepad.sThumbLX > -INPUT_DEADZONE) && - (state.Gamepad.sThumbLY < INPUT_DEADZONE && - state.Gamepad.sThumbLY > -INPUT_DEADZONE)) - { - state.Gamepad.sThumbLX = 0; - state.Gamepad.sThumbLY = 0; - } + if ((state.Gamepad.sThumbLX < INPUT_DEADZONE && + state.Gamepad.sThumbLX > -INPUT_DEADZONE) && + (state.Gamepad.sThumbLY < INPUT_DEADZONE && + state.Gamepad.sThumbLY > -INPUT_DEADZONE)) + { + state.Gamepad.sThumbLX = 0; + state.Gamepad.sThumbLY = 0; + } - if ((state.Gamepad.sThumbRX < INPUT_DEADZONE && - state.Gamepad.sThumbRX > -INPUT_DEADZONE) && - (state.Gamepad.sThumbRY < INPUT_DEADZONE && - state.Gamepad.sThumbRY > -INPUT_DEADZONE)) - { - state.Gamepad.sThumbRX = 0; - state.Gamepad.sThumbRY = 0; - } + if ((state.Gamepad.sThumbRX < INPUT_DEADZONE && + state.Gamepad.sThumbRX > -INPUT_DEADZONE) && + (state.Gamepad.sThumbRY < INPUT_DEADZONE && + state.Gamepad.sThumbRY > -INPUT_DEADZONE)) + { + state.Gamepad.sThumbRX = 0; + state.Gamepad.sThumbRY = 0; + } - e->axisesCount = 2; - RGFW_point axis1 = RGFW_POINT(state.Gamepad.sThumbLX, state.Gamepad.sThumbLY); - RGFW_point axis2 = RGFW_POINT(state.Gamepad.sThumbRX, state.Gamepad.sThumbRY); + e->axisesCount = 2; + RGFW_point axis1 = RGFW_POINT(((float)state.Gamepad.sThumbLX / 32768.0f) * 100, ((float)state.Gamepad.sThumbLY / -32768.0f) * 100); + RGFW_point axis2 = RGFW_POINT(((float)state.Gamepad.sThumbRX / 32768.0f) * 100, ((float)state.Gamepad.sThumbRY / -32768.0f) * 100); - if (axis1.x != e->axis[0].x || axis1.y != e->axis[0].y || axis2.x != e->axis[1].x || axis2.y != e->axis[1].y) { - e->type = RGFW_jsAxisMove; - - e->axis[0] = axis1; - e->axis[1] = axis2; - - return 1; - } + if (axis1.x != e->axis[0].x || axis1.y != e->axis[0].y){ + win->event.whichAxis = 0; + e->type = RGFW_gamepadAxisMove; e->axis[0] = axis1; + RGFW_gamepadAxes[i][0] = e->axis[0]; + + RGFW_gamepadAxisCallback(win, e->gamepad, e->axis, e->axisesCount, e->whichAxis); + return 1; + } + + if (axis2.x != e->axis[1].x || axis2.y != e->axis[1].y) { + win->event.whichAxis = 1; + e->type = RGFW_gamepadAxisMove; e->axis[1] = axis2; - } + RGFW_gamepadAxes[i][1] = e->axis[1]; - return 0; + RGFW_gamepadAxisCallback(win, e->gamepad, e->axis, e->axisesCount, e->whichAxis); + return 1; + } } - void RGFW_stopCheckEvents(void) { - PostMessageW(RGFW_root->src.window, WM_NULL, 0, 0); + #endif + + return 0; +} + +void RGFW_stopCheckEvents(void) { + PostMessageW(RGFW_root->src.window, WM_NULL, 0, 0); +} + +void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) { + RGFW_UNUSED(win); + + MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD) (waitMS * 1e3), QS_ALLINPUT); +} + +RGFW_event* RGFW_window_checkEvent(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + + if (win->event.type == RGFW_quit) { + return NULL; } - void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) { - RGFW_UNUSED(win); + MSG msg; - MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD) (waitMS * 1e3), QS_ALLINPUT); + if (RGFW_eventWindow.src.window == win->src.window) { + if (RGFW_eventWindow.r.x != -1) { + win->r.x = RGFW_eventWindow.r.x; + win->r.y = RGFW_eventWindow.r.y; + win->event.type = RGFW_windowMoved; + RGFW_windowMoveCallback(win, win->r); + } + + if (RGFW_eventWindow.r.w != -1) { + win->r.w = RGFW_eventWindow.r.w; + win->r.h = RGFW_eventWindow.r.h; + win->event.type = RGFW_windowResized; + RGFW_windowResizeCallback(win, win->r); + } + + RGFW_eventWindow.src.window = NULL; + RGFW_eventWindow.r = RGFW_RECT(-1, -1, -1, -1); + + return &win->event; } - RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) { - assert(win != NULL); - if (win->event.type == RGFW_quit) { - return NULL; - } - - MSG msg; - - if (RGFW_eventWindow.src.window == win->src.window) { - if (RGFW_eventWindow.r.x != -1) { - win->r.x = RGFW_eventWindow.r.x; - win->r.y = RGFW_eventWindow.r.y; - win->event.type = RGFW_windowMoved; - RGFW_windowMoveCallback(win, win->r); - } - - if (RGFW_eventWindow.r.w != -1) { - win->r.w = RGFW_eventWindow.r.w; - win->r.h = RGFW_eventWindow.r.h; - win->event.type = RGFW_windowResized; - RGFW_windowResizeCallback(win, win->r); - } - - RGFW_eventWindow.src.window = NULL; - RGFW_eventWindow.r = RGFW_RECT(-1, -1, -1, -1); - - return &win->event; - } - - - static HDROP drop; - - if (win->event.type == RGFW_dnd_init) { - if (win->event.droppedFilesCount) { - u32 i; - for (i = 0; i < win->event.droppedFilesCount; i++) - win->event.droppedFiles[i][0] = '\0'; - } - - win->event.droppedFilesCount = 0; - win->event.droppedFilesCount = DragQueryFileW(drop, 0xffffffff, NULL, 0); - //win->event.droppedFiles = (char**)RGFW_CALLOC(win->event.droppedFilesCount, sizeof(char*)); + static HDROP drop; + if (win->event.type == RGFW_DNDInit) { + if (win->event.droppedFilesCount) { u32 i; - for (i = 0; i < win->event.droppedFilesCount; i++) { - const UINT length = DragQueryFileW(drop, i, NULL, 0); - WCHAR* buffer = (WCHAR*) RGFW_CALLOC((size_t) length + 1, sizeof(WCHAR)); - - DragQueryFileW(drop, i, buffer, length + 1); - strncpy(win->event.droppedFiles[i], createUTF8FromWideStringWin32(buffer), RGFW_MAX_PATH); - win->event.droppedFiles[i][RGFW_MAX_PATH - 1] = '\0'; - RGFW_FREE(buffer); - } - - DragFinish(drop); - RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount); - - win->event.type = RGFW_dnd; - return &win->event; + for (i = 0; i < win->event.droppedFilesCount; i++) + win->event.droppedFiles[i][0] = '\0'; } - win->event.inFocus = (GetForegroundWindow() == win->src.window); + win->event.droppedFilesCount = 0; + win->event.droppedFilesCount = DragQueryFileW(drop, 0xffffffff, NULL, 0); - if (RGFW_checkXInput(win, &win->event)) - return &win->event; + u32 i; + for (i = 0; i < win->event.droppedFilesCount; i++) { + UINT length = DragQueryFileW(drop, i, NULL, 0); + if (length == 0) + continue; - static BYTE keyboardState[256]; + WCHAR buffer[RGFW_MAX_PATH * 2]; + if (length > (RGFW_MAX_PATH * 2) - 1) + length = RGFW_MAX_PATH * 2; - if (PeekMessageA(&msg, win->src.window, 0u, 0u, PM_REMOVE)) { - switch (msg.message) { - case WM_CLOSE: - case WM_QUIT: - RGFW_windowQuitCallback(win); - win->event.type = RGFW_quit; + DragQueryFileW(drop, i, buffer, length + 1); + + char* str = RGFW_createUTF8FromWideStringWin32(buffer); + if (str != NULL) + RGFW_MEMCPY(win->event.droppedFiles[i], str, length + 1); + + win->event.droppedFiles[i][RGFW_MAX_PATH - 1] = '\0'; + } + + DragFinish(drop); + RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount); + + win->event.type = RGFW_DND; + return &win->event; + } + + win->event.inFocus = (GetForegroundWindow() == win->src.window); + + if (RGFW_checkXInput(win, &win->event)) + return &win->event; + + static BYTE keyboardState[256]; + GetKeyboardState(keyboardState); + + + if (!IsWindow(win->src.window)) { + win->event.type = RGFW_quit; + RGFW_windowQuitCallback(win); + return &win->event; + } + + if (PeekMessageA(&msg, win->src.window, 0u, 0u, PM_REMOVE) == 0) + return NULL; + + switch (msg.message) { + case WM_CLOSE: + case WM_QUIT: + RGFW_windowQuitCallback(win); + win->event.type = RGFW_quit; + break; + + case WM_ACTIVATE: + win->event.inFocus = (LOWORD(msg.wParam) == WA_INACTIVE); + + if (win->event.inFocus) { + win->event.type = RGFW_focusIn; + RGFW_focusCallback(win, 1); + } + else { + win->event.type = RGFW_focusOut; + RGFW_focusCallback(win, 0); + } + + break; + + case WM_PAINT: + win->event.type = RGFW_windowRefresh; + RGFW_windowRefreshCallback(win); + break; + + case WM_MOUSELEAVE: + win->event.type = RGFW_mouseLeave; + win->_flags |= RGFW_MOUSE_LEFT; + RGFW_mouseNotifyCallBack(win, win->event.point, 0); + break; + + case WM_KEYUP: { + i32 scancode = (HIWORD(msg.lParam) & (KF_EXTENDED | 0xff)); + if (scancode == 0) + scancode = MapVirtualKeyW((u32)msg.wParam, MAPVK_VK_TO_VSC); + + switch (scancode) { + case 0x54: scancode = 0x137; break; /* Alt+PrtS */ + case 0x146: scancode = 0x45; break; /* Ctrl+Pause */ + case 0x136: scancode = 0x36; break; /* CJK IME sets the extended bit for right Shift */ + default: break; + } + + win->event.key = RGFW_apiKeyToRGFW((u32) scancode); + + if (msg.wParam == VK_CONTROL) { + if (HIWORD(msg.lParam) & KF_EXTENDED) + win->event.key = RGFW_controlR; + else win->event.key = RGFW_controlL; + } + + wchar_t charBuffer; + ToUnicodeEx(msg.wParam, scancode, keyboardState, (wchar_t*)&charBuffer, 1, 0, NULL); + + win->event.keyChar = (u8)charBuffer; + + RGFW_keyboard[win->event.key].prev = RGFW_isPressed(win, win->event.key); + win->event.type = RGFW_keyReleased; + RGFW_keyboard[win->event.key].current = 0; + + RGFW_updateKeyMods(win, (GetKeyState(VK_CAPITAL) & 0x0001), (GetKeyState(VK_NUMLOCK) & 0x0001)); + + RGFW_keyCallback(win, win->event.key, win->event.keyChar, win->event.keyMod, 0); + break; + } + case WM_KEYDOWN: { + i32 scancode = (HIWORD(msg.lParam) & (KF_EXTENDED | 0xff)); + if (scancode == 0) + scancode = MapVirtualKeyW((u32)msg.wParam, MAPVK_VK_TO_VSC); + + switch (scancode) { + case 0x54: scancode = 0x137; break; /* Alt+PrtS */ + case 0x146: scancode = 0x45; break; /* Ctrl+Pause */ + case 0x136: scancode = 0x36; break; /* CJK IME sets the extended bit for right Shift */ + default: break; + } + + win->event.key = RGFW_apiKeyToRGFW((u32) scancode); + + if (msg.wParam == VK_CONTROL) { + if (HIWORD(msg.lParam) & KF_EXTENDED) + win->event.key = RGFW_controlR; + else win->event.key = RGFW_controlL; + } + + wchar_t charBuffer; + ToUnicodeEx(msg.wParam, scancode, keyboardState, &charBuffer, 1, 0, NULL); + win->event.keyChar = (u8)charBuffer; + + RGFW_keyboard[win->event.key].prev = RGFW_isPressed(win, win->event.key); + + win->event.type = RGFW_keyPressed; + win->event.repeat = RGFW_isPressed(win, win->event.key); + RGFW_keyboard[win->event.key].current = 1; + RGFW_updateKeyMods(win, (GetKeyState(VK_CAPITAL) & 0x0001), (GetKeyState(VK_NUMLOCK) & 0x0001)); + + RGFW_keyCallback(win, win->event.key, win->event.keyChar, win->event.keyMod, 1); + break; + } + + case WM_MOUSEMOVE: { + if ((win->_flags & RGFW_HOLD_MOUSE)) break; - case WM_ACTIVATE: - win->event.inFocus = (LOWORD(msg.wParam) == WA_INACTIVE); + win->event.type = RGFW_mousePosChanged; - if (win->event.inFocus) { - win->event.type = RGFW_focusIn; - RGFW_focusCallback(win, 1); + i32 x = GET_X_LPARAM(msg.lParam); + i32 y = GET_Y_LPARAM(msg.lParam); + + RGFW_mousePosCallback(win, win->event.point); + + if (win->_flags & RGFW_MOUSE_LEFT) { + win->_flags ^= RGFW_MOUSE_LEFT; + win->event.type = RGFW_mouseEnter; + RGFW_mouseNotifyCallBack(win, win->event.point, 1); + } + + /*if ((win->_flags & RGFW_HOLD_MOUSE)) { + RGFW_point p = RGFW_getGlobalMousePoint(); + //p = RGFW_POINT(p.x + win->r.x, p.y + win->r.y); + + win->event.point.x = x - win->_lastMousePoint.x; + win->event.point.y = y - win->_lastMousePoint.y; + + win->_lastMousePoint = RGFW_POINT(x, y); + break; + }*/ + + win->event.point.x = x; + win->event.point.y = y; + win->_lastMousePoint = RGFW_POINT(x, y); + + break; + } + case WM_INPUT: { + if (!(win->_flags & RGFW_HOLD_MOUSE)) + break; + + unsigned size = sizeof(RAWINPUT); + static RAWINPUT raw = {}; + + GetRawInputData((HRAWINPUT)msg.lParam, RID_INPUT, &raw, &size, sizeof(RAWINPUTHEADER)); + + if (raw.header.dwType != RIM_TYPEMOUSE || (raw.data.mouse.lLastX == 0 && raw.data.mouse.lLastY == 0) ) + break; + + if (raw.data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE) { + POINT pos = {0, 0}; + int width, height; + + if (raw.data.mouse.usFlags & MOUSE_VIRTUAL_DESKTOP) { + pos.x += GetSystemMetrics(SM_XVIRTUALSCREEN); + pos.y += GetSystemMetrics(SM_YVIRTUALSCREEN); + width = GetSystemMetrics(SM_CXVIRTUALSCREEN); + height = GetSystemMetrics(SM_CYVIRTUALSCREEN); } else { - win->event.type = RGFW_focusOut; - RGFW_focusCallback(win, 0); + width = GetSystemMetrics(SM_CXSCREEN); + height = GetSystemMetrics(SM_CYSCREEN); } - break; - - case WM_PAINT: - win->event.type = RGFW_windowRefresh; - RGFW_windowRefreshCallback(win); - break; - - case WM_MOUSELEAVE: - win->event.type = RGFW_mouseLeave; - win->_winArgs |= RGFW_MOUSE_LEFT; - RGFW_mouseNotifyCallBack(win, win->event.point, 0); - break; - - case WM_KEYUP: { - win->event.keyCode = RGFW_apiKeyCodeToRGFW((u32) msg.wParam); - - RGFW_keyboard[win->event.keyCode].prev = RGFW_isPressed(win, win->event.keyCode); + pos.x += (int) ((raw.data.mouse.lLastX / 65535.f) * width); + pos.y += (int) ((raw.data.mouse.lLastY / 65535.f) * height); + ScreenToClient(win->src.window, &pos); - static char keyName[16]; - - { - GetKeyNameTextA((LONG) msg.lParam, keyName, 16); - - if ((!(GetKeyState(VK_CAPITAL) & 0x0001) && !(GetKeyState(VK_SHIFT) & 0x8000)) || - ((GetKeyState(VK_CAPITAL) & 0x0001) && (GetKeyState(VK_SHIFT) & 0x8000))) { - CharLowerBuffA(keyName, 16); - } - } - - RGFW_updateLockState(win, (GetKeyState(VK_CAPITAL) & 0x0001), (GetKeyState(VK_NUMLOCK) & 0x0001)); - - strncpy(win->event.keyName, keyName, 16); - - if (RGFW_isPressed(win, RGFW_ShiftL)) { - ToAscii((UINT) msg.wParam, MapVirtualKey((UINT) msg.wParam, MAPVK_VK_TO_CHAR), - keyboardState, (LPWORD) win->event.keyName, 0); - } - - win->event.type = RGFW_keyReleased; - RGFW_keyboard[win->event.keyCode].current = 0; - RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 0); - break; - } - case WM_KEYDOWN: { - win->event.keyCode = RGFW_apiKeyCodeToRGFW((u32) msg.wParam); - - RGFW_keyboard[win->event.keyCode].prev = RGFW_isPressed(win, win->event.keyCode); - - static char keyName[16]; - - { - GetKeyNameTextA((LONG) msg.lParam, keyName, 16); - - if ((!(GetKeyState(VK_CAPITAL) & 0x0001) && !(GetKeyState(VK_SHIFT) & 0x8000)) || - ((GetKeyState(VK_CAPITAL) & 0x0001) && (GetKeyState(VK_SHIFT) & 0x8000))) { - CharLowerBuffA(keyName, 16); - } - } - - RGFW_updateLockState(win, (GetKeyState(VK_CAPITAL) & 0x0001), (GetKeyState(VK_NUMLOCK) & 0x0001)); - - strncpy(win->event.keyName, keyName, 16); - - if (RGFW_isPressed(win, RGFW_ShiftL) & 0x8000) { - ToAscii((UINT) msg.wParam, MapVirtualKey((UINT) msg.wParam, MAPVK_VK_TO_CHAR), - keyboardState, (LPWORD) win->event.keyName, 0); - } - - win->event.type = RGFW_keyPressed; - win->event.repeat = RGFW_isPressed(win, win->event.keyCode); - RGFW_keyboard[win->event.keyCode].current = 1; - RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 1); - break; + win->event.point.x = pos.x - win->_lastMousePoint.x; + win->event.point.y = pos.y - win->_lastMousePoint.y; + } else { + win->event.point.x = raw.data.mouse.lLastX; + win->event.point.y = raw.data.mouse.lLastY; } - case WM_MOUSEMOVE: - if ((win->_winArgs & RGFW_HOLD_MOUSE)) - break; + win->event.type = RGFW_mousePosChanged; + win->_lastMousePoint.x += win->event.point.x; + win->_lastMousePoint.y += win->event.point.y; + break; + } - win->event.type = RGFW_mousePosChanged; + case WM_LBUTTONDOWN: + win->event.button = RGFW_mouseLeft; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 1; + win->event.type = RGFW_mouseButtonPressed; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); + break; + case WM_RBUTTONDOWN: + win->event.button = RGFW_mouseRight; + win->event.type = RGFW_mouseButtonPressed; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 1; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); + break; + case WM_MBUTTONDOWN: + win->event.button = RGFW_mouseMiddle; + win->event.type = RGFW_mouseButtonPressed; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 1; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); + break; - win->event.point.x = GET_X_LPARAM(msg.lParam); - win->event.point.y = GET_Y_LPARAM(msg.lParam); - - RGFW_mousePosCallback(win, win->event.point); + case WM_MOUSEWHEEL: + if (msg.wParam > 0) + win->event.button = RGFW_mouseScrollUp; + else + win->event.button = RGFW_mouseScrollDown; - if (win->_winArgs & RGFW_MOUSE_LEFT) { - win->_winArgs ^= RGFW_MOUSE_LEFT; - win->event.type = RGFW_mouseEnter; - RGFW_mouseNotifyCallBack(win, win->event.point, 1); - } + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 1; - break; + win->event.scroll = (SHORT) HIWORD(msg.wParam) / (double) WHEEL_DELTA; - case WM_INPUT: { - if (!(win->_winArgs & RGFW_HOLD_MOUSE)) - break; - - unsigned size = sizeof(RAWINPUT); - static RAWINPUT raw[sizeof(RAWINPUT)]; - GetRawInputData((HRAWINPUT)msg.lParam, RID_INPUT, raw, &size, sizeof(RAWINPUTHEADER)); + win->event.type = RGFW_mouseButtonPressed; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); + break; - if (raw->header.dwType != RIM_TYPEMOUSE || (raw->data.mouse.lLastX == 0 && raw->data.mouse.lLastY == 0) ) - break; - - win->event.type = RGFW_mousePosChanged; - win->event.point.x = raw->data.mouse.lLastX; - win->event.point.y = raw->data.mouse.lLastY; - break; - } + case WM_LBUTTONUP: - case WM_LBUTTONDOWN: - win->event.button = RGFW_mouseLeft; - RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; - RGFW_mouseButtons[win->event.button].current = 1; - win->event.type = RGFW_mouseButtonPressed; - RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); - break; - case WM_RBUTTONDOWN: - win->event.button = RGFW_mouseRight; - win->event.type = RGFW_mouseButtonPressed; - RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; - RGFW_mouseButtons[win->event.button].current = 1; - RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); - break; - case WM_MBUTTONDOWN: - win->event.button = RGFW_mouseMiddle; - win->event.type = RGFW_mouseButtonPressed; - RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; - RGFW_mouseButtons[win->event.button].current = 1; - RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); - break; + win->event.button = RGFW_mouseLeft; + win->event.type = RGFW_mouseButtonReleased; - case WM_MOUSEWHEEL: - if (msg.wParam > 0) - win->event.button = RGFW_mouseScrollUp; - else - win->event.button = RGFW_mouseScrollDown; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 0; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); + break; + case WM_RBUTTONUP: + win->event.button = RGFW_mouseRight; + win->event.type = RGFW_mouseButtonReleased; - RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; - RGFW_mouseButtons[win->event.button].current = 1; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 0; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); + break; + case WM_MBUTTONUP: + win->event.button = RGFW_mouseMiddle; + win->event.type = RGFW_mouseButtonReleased; - win->event.scroll = (SHORT) HIWORD(msg.wParam) / (double) WHEEL_DELTA; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 0; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); + break; + case WM_DROPFILES: { + win->event.type = RGFW_DNDInit; - win->event.type = RGFW_mouseButtonPressed; - RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); - break; + drop = (HDROP) msg.wParam; + POINT pt; - case WM_LBUTTONUP: - - win->event.button = RGFW_mouseLeft; - win->event.type = RGFW_mouseButtonReleased; + /* Move the mouse to the position of the drop */ + DragQueryPoint(drop, &pt); - RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; - RGFW_mouseButtons[win->event.button].current = 0; - RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); - break; - case WM_RBUTTONUP: - win->event.button = RGFW_mouseRight; - win->event.type = RGFW_mouseButtonReleased; + win->event.point.x = pt.x; + win->event.point.y = pt.y; - RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; - RGFW_mouseButtons[win->event.button].current = 0; - RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); - break; - case WM_MBUTTONUP: - win->event.button = RGFW_mouseMiddle; - win->event.type = RGFW_mouseButtonReleased; + RGFW_dndInitCallback(win, win->event.point); + } + break; + case WM_GETMINMAXINFO: + { + MINMAXINFO* mmi = (MINMAXINFO*) msg.lParam; + mmi->ptMinTrackSize.x = win->src.minSize.w; + mmi->ptMinTrackSize.y = win->src.minSize.h; - RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; - RGFW_mouseButtons[win->event.button].current = 0; - RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); - break; - - /* - much of this event is source from glfw - */ - case WM_DROPFILES: { - win->event.type = RGFW_dnd_init; - - drop = (HDROP) msg.wParam; - POINT pt; - - /* Move the mouse to the position of the drop */ - DragQueryPoint(drop, &pt); - - win->event.point.x = pt.x; - win->event.point.y = pt.y; - - RGFW_dndInitCallback(win, win->event.point); - } - break; - case WM_GETMINMAXINFO: - { - if (win->src.maxSize.w == 0 && win->src.maxSize.h == 0) - break; - - MINMAXINFO* mmi = (MINMAXINFO*) msg.lParam; - mmi->ptMinTrackSize.x = win->src.minSize.w; - mmi->ptMinTrackSize.y = win->src.minSize.h; - mmi->ptMaxTrackSize.x = win->src.maxSize.w; - mmi->ptMaxTrackSize.y = win->src.maxSize.h; - return 0; - } - default: - win->event.type = 0; - break; - } + if (win->src.maxSize.w == 0 && win->src.maxSize.h == 0) + return RGFW_window_checkEvent(win); + mmi->ptMaxTrackSize.x = win->src.maxSize.w; + mmi->ptMaxTrackSize.y = win->src.maxSize.h; + return RGFW_window_checkEvent(win); + } + default: TranslateMessage(&msg); DispatchMessageA(&msg); - } - - else - win->event.type = 0; - - if (!IsWindow(win->src.window)) { - win->event.type = RGFW_quit; - RGFW_windowQuitCallback(win); - } - - if (win->event.type) - return &win->event; - else - return NULL; + return RGFW_window_checkEvent(win); } - u8 RGFW_window_isFullscreen(RGFW_window* win) { - assert(win != NULL); + TranslateMessage(&msg); + DispatchMessageA(&msg); - #ifndef __cplusplus - WINDOWPLACEMENT placement = { 0 }; - #else - WINDOWPLACEMENT placement = { }; - #endif - GetWindowPlacement(win->src.window, &placement); - return placement.showCmd == SW_SHOWMAXIMIZED; - } + return &win->event; +} - u8 RGFW_window_isHidden(RGFW_window* win) { - assert(win != NULL); +u8 RGFW_window_isFullscreen(RGFW_window* win) { + RGFW_ASSERT(win != NULL); - return IsWindowVisible(win->src.window) == 0 && !RGFW_window_isMinimized(win); - } + #ifndef __cplusplus + WINDOWPLACEMENT placement = { 0 }; + #else + WINDOWPLACEMENT placement = { }; + #endif + GetWindowPlacement(win->src.window, &placement); + return placement.showCmd == SW_SHOWMAXIMIZED; +} - u8 RGFW_window_isMinimized(RGFW_window* win) { - assert(win != NULL); +u8 RGFW_window_isHidden(RGFW_window* win) { + RGFW_ASSERT(win != NULL); - #ifndef __cplusplus - WINDOWPLACEMENT placement = { 0 }; - #else - WINDOWPLACEMENT placement = { }; - #endif - GetWindowPlacement(win->src.window, &placement); - return placement.showCmd == SW_SHOWMINIMIZED; - } + return IsWindowVisible(win->src.window) == 0 && !RGFW_window_isMinimized(win); +} - u8 RGFW_window_isMaximized(RGFW_window* win) { - assert(win != NULL); +u8 RGFW_window_isMinimized(RGFW_window* win) { + RGFW_ASSERT(win != NULL); - #ifndef __cplusplus - WINDOWPLACEMENT placement = { 0 }; - #else - WINDOWPLACEMENT placement = { }; - #endif - GetWindowPlacement(win->src.window, &placement); - return placement.showCmd == SW_SHOWMAXIMIZED; - } + #ifndef __cplusplus + WINDOWPLACEMENT placement = { 0 }; + #else + WINDOWPLACEMENT placement = { }; + #endif + GetWindowPlacement(win->src.window, &placement); + return placement.showCmd == SW_SHOWMINIMIZED; +} - typedef struct { int iIndex; HMONITOR hMonitor; } RGFW_mInfo; - BOOL CALLBACK GetMonitorByHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { - RGFW_UNUSED(hdcMonitor) - RGFW_UNUSED(lprcMonitor) +u8 RGFW_window_isMaximized(RGFW_window* win) { + RGFW_ASSERT(win != NULL); - RGFW_mInfo* info = (RGFW_mInfo*) dwData; - if (info->hMonitor == hMonitor) - return FALSE; + #ifndef __cplusplus + WINDOWPLACEMENT placement = { 0 }; + #else + WINDOWPLACEMENT placement = { }; + #endif + GetWindowPlacement(win->src.window, &placement); + return placement.showCmd == SW_SHOWMAXIMIZED; +} - info->iIndex++; - return TRUE; - } - - #ifndef RGFW_NO_MONITOR - RGFW_monitor win32CreateMonitor(HMONITOR src) { - RGFW_monitor monitor; - MONITORINFO monitorInfo; +typedef struct { int iIndex; HMONITOR hMonitor; } RGFW_mInfo; +BOOL CALLBACK GetMonitorByHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { + RGFW_UNUSED(hdcMonitor); + RGFW_UNUSED(lprcMonitor); - monitorInfo.cbSize = sizeof(MONITORINFO); - GetMonitorInfoA(src, &monitorInfo); + RGFW_mInfo* info = (RGFW_mInfo*) dwData; + if (info->hMonitor == hMonitor) + return FALSE; - RGFW_mInfo info; - info.iIndex = 0; - info.hMonitor = src; + info->iIndex++; + return TRUE; +} - /* get the monitor's index */ - if (EnumDisplayMonitors(NULL, NULL, GetMonitorByHandle, (LPARAM) &info)) { - DISPLAY_DEVICEA dd; - dd.cb = sizeof(dd); +#ifndef RGFW_NO_MONITOR - /* loop through the devices until you find a device with the monitor's index */ - size_t deviceIndex; - for (deviceIndex = 0; EnumDisplayDevicesA(0, (DWORD) deviceIndex, &dd, 0); deviceIndex++) { - char* deviceName = dd.DeviceName; - if (EnumDisplayDevicesA(deviceName, info.iIndex, &dd, 0)) { - strncpy(monitor.name, dd.DeviceString, 128); /*!< copy the monitor's name */ - break; - } +RGFW_monitor win32CreateMonitor(HMONITOR src) { + RGFW_monitor monitor; + MONITORINFOEX monitorInfo; + + monitorInfo.cbSize = sizeof(MONITORINFOEX); + GetMonitorInfoA(src, (LPMONITORINFO)&monitorInfo); + + RGFW_mInfo info; + info.iIndex = 0; + info.hMonitor = src; + + /* get the monitor's index */ + if (EnumDisplayMonitors(NULL, NULL, GetMonitorByHandle, (LPARAM) &info)) { + DISPLAY_DEVICEA dd; + dd.cb = sizeof(dd); + + /* loop through the devices until you find a device with the monitor's index */ + size_t deviceIndex; + for (deviceIndex = 0; EnumDisplayDevicesA(0, (DWORD) deviceIndex, &dd, 0); deviceIndex++) { + char* deviceName = dd.DeviceName; + if (EnumDisplayDevicesA(deviceName, info.iIndex, &dd, 0)) { + RGFW_MEMCPY(monitor.name, dd.DeviceString, 128); /*!< copy the monitor's name */ + break; } } + } - monitor.rect.x = monitorInfo.rcWork.left; - monitor.rect.y = monitorInfo.rcWork.top; - monitor.rect.w = monitorInfo.rcWork.right - monitorInfo.rcWork.left; - monitor.rect.h = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top; + monitor.rect.x = monitorInfo.rcWork.left; + monitor.rect.y = monitorInfo.rcWork.top; + monitor.rect.w = monitorInfo.rcWork.right - monitorInfo.rcWork.left; + monitor.rect.h = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top; -#ifndef RGFW_NO_DPI - #ifndef USER_DEFAULT_SCREEN_DPI - #define USER_DEFAULT_SCREEN_DPI 96 - #endif + HDC hdc = CreateDC(monitorInfo.szDevice, NULL, NULL, NULL); + /* get pixels per inch */ + float dpiX = (float)GetDeviceCaps(hdc, LOGPIXELSX); + float dpiY = (float)GetDeviceCaps(hdc, LOGPIXELSX); + monitor.scaleX = dpiX / 96.0f; + monitor.scaleY = dpiY / 96.0f; + + monitor.physW = GetDeviceCaps(hdc, HORZSIZE) / 25.4; + monitor.physH = GetDeviceCaps(hdc, VERTSIZE) / 25.4; + DeleteDC(hdc); + + #ifndef RGFW_NO_DPI if (GetDpiForMonitor != NULL) { u32 x, y; GetDpiForMonitor(src, MDT_EFFECTIVE_DPI, &x, &y); - - monitor.scaleX = (float) (x) / (float) USER_DEFAULT_SCREEN_DPI; - monitor.scaleY = (float) (y) / (float) USER_DEFAULT_SCREEN_DPI; + + monitor.pixelRatio = (float) (x) / (float) dpiX; + monitor.pixelRatio = (float) (y) / (float) dpiY; } -#endif - - HDC hdc = GetDC(NULL); - /* get pixels per inch */ - i32 ppiX = GetDeviceCaps(hdc, LOGPIXELSX); - i32 ppiY = GetDeviceCaps(hdc, LOGPIXELSY); - ReleaseDC(NULL, hdc); - - /* Calculate physical height in inches */ - monitor.physW = GetSystemMetrics(SM_CYSCREEN) / (float) ppiX; - monitor.physH = GetSystemMetrics(SM_CXSCREEN) / (float) ppiY; - - return monitor; - } - #endif /* RGFW_NO_MONITOR */ - - - #ifndef RGFW_NO_MONITOR - RGFW_monitor RGFW_monitors[6]; - BOOL CALLBACK GetMonitorHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { - RGFW_UNUSED(hdcMonitor) - RGFW_UNUSED(lprcMonitor) - - RGFW_mInfo* info = (RGFW_mInfo*) dwData; - - if (info->iIndex >= 6) - return FALSE; - - RGFW_monitors[info->iIndex] = win32CreateMonitor(hMonitor); - info->iIndex++; - - return TRUE; - } - - RGFW_monitor RGFW_getPrimaryMonitor(void) { - #ifdef __cplusplus - return win32CreateMonitor(MonitorFromPoint({ 0, 0 }, MONITOR_DEFAULTTOPRIMARY)); - #else - return win32CreateMonitor(MonitorFromPoint((POINT) { 0, 0 }, MONITOR_DEFAULTTOPRIMARY)); - #endif - } - - RGFW_monitor* RGFW_getMonitors(void) { - RGFW_mInfo info; - info.iIndex = 0; - while (EnumDisplayMonitors(NULL, NULL, GetMonitorHandle, (LPARAM) &info)); - - return RGFW_monitors; - } - - RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { - HMONITOR src = MonitorFromWindow(win->src.window, MONITOR_DEFAULTTOPRIMARY); - return win32CreateMonitor(src); - } #endif - HICON RGFW_loadHandleImage(RGFW_window* win, u8* src, RGFW_area a, BOOL icon) { - assert(win != NULL); + #ifdef RGFW_DEBUG + printf("RGFW INFO: monitor found: scale (%s):\n rect: {%i, %i, %i, %i}\n physical size:%f %f\n scale: %f %f\n pixelRatio: %f\n", monitor.name, monitor.rect.x, monitor.rect.y, monitor.rect.w, monitor.rect.h, monitor.physW, monitor.physH, monitor.scaleX, monitor.scaleY, monitor.pixelRatio); + #endif - u32 i; - HDC dc; - HICON handle; - HBITMAP color, mask; - BITMAPV5HEADER bi; - ICONINFO ii; - u8* target = NULL; - u8* source = src; + return monitor; +} +#endif /* RGFW_NO_MONITOR */ - ZeroMemory(&bi, sizeof(bi)); - bi.bV5Size = sizeof(bi); - bi.bV5Width = a.w; - bi.bV5Height = -((LONG) a.h); - bi.bV5Planes = 1; - bi.bV5BitCount = 32; - bi.bV5Compression = BI_BITFIELDS; - bi.bV5RedMask = 0x00ff0000; - bi.bV5GreenMask = 0x0000ff00; - bi.bV5BlueMask = 0x000000ff; - bi.bV5AlphaMask = 0xff000000; +#ifndef RGFW_NO_MONITOR - dc = GetDC(NULL); - color = CreateDIBSection(dc, - (BITMAPINFO*) &bi, - DIB_RGB_COLORS, - (void**) &target, - NULL, - (DWORD) 0); - ReleaseDC(NULL, dc); +RGFW_monitor RGFW_monitors[6]; +BOOL CALLBACK GetMonitorHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { + RGFW_UNUSED(hdcMonitor); + RGFW_UNUSED(lprcMonitor); - mask = CreateBitmap(a.w, a.h, 1, 1, NULL); + RGFW_mInfo* info = (RGFW_mInfo*) dwData; - for (i = 0; i < a.w * a.h; i++) { - target[0] = source[2]; - target[1] = source[1]; - target[2] = source[0]; - target[3] = source[3]; - target += 4; - source += 4; - } + if (info->iIndex >= 6) + return FALSE; - ZeroMemory(&ii, sizeof(ii)); - ii.fIcon = icon; - ii.xHotspot = 0; - ii.yHotspot = 0; - ii.hbmMask = mask; - ii.hbmColor = color; + RGFW_monitors[info->iIndex] = win32CreateMonitor(hMonitor); + info->iIndex++; - handle = CreateIconIndirect(&ii); + return TRUE; +} - DeleteObject(color); - DeleteObject(mask); +RGFW_monitor RGFW_getPrimaryMonitor(void) { + #ifdef __cplusplus + return win32CreateMonitor(MonitorFromPoint({ 0, 0 }, MONITOR_DEFAULTTOPRIMARY)); + #else + return win32CreateMonitor(MonitorFromPoint((POINT) { 0, 0 }, MONITOR_DEFAULTTOPRIMARY)); + #endif +} - return handle; - } +RGFW_monitor* RGFW_getMonitors(void) { + RGFW_mInfo info; + info.iIndex = 0; + while (EnumDisplayMonitors(NULL, NULL, GetMonitorHandle, (LPARAM) &info)); - void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) { - assert(win != NULL); - RGFW_UNUSED(channels) + return RGFW_monitors; +} - HCURSOR cursor = (HCURSOR) RGFW_loadHandleImage(win, image, a, FALSE); - SetClassLongPtrA(win->src.window, GCLP_HCURSOR, (LPARAM) cursor); - SetCursor(cursor); - DestroyCursor(cursor); - } +RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { + HMONITOR src = MonitorFromWindow(win->src.window, MONITOR_DEFAULTTOPRIMARY); + return win32CreateMonitor(src); +} - void RGFW_window_setMouseDefault(RGFW_window* win) { - RGFW_window_setMouseStandard(win, RGFW_MOUSE_ARROW); - } - - void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) { - assert(win != NULL); - - if (mouse > (sizeof(RGFW_mouseIconSrc) / sizeof(u32))) - return; - - char* icon = MAKEINTRESOURCEA(RGFW_mouseIconSrc[mouse]); - - SetClassLongPtrA(win->src.window, GCLP_HCURSOR, (LPARAM) LoadCursorA(NULL, icon)); - SetCursor(LoadCursorA(NULL, icon)); - } - - void RGFW_window_hide(RGFW_window* win) { - ShowWindow(win->src.window, SW_HIDE); - } - - void RGFW_window_show(RGFW_window* win) { - ShowWindow(win->src.window, SW_RESTORE); - } - - void RGFW_window_close(RGFW_window* win) { - assert(win != NULL); - -#ifdef RGFW_EGL - RGFW_closeEGL(win); #endif - if (win == RGFW_root) { -#ifdef RGFW_DIRECTX +HICON RGFW_loadHandleImage(u8* src, RGFW_area a, BOOL icon) { + u32 i; + HDC dc; + HICON handle; + HBITMAP color, mask; + BITMAPV5HEADER bi; + ICONINFO ii; + u8* target = NULL; + u8* source = src; + + ZeroMemory(&bi, sizeof(bi)); + bi.bV5Size = sizeof(bi); + bi.bV5Width = a.w; + bi.bV5Height = -((LONG) a.h); + bi.bV5Planes = 1; + bi.bV5BitCount = 32; + bi.bV5Compression = BI_BITFIELDS; + bi.bV5RedMask = 0x00ff0000; + bi.bV5GreenMask = 0x0000ff00; + bi.bV5BlueMask = 0x000000ff; + bi.bV5AlphaMask = 0xff000000; + + dc = GetDC(NULL); + color = CreateDIBSection(dc, + (BITMAPINFO*) &bi, + DIB_RGB_COLORS, + (void**) &target, + NULL, + (DWORD) 0); + ReleaseDC(NULL, dc); + + mask = CreateBitmap(a.w, a.h, 1, 1, NULL); + + for (i = 0; i < a.w * a.h; i++) { + target[0] = source[2]; + target[1] = source[1]; + target[2] = source[0]; + target[3] = source[3]; + target += 4; + source += 4; + } + + ZeroMemory(&ii, sizeof(ii)); + ii.fIcon = icon; + ii.xHotspot = 0; + ii.yHotspot = 0; + ii.hbmMask = mask; + ii.hbmColor = color; + + handle = CreateIconIndirect(&ii); + + DeleteObject(color); + DeleteObject(mask); + + return handle; +} + +void* RGFW_loadMouse(u8* icon, RGFW_area a, i32 channels) { + RGFW_UNUSED(channels); + + HCURSOR cursor = (HCURSOR) RGFW_loadHandleImage(icon, a, FALSE); + return cursor; +} + +void RGFW_window_setMouse(RGFW_window* win, RGFW_mouse* mouse) { + RGFW_ASSERT(win && mouse); + SetClassLongPtrA(win->src.window, GCLP_HCURSOR, (LPARAM) mouse); + SetCursor((HCURSOR)mouse); +} + +void RGFW_freeMouse(RGFW_mouse* mouse) { + RGFW_ASSERT(mouse); + DestroyCursor((HCURSOR)mouse); +} + +b32 RGFW_window_setMouseDefault(RGFW_window* win) { + return RGFW_window_setMouseStandard(win, RGFW_mouseArrow); +} + +b32 RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) { + RGFW_ASSERT(win != NULL); + + if (mouse > (sizeof(RGFW_mouseIconSrc) / sizeof(u32))) + return 0; + + char* icon = MAKEINTRESOURCEA(RGFW_mouseIconSrc[mouse]); + + SetClassLongPtrA(win->src.window, GCLP_HCURSOR, (LPARAM) LoadCursorA(NULL, icon)); + SetCursor(LoadCursorA(NULL, icon)); + return 1; +} + +void RGFW_window_hide(RGFW_window* win) { + ShowWindow(win->src.window, SW_HIDE); +} + +void RGFW_window_show(RGFW_window* win) { + ShowWindow(win->src.window, SW_RESTORE); +} + +#define RGFW_FREE_LIBRARY(x) if (x != NULL) FreeLibrary(x); x = NULL; + +void RGFW_window_close(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + RGFW_windowsOpen--; + + #ifdef RGFW_EGL + RGFW_closeEGL(win); + #endif + + #ifdef RGFW_DIRECTX + win->src.swapchain->lpVtbl->Release(win->src.swapchain); + win->src.renderTargetView->lpVtbl->Release(win->src.renderTargetView); + win->src.pDepthStencilView->lpVtbl->Release(win->src.pDepthStencilView); + #endif + + #ifdef RGFW_BUFFER + DeleteDC(win->src.hdcMem); + DeleteObject(win->src.bitmap); + #endif + + #ifdef RGFW_OPENGL + wglDeleteContext((HGLRC) win->src.ctx); /*!< delete opengl context */ + #endif + ReleaseDC(win->src.window, win->src.hdc); /*!< delete device context */ + DestroyWindow(win->src.window); /*!< delete window */ + + #ifdef RGFW_ALLOC_DROPFILES + { + u32 i; + for (i = 0; i < RGFW_MAX_DROPS; i++) + win->_mem.free(win->_mem.userdata, win->event.droppedFiles[i]); + + win->_mem.free(win->_mem.userdata, win->event.droppedFiles); + } + #endif + + if (RGFW_windowsOpen <= 0) { + #ifdef RGFW_DIRECTX RGFW_dxInfo.pDeviceContext->lpVtbl->Release(RGFW_dxInfo.pDeviceContext); RGFW_dxInfo.pDevice->lpVtbl->Release(RGFW_dxInfo.pDevice); RGFW_dxInfo.pAdapter->lpVtbl->Release(RGFW_dxInfo.pAdapter); RGFW_dxInfo.pFactory->lpVtbl->Release(RGFW_dxInfo.pFactory); -#endif - - if (RGFW_XInput_dll != NULL) { - FreeLibrary(RGFW_XInput_dll); - RGFW_XInput_dll = NULL; - } + #endif - #ifndef RGFW_NO_DPI - if (RGFW_Shcore_dll != NULL) { - FreeLibrary(RGFW_Shcore_dll); - RGFW_Shcore_dll = NULL; - } - #endif + #ifndef RGFW_NO_XINPUT + RGFW_FREE_LIBRARY(RGFW_XInput_dll); + #endif - if (wglinstance != NULL) { - FreeLibrary(wglinstance); - wglinstance = NULL; - } + #ifndef RGFW_NO_DPI + RGFW_FREE_LIBRARY(RGFW_Shcore_dll); + #endif - RGFW_root = NULL; - } + #if !defined(RGFW_NO_LOAD_WINMM) && !defined(RGFW_NO_WINMM) + RGFW_FREE_LIBRARY(RGFW_winmm_dll); + #endif -#ifdef RGFW_DIRECTX - win->src.swapchain->lpVtbl->Release(win->src.swapchain); - win->src.renderTargetView->lpVtbl->Release(win->src.renderTargetView); - win->src.pDepthStencilView->lpVtbl->Release(win->src.pDepthStencilView); -#endif + RGFW_FREE_LIBRARY(RGFW_wgl_dll); + RGFW_root = NULL; -#ifdef RGFW_BUFFER - DeleteDC(win->src.hdcMem); - DeleteObject(win->src.bitmap); -#endif - -#ifdef RGFW_OPENGL - wglDeleteContext((HGLRC) win->src.ctx); /*!< delete opengl context */ -#endif - DeleteDC(win->src.hdc); /*!< delete device context */ - DestroyWindow(win->src.window); /*!< delete window */ - -#if defined(RGFW_OSMESA) - if (win->buffer != NULL) - RGFW_FREE(win->buffer); -#endif - -#ifdef RGFW_ALLOC_DROPFILES - { - u32 i; - for (i = 0; i < RGFW_MAX_DROPS; i++) - RGFW_FREE(win->event.droppedFiles[i]); - - - RGFW_FREE(win->event.droppedFiles); - } -#endif - - RGFW_FREE(win); - } - - void RGFW_window_move(RGFW_window* win, RGFW_point v) { - assert(win != NULL); - - win->r.x = v.x; - win->r.y = v.y; - SetWindowPos(win->src.window, HWND_TOP, win->r.x, win->r.y, 0, 0, SWP_NOSIZE); - } - - void RGFW_window_resize(RGFW_window* win, RGFW_area a) { - assert(win != NULL); - - win->r.w = a.w; - win->r.h = a.h; - SetWindowPos(win->src.window, HWND_TOP, 0, 0, win->r.w, win->r.h + win->src.hOffset, SWP_NOMOVE); - } - - - void RGFW_window_setName(RGFW_window* win, char* name) { - assert(win != NULL); - - SetWindowTextA(win->src.window, name); - } - - /* sourced from GLFW */ - #ifndef RGFW_NO_PASSTHROUGH - void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) { - assert(win != NULL); - - COLORREF key = 0; - BYTE alpha = 0; - DWORD flags = 0; - DWORD exStyle = GetWindowLongW(win->src.window, GWL_EXSTYLE); - - if (exStyle & WS_EX_LAYERED) - GetLayeredWindowAttributes(win->src.window, &key, &alpha, &flags); - - if (passthrough) - exStyle |= (WS_EX_TRANSPARENT | WS_EX_LAYERED); - else - { - exStyle &= ~WS_EX_TRANSPARENT; - // NOTE: Window opacity also needs the layered window style so do not - // remove it if the window is alpha blended - if (exStyle & WS_EX_LAYERED) - { - if (!(flags & LWA_ALPHA)) - exStyle &= ~WS_EX_LAYERED; - } - } - - SetWindowLongW(win->src.window, GWL_EXSTYLE, exStyle); - - if (passthrough) { - SetLayeredWindowAttributes(win->src.window, key, alpha, flags); + if (RGFW_hiddenMouse != NULL) { + RGFW_freeMouse(RGFW_hiddenMouse); + RGFW_hiddenMouse = 0; } } - #endif - /* much of this function is sourced from GLFW */ - void RGFW_window_setIcon(RGFW_window* win, u8* src, RGFW_area a, i32 channels) { - assert(win != NULL); - #ifndef RGFW_WIN95 - RGFW_UNUSED(channels) + RGFW_clipboard_switch(NULL); - HICON handle = RGFW_loadHandleImage(win, src, a, TRUE); + if ((win->_flags & RGFW_WINDOW_ALLOC)) + win->_mem.free(win->_mem.userdata, win); +} + +void RGFW_window_move(RGFW_window* win, RGFW_point v) { + RGFW_ASSERT(win != NULL); + + win->r.x = v.x; + win->r.y = v.y; + SetWindowPos(win->src.window, HWND_TOP, win->r.x, win->r.y, 0, 0, SWP_NOSIZE); +} + +void RGFW_window_resize(RGFW_window* win, RGFW_area a) { + RGFW_ASSERT(win != NULL); + + win->r.w = a.w; + win->r.h = a.h; + SetWindowPos(win->src.window, HWND_TOP, 0, 0, win->r.w, win->r.h + win->src.hOffset, SWP_NOMOVE); +} + + +void RGFW_window_setName(RGFW_window* win, const char* name) { + RGFW_ASSERT(win != NULL); + + SetWindowTextA(win->src.window, name); +} + +#ifndef RGFW_NO_PASSTHROUGH + +void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) { + RGFW_ASSERT(win != NULL); + + COLORREF key = 0; + BYTE alpha = 0; + DWORD flags = 0; + DWORD exStyle = GetWindowLongW(win->src.window, GWL_EXSTYLE); + + if (exStyle & WS_EX_LAYERED) + GetLayeredWindowAttributes(win->src.window, &key, &alpha, &flags); + + if (passthrough) + exStyle |= (WS_EX_TRANSPARENT | WS_EX_LAYERED); + else { + exStyle &= ~WS_EX_TRANSPARENT; + if (exStyle & WS_EX_LAYERED && !(flags & LWA_ALPHA)) + exStyle &= ~WS_EX_LAYERED; + } + + SetWindowLongW(win->src.window, GWL_EXSTYLE, exStyle); + + if (passthrough) + SetLayeredWindowAttributes(win->src.window, key, alpha, flags); +} +#endif + +b32 RGFW_window_setIcon(RGFW_window* win, u8* src, RGFW_area a, i32 channels) { + RGFW_ASSERT(win != NULL); + #ifndef RGFW_WIN95 + RGFW_UNUSED(channels); + + HICON handle = RGFW_loadHandleImage(src, a, TRUE); SetClassLongPtrA(win->src.window, GCLP_HICON, (LPARAM) handle); DestroyIcon(handle); - #else - RGFW_UNUSED(src) - RGFW_UNUSED(a) - RGFW_UNUSED(channels) + return 1; + #else + RGFW_UNUSED(src); + RGFW_UNUSED(a); + RGFW_UNUSED(channels); + return 0; + #endif +} + +RGFW_ssize_t RGFW_readClipboardPtr(char* str, size_t strCapacity) { + /* Open the clipboard */ + if (OpenClipboard(NULL) == 0) + return -1; + + /* Get the clipboard data as a Unicode string */ + HANDLE hData = GetClipboardData(CF_UNICODETEXT); + if (hData == NULL) { + CloseClipboard(); + return -1; + } + + wchar_t* wstr = (wchar_t*) GlobalLock(hData); + + RGFW_ssize_t textLen = 0; + + { + setlocale(LC_ALL, "en_US.UTF-8"); + + textLen = wcstombs(NULL, wstr, 0) + 1; + if (str != NULL && (RGFW_ssize_t)strCapacity <= textLen - 1) + textLen = 0; + + if (str != NULL && textLen) { + + if (textLen > 1) + wcstombs(str, wstr, (textLen) ); + + str[textLen] = '\0'; + } + } + + /* Release the clipboard data */ + GlobalUnlock(hData); + CloseClipboard(); + + return textLen; +} + +void RGFW_writeClipboard(const char* text, u32 textLen) { + HANDLE object; + WCHAR* buffer; + + object = GlobalAlloc(GMEM_MOVEABLE, (1 + textLen) * sizeof(WCHAR)); + if (!object) + return; + + buffer = (WCHAR*) GlobalLock(object); + if (!buffer) { + GlobalFree(object); + return; + } + + MultiByteToWideChar(CP_UTF8, 0, text, -1, buffer, textLen); + GlobalUnlock(object); + + if (!OpenClipboard(RGFW_root->src.window)) { + GlobalFree(object); + return; + } + + EmptyClipboard(); + SetClipboardData(CF_UNICODETEXT, object); + CloseClipboard(); +} + +void RGFW_window_moveMouse(RGFW_window* win, RGFW_point p) { + RGFW_ASSERT(win != NULL); + win->_lastMousePoint = RGFW_POINT(p.x - win->r.x, p.y - win->r.y); + SetCursorPos(p.x, p.y); +} + +#ifdef RGFW_OPENGL +void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) { + if (win == NULL) + wglMakeCurrent(NULL, NULL); + else + wglMakeCurrent(win->src.hdc, (HGLRC) win->src.ctx); +} +#endif + +#ifndef RGFW_EGL + +void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { + RGFW_ASSERT(win != NULL); + + #if defined(RGFW_OPENGL) + typedef BOOL(APIENTRY* PFNWGLSWAPINTERVALEXTPROC)(int interval); + static PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL; + static void* loadSwapFunc = (void*) 1; + + if (loadSwapFunc == NULL) { + #ifdef RGFW_DEBUG + fprintf(stderr, "wglSwapIntervalEXT not supported\n"); + #endif + return; + } + + if (wglSwapIntervalEXT == NULL) { + loadSwapFunc = (void*) wglGetProcAddress("wglSwapIntervalEXT"); + wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) loadSwapFunc; + } + + if (wglSwapIntervalEXT(swapInterval) == FALSE) { + #ifdef RGFW_DEBUG + fprintf(stderr, "Failed to set swap interval\n"); #endif } - - char* RGFW_readClipboard(size_t* size) { - /* Open the clipboard */ - if (OpenClipboard(NULL) == 0) - return (char*) ""; - - /* Get the clipboard data as a Unicode string */ - HANDLE hData = GetClipboardData(CF_UNICODETEXT); - if (hData == NULL) { - CloseClipboard(); - return (char*) ""; - } - - wchar_t* wstr = (wchar_t*) GlobalLock(hData); - - char* text; - - { - setlocale(LC_ALL, "en_US.UTF-8"); - - size_t textLen = wcstombs(NULL, wstr, 0); - if (textLen == 0) - return (char*) ""; - - text = (char*) RGFW_MALLOC((textLen * sizeof(char)) + 1); - - wcstombs(text, wstr, (textLen) +1); - - if (size != NULL) - *size = textLen + 1; - - text[textLen] = '\0'; - } - - /* Release the clipboard data */ - GlobalUnlock(hData); - CloseClipboard(); - - return text; - } - - void RGFW_writeClipboard(const char* text, u32 textLen) { - HANDLE object; - WCHAR* buffer; - - object = GlobalAlloc(GMEM_MOVEABLE, (1 + textLen) * sizeof(WCHAR)); - if (!object) - return; - - buffer = (WCHAR*) GlobalLock(object); - if (!buffer) { - GlobalFree(object); - return; - } - - MultiByteToWideChar(CP_UTF8, 0, text, -1, buffer, textLen); - GlobalUnlock(object); - - if (!OpenClipboard(RGFW_root->src.window)) { - GlobalFree(object); - return; - } - - EmptyClipboard(); - SetClipboardData(CF_UNICODETEXT, object); - CloseClipboard(); - } - - u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber) { - assert(win != NULL); - - RGFW_UNUSED(jsNumber) - - return RGFW_registerJoystickF(win, (char*) ""); - } - - u16 RGFW_registerJoystickF(RGFW_window* win, char* file) { - assert(win != NULL); - RGFW_UNUSED(file) - - return RGFW_joystickCount - 1; - } - - void RGFW_window_moveMouse(RGFW_window* win, RGFW_point p) { - assert(win != NULL); - - SetCursorPos(p.x, p.y); - } - - #ifdef RGFW_OPENGL - void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) { - if (win == NULL) - wglMakeCurrent(NULL, NULL); - else - wglMakeCurrent(win->src.hdc, (HGLRC) win->src.ctx); - } + #else + RGFW_UNUSED(swapInterval); #endif +} - #ifndef RGFW_EGL - void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { - assert(win != NULL); - - #if defined(RGFW_OPENGL) - typedef BOOL(APIENTRY* PFNWGLSWAPINTERVALEXTPROC)(int interval); - static PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL; - static void* loadSwapFunc = (void*) 1; +#endif - if (loadSwapFunc == NULL) { - fprintf(stderr, "wglSwapIntervalEXT not supported\n"); - return; - } - - if (wglSwapIntervalEXT == NULL) { - loadSwapFunc = (void*) wglGetProcAddress("wglSwapIntervalEXT"); - wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) loadSwapFunc; - } - - if (wglSwapIntervalEXT(swapInterval) == FALSE) - fprintf(stderr, "Failed to set swap interval\n"); - #else - RGFW_UNUSED(swapInterval); - #endif - - } - #endif - - void RGFW_window_swapBuffers(RGFW_window* win) { - //assert(win != NULL); - /* clear the window*/ - - if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) { -#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) - #ifdef RGFW_OSMESA - RGFW_OSMesa_reorganize(); - #endif +void RGFW_window_swapBuffers(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + /* clear the window*/ + if (!(win->_flags & RGFW_NO_CPU_RENDER)) { + #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) HGDIOBJ oldbmp = SelectObject(win->src.hdcMem, win->src.bitmap); BitBlt(win->src.hdc, 0, 0, win->r.w, win->r.h, win->src.hdcMem, 0, 0, SRCCOPY); SelectObject(win->src.hdcMem, oldbmp); -#endif - } - - if (!(win->_winArgs & RGFW_NO_GPU_RENDER)) { - #ifdef RGFW_EGL - eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface); - #elif defined(RGFW_OPENGL) - SwapBuffers(win->src.hdc); - #endif - - #if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX) - win->src.swapchain->lpVtbl->Present(win->src.swapchain, 0, 0); - #endif - } + #endif } - char* createUTF8FromWideStringWin32(const WCHAR* source) { - char* target; - i32 size; + if (!(win->_flags & RGFW_NO_GPU_RENDER)) { + #ifdef RGFW_EGL + eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface); + #elif defined(RGFW_OPENGL) + SwapBuffers(win->src.hdc); + #endif - size = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL); - if (!size) { - return NULL; - } - - target = (char*) RGFW_CALLOC(size, 1); - - if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, size, NULL, NULL)) { - RGFW_FREE(target); - return NULL; - } - - return target; + #if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX) + win->src.swapchain->lpVtbl->Present(win->src.swapchain, 0, 0); + #endif } - - static inline LARGE_INTEGER RGFW_win32_initTimer(void) { - static LARGE_INTEGER frequency = {{0, 0}}; - if (frequency.QuadPart == 0) { - timeBeginPeriod(1); - QueryPerformanceFrequency(&frequency); - } +} - return frequency; +char* RGFW_createUTF8FromWideStringWin32(const WCHAR* source) { + if (source == NULL) { + return NULL; + } + i32 size = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL); + if (!size) { + return NULL; } - u64 RGFW_getTimeNS(void) { - LARGE_INTEGER frequency = RGFW_win32_initTimer(); + static char target[RGFW_MAX_PATH * 2]; + if (size > RGFW_MAX_PATH * 2) + size = RGFW_MAX_PATH * 2; - LARGE_INTEGER counter; - QueryPerformanceCounter(&counter); + target[size] = 0; - return (u64) ((counter.QuadPart * 1e9) / frequency.QuadPart); + if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, size, NULL, NULL)) { + return NULL; } - u64 RGFW_getTime(void) { - LARGE_INTEGER frequency = RGFW_win32_initTimer(); + return target; +} - LARGE_INTEGER counter; - QueryPerformanceCounter(&counter); - return (u64) (counter.QuadPart / (double) frequency.QuadPart); - } - - void RGFW_sleep(u64 ms) { - Sleep(ms); +static inline LARGE_INTEGER RGFW_win32_initTimer(void) { + static LARGE_INTEGER frequency = {{0, 0}}; + if (frequency.QuadPart == 0) { + #if !defined(RGFW_NO_WINMM) + timeBeginPeriod(1); + #endif + QueryPerformanceFrequency(&frequency); } + return frequency; +} + +u64 RGFW_getTimeNS(void) { + LARGE_INTEGER frequency = RGFW_win32_initTimer(); + + LARGE_INTEGER counter; + QueryPerformanceCounter(&counter); + + return (u64) ((counter.QuadPart * 1e9) / frequency.QuadPart); +} + +u64 RGFW_getTime(void) { + LARGE_INTEGER frequency = RGFW_win32_initTimer(); + + LARGE_INTEGER counter; + QueryPerformanceCounter(&counter); + return (u64) (counter.QuadPart / (double) frequency.QuadPart); +} + +void RGFW_sleep(u64 ms) { + Sleep(ms); +} + #ifndef RGFW_NO_THREADS - RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args) { return CreateThread(NULL, 0, ptr, args, 0, NULL); } - void RGFW_cancelThread(RGFW_thread thread) { CloseHandle((HANDLE) thread); } - void RGFW_joinThread(RGFW_thread thread) { WaitForSingleObject((HANDLE) thread, INFINITE); } - void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { SetThreadPriority((HANDLE) thread, priority); } + +RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args) { return CreateThread(NULL, 0, ptr, args, 0, NULL); } +void RGFW_cancelThread(RGFW_thread thread) { CloseHandle((HANDLE) thread); } +void RGFW_joinThread(RGFW_thread thread) { WaitForSingleObject((HANDLE) thread, INFINITE); } +void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { SetThreadPriority((HANDLE) thread, priority); } + #endif #endif /* RGFW_WINDOWS */ @@ -6652,7 +7096,7 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ -/* +/* Start of MacOS defines @@ -6660,678 +7104,837 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ */ #if defined(RGFW_MACOS) - /* - based on silicon.h - start of cocoa wrapper - */ +/* + based on silicon.h + start of cocoa wrapper +*/ -#include +#include #include #include #include #include - typedef CGRect NSRect; - typedef CGPoint NSPoint; - typedef CGSize NSSize; +typedef CGRect NSRect; +typedef CGPoint NSPoint; +typedef CGSize NSSize; - typedef void NSBitmapImageRep; - typedef void NSCursor; - typedef void NSDraggingInfo; - typedef void NSWindow; - typedef void NSApplication; - typedef void NSScreen; - typedef void NSEvent; - typedef void NSString; - typedef void NSOpenGLContext; - typedef void NSPasteboard; - typedef void NSColor; - typedef void NSArray; - typedef void NSImageRep; - typedef void NSImage; - typedef void NSOpenGLView; - - - typedef const char* NSPasteboardType; - typedef unsigned long NSUInteger; - typedef long NSInteger; - typedef NSInteger NSModalResponse; +typedef const char* NSPasteboardType; +typedef unsigned long NSUInteger; +typedef long NSInteger; +typedef NSInteger NSModalResponse; #ifdef __arm64__ /* ARM just uses objc_msgSend */ #define abi_objc_msgSend_stret objc_msgSend #define abi_objc_msgSend_fpret objc_msgSend -#else /* __i386__ */ +#else /* __i386__ */ /* x86 just uses abi_objc_msgSend_fpret and (NSColor *)objc_msgSend_id respectively */ #define abi_objc_msgSend_stret objc_msgSend_stret #define abi_objc_msgSend_fpret objc_msgSend_fpret #endif #define NSAlloc(nsclass) objc_msgSend_id((id)nsclass, sel_registerName("alloc")) -#define objc_msgSend_bool ((BOOL (*)(id, SEL))objc_msgSend) -#define objc_msgSend_void ((void (*)(id, SEL))objc_msgSend) -#define objc_msgSend_void_id ((void (*)(id, SEL, id))objc_msgSend) -#define objc_msgSend_uint ((NSUInteger (*)(id, SEL))objc_msgSend) -#define objc_msgSend_void_bool ((void (*)(id, SEL, BOOL))objc_msgSend) -#define objc_msgSend_bool_void ((BOOL (*)(id, SEL))objc_msgSend) -#define objc_msgSend_void_SEL ((void (*)(id, SEL, SEL))objc_msgSend) -#define objc_msgSend_id ((id (*)(id, SEL))objc_msgSend) -#define objc_msgSend_id_id ((id (*)(id, SEL, id))objc_msgSend) -#define objc_msgSend_id_bool ((BOOL (*)(id, SEL, id))objc_msgSend) -#define objc_msgSend_int ((id (*)(id, SEL, int))objc_msgSend) -#define objc_msgSend_arr ((id (*)(id, SEL, int))objc_msgSend) -#define objc_msgSend_ptr ((id (*)(id, SEL, void*))objc_msgSend) -#define objc_msgSend_class ((id (*)(Class, SEL))objc_msgSend) -#define objc_msgSend_class_char ((id (*)(Class, SEL, char*))objc_msgSend) +#define objc_msgSend_bool(x, y) ((BOOL (*)(id, SEL))objc_msgSend) ((id)(x), (SEL)y) +#define objc_msgSend_void(x, y) ((void (*)(id, SEL))objc_msgSend) ((id)(x), (SEL)y) +#define objc_msgSend_void_id(x, y, z) ((void (*)(id, SEL, id))objc_msgSend) ((id)x, (SEL)y, (id)z) +#define objc_msgSend_uint(x, y) ((NSUInteger (*)(id, SEL))objc_msgSend) ((id)(x), (SEL)y) +#define objc_msgSend_void_bool(x, y, z) ((void (*)(id, SEL, BOOL))objc_msgSend) ((id)(x), (SEL)y, (BOOL)z) +#define objc_msgSend_bool_void(x, y) ((BOOL (*)(id, SEL))objc_msgSend) ((id)(x), (SEL)y) +#define objc_msgSend_void_SEL(x, y, z) ((void (*)(id, SEL, SEL))objc_msgSend) ((id)(x), (SEL)y, (SEL)z) +#define objc_msgSend_id(x, y) ((id (*)(id, SEL))objc_msgSend) ((id)(x), (SEL)y) +#define objc_msgSend_id_id(x, y, z) ((id (*)(id, SEL, id))objc_msgSend) ((id)(x), (SEL)y, (id)z) +#define objc_msgSend_id_bool(x, y, z) ((BOOL (*)(id, SEL, id))objc_msgSend) ((id)(x), (SEL)y, (id)z) +#define objc_msgSend_int(x, y, z) ((id (*)(id, SEL, int))objc_msgSend) ((id)(x), (SEL)y, (int)z) +#define objc_msgSend_arr(x, y, z) ((id (*)(id, SEL, int))objc_msgSend) ((id)(x), (SEL)y, (int)z) +#define objc_msgSend_ptr(x, y, z) ((id (*)(id, SEL, void*))objc_msgSend) ((id)(x), (SEL)y, (void*)z) +#define objc_msgSend_class(x, y) ((id (*)(Class, SEL))objc_msgSend) ((Class)(x), (SEL)y) +#define objc_msgSend_class_char(x, y, z) ((id (*)(Class, SEL, char*))objc_msgSend) ((Class)(x), (SEL)y, (char*)z) - NSApplication* NSApp = NULL; +id NSApp = NULL; - void NSRelease(id obj) { - objc_msgSend_void(obj, sel_registerName("release")); +#define NSRelease(obj) objc_msgSend_void((id)obj, sel_registerName("release")) + +id NSString_stringWithUTF8String(const char* str) { + return ((id(*)(id, SEL, const char*))objc_msgSend) + ((id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), str); +} + +const char* NSString_to_char(id str) { + return ((const char* (*)(id, SEL)) objc_msgSend) ((id)(id)str, sel_registerName("UTF8String")); +} + +void si_impl_func_to_SEL_with_name(const char* class_name, const char* register_name, void* function) { + Class selected_class; + + if (RGFW_STRNCMP(class_name, "NSView", 6) == 0) { + selected_class = objc_getClass("ViewClass"); + } else if (RGFW_STRNCMP(class_name, "NSWindow", 8) == 0) { + selected_class = objc_getClass("WindowClass"); + } else { + selected_class = objc_getClass(class_name); } - #define release NSRelease + class_addMethod(selected_class, sel_registerName(register_name), (IMP) function, 0); +} - NSString* NSString_stringWithUTF8String(const char* str) { - return ((id(*)(id, SEL, const char*))objc_msgSend) - ((id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), str); - } +/* Header for the array. */ +typedef struct siArrayHeader { + size_t count; + /* TODO(EimaMei): Add a `type_width` later on. */ +} siArrayHeader; - const char* NSString_to_char(NSString* str) { - return ((const char* (*)(id, SEL)) objc_msgSend) (str, sel_registerName("UTF8String")); - } - - void si_impl_func_to_SEL_with_name(const char* class_name, const char* register_name, void* function) { - Class selected_class; - - if (strcmp(class_name, "NSView") == 0) { - selected_class = objc_getClass("ViewClass"); - } else if (strcmp(class_name, "NSWindow") == 0) { - selected_class = objc_getClass("WindowClass"); - } else { - selected_class = objc_getClass(class_name); - } - - class_addMethod(selected_class, sel_registerName(register_name), (IMP) function, 0); - } - - /* Header for the array. */ - typedef struct siArrayHeader { - size_t count; - /* TODO(EimaMei): Add a `type_width` later on. */ - } siArrayHeader; - - /* Gets the header of the siArray. */ +/* Gets the header of the siArray. */ #define SI_ARRAY_HEADER(s) ((siArrayHeader*)s - 1) - - void* si_array_init_reserve(size_t sizeof_element, size_t count) { - siArrayHeader* ptr = malloc(sizeof(siArrayHeader) + (sizeof_element * count)); - void* array = ptr + sizeof(siArrayHeader); - - siArrayHeader* header = SI_ARRAY_HEADER(array); - header->count = count; - - return array; - } - #define si_array_len(array) (SI_ARRAY_HEADER(array)->count) -#define si_func_to_SEL(class_name, function) si_impl_func_to_SEL_with_name(class_name, #function":", function) - /* Creates an Objective-C method (SEL) from a regular C function with the option to set the register name.*/ -#define si_func_to_SEL_with_name(class_name, register_name, function) si_impl_func_to_SEL_with_name(class_name, register_name":", function) - - unsigned char* NSBitmapImageRep_bitmapData(NSBitmapImageRep* imageRep) { - return ((unsigned char* (*)(id, SEL))objc_msgSend) - (imageRep, sel_registerName("bitmapData")); - } +#define si_func_to_SEL(class_name, function) si_impl_func_to_SEL_with_name(class_name, #function":", (void*)function) +/* Creates an Objective-C method (SEL) from a regular C function with the option to set the register name.*/ +#define si_func_to_SEL_with_name(class_name, register_name, function) si_impl_func_to_SEL_with_name(class_name, register_name":", (void*)function) -#define NS_ENUM(type, name) type name; enum +unsigned char* NSBitmapImageRep_bitmapData(id imageRep) { + return ((unsigned char* (*)(id, SEL))objc_msgSend) ((id)imageRep, sel_registerName("bitmapData")); +} - typedef NS_ENUM(NSUInteger, NSBitmapFormat) { - NSBitmapFormatAlphaFirst = 1 << 0, // 0 means is alpha last (RGBA, CMYKA, etc.) - NSBitmapFormatAlphaNonpremultiplied = 1 << 1, // 0 means is premultiplied - NSBitmapFormatFloatingPointSamples = 1 << 2, // 0 is integer +typedef RGFW_ENUM(NSUInteger, NSBitmapFormat) { + NSBitmapFormatAlphaFirst = 1 << 0, // 0 means is alpha last (RGBA, CMYKA, etc.) + NSBitmapFormatAlphaNonpremultiplied = 1 << 1, // 0 means is premultiplied + NSBitmapFormatFloatingpointSamples = 1 << 2, // 0 is integer - NSBitmapFormatSixteenBitLittleEndian API_AVAILABLE(macos(10.10)) = (1 << 8), - NSBitmapFormatThirtyTwoBitLittleEndian API_AVAILABLE(macos(10.10)) = (1 << 9), - NSBitmapFormatSixteenBitBigEndian API_AVAILABLE(macos(10.10)) = (1 << 10), - NSBitmapFormatThirtyTwoBitBigEndian API_AVAILABLE(macos(10.10)) = (1 << 11) - }; + NSBitmapFormatSixteenBitLittleEndian API_AVAILABLE(macos(10.10)) = (1 << 8), + NSBitmapFormatThirtyTwoBitLittleEndian API_AVAILABLE(macos(10.10)) = (1 << 9), + NSBitmapFormatSixteenBitBigEndian API_AVAILABLE(macos(10.10)) = (1 << 10), + NSBitmapFormatThirtyTwoBitBigEndian API_AVAILABLE(macos(10.10)) = (1 << 11) +}; - NSBitmapImageRep* NSBitmapImageRep_initWithBitmapData(unsigned char** planes, NSInteger width, NSInteger height, NSInteger bps, NSInteger spp, bool alpha, bool isPlanar, const char* colorSpaceName, NSBitmapFormat bitmapFormat, NSInteger rowBytes, NSInteger pixelBits) { - void* func = sel_registerName("initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bitmapFormat:bytesPerRow:bitsPerPixel:"); +id NSBitmapImageRep_initWithBitmapData(unsigned char** planes, NSInteger width, NSInteger height, NSInteger bps, NSInteger spp, bool alpha, bool isPlanar, const char* colorSpaceName, NSBitmapFormat bitmapFormat, NSInteger rowBytes, NSInteger pixelBits) { + SEL func = sel_registerName("initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bitmapFormat:bytesPerRow:bitsPerPixel:"); - return (NSBitmapImageRep*) ((id(*)(id, SEL, unsigned char**, NSInteger, NSInteger, NSInteger, NSInteger, bool, bool, const char*, NSBitmapFormat, NSInteger, NSInteger))objc_msgSend) - (NSAlloc((id)objc_getClass("NSBitmapImageRep")), func, planes, width, height, bps, spp, alpha, isPlanar, NSString_stringWithUTF8String(colorSpaceName), bitmapFormat, rowBytes, pixelBits); - } + return (id) ((id(*)(id, SEL, unsigned char**, NSInteger, NSInteger, NSInteger, NSInteger, bool, bool, id, NSBitmapFormat, NSInteger, NSInteger))objc_msgSend) + (NSAlloc((id)objc_getClass("NSBitmapImageRep")), func, planes, width, height, bps, spp, alpha, isPlanar, NSString_stringWithUTF8String(colorSpaceName), bitmapFormat, rowBytes, pixelBits); +} - NSColor* NSColor_colorWithSRGB(CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha) { - void* nsclass = objc_getClass("NSColor"); - void* func = sel_registerName("colorWithSRGBRed:green:blue:alpha:"); - return ((id(*)(id, SEL, CGFloat, CGFloat, CGFloat, CGFloat))objc_msgSend) - (nsclass, func, red, green, blue, alpha); - } +id NSColor_colorWithSRGB(CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha) { + void* nsclass = objc_getClass("NSColor"); + SEL func = sel_registerName("colorWithSRGBRed:green:blue:alpha:"); + return ((id(*)(id, SEL, CGFloat, CGFloat, CGFloat, CGFloat))objc_msgSend) + ((id)nsclass, func, red, green, blue, alpha); +} - NSCursor* NSCursor_initWithImage(NSImage* newImage, NSPoint aPoint) { - void* func = sel_registerName("initWithImage:hotSpot:"); - void* nsclass = objc_getClass("NSCursor"); +id NSCursor_initWithImage(id newImage, NSPoint aPoint) { + SEL func = sel_registerName("initWithImage:hotSpot:"); + void* nsclass = objc_getClass("NSCursor"); - return (NSCursor*) ((id(*)(id, SEL, id, NSPoint))objc_msgSend) - (NSAlloc(nsclass), func, newImage, aPoint); - } + return (id) ((id(*)(id, SEL, id, NSPoint))objc_msgSend) + (NSAlloc(nsclass), func, newImage, aPoint); +} - void NSImage_addRepresentation(NSImage* image, NSImageRep* imageRep) { - void* func = sel_registerName("addRepresentation:"); - objc_msgSend_void_id(image, func, imageRep); - } +void NSImage_addRepresentation(id image, id imageRep) { + SEL func = sel_registerName("addRepresentation:"); + objc_msgSend_void_id(image, func, (id)imageRep); +} - NSImage* NSImage_initWithSize(NSSize size) { - void* func = sel_registerName("initWithSize:"); - return ((id(*)(id, SEL, NSSize))objc_msgSend) - (NSAlloc((id)objc_getClass("NSImage")), func, size); - } +id NSImage_initWithSize(NSSize size) { + SEL func = sel_registerName("initWithSize:"); + return ((id(*)(id, SEL, NSSize))objc_msgSend) + (NSAlloc((id)objc_getClass("NSImage")), func, size); +} #define NS_OPENGL_ENUM_DEPRECATED(minVers, maxVers) API_AVAILABLE(macos(minVers)) - typedef NS_ENUM(NSInteger, NSOpenGLContextParameter) { - NSOpenGLContextParameterSwapInterval NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 222, /* 1 param. 0 -> Don't sync, 1 -> Sync to vertical retrace */ - NSOpenGLContextParametectxaceOrder NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 235, /* 1 param. 1 -> Above Window (default), -1 -> Below Window */ - NSOpenGLContextParametectxaceOpacity NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 236, /* 1 param. 1-> Surface is opaque (default), 0 -> non-opaque */ - NSOpenGLContextParametectxaceBackingSize NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 304, /* 2 params. Width/height of surface backing size */ - NSOpenGLContextParameterReclaimResources NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 308, /* 0 params. */ - NSOpenGLContextParameterCurrentRendererID NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 309, /* 1 param. Retrieves the current renderer ID */ - NSOpenGLContextParameterGPUVertexProcessing NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 310, /* 1 param. Currently processing vertices with GPU (get) */ - NSOpenGLContextParameterGPUFragmentProcessing NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 311, /* 1 param. Currently processing fragments with GPU (get) */ - NSOpenGLContextParameterHasDrawable NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 314, /* 1 param. Boolean returned if drawable is attached */ - NSOpenGLContextParameterMPSwapsInFlight NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 315, /* 1 param. Max number of swaps queued by the MP GL engine */ +typedef RGFW_ENUM(NSInteger, NSOpenGLContextParameter) { + NSOpenGLContextParameterSwapInterval NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 222, /* 1 param. 0 -> Don't sync, 1 -> Sync to vertical retrace */ + NSOpenGLContextParametectxaceOrder NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 235, /* 1 param. 1 -> Above Window (default), -1 -> Below Window */ + NSOpenGLContextParametectxaceOpacity NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 236, /* 1 param. 1-> Surface is opaque (default), 0 -> non-opaque */ + NSOpenGLContextParametectxaceBackingSize NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 304, /* 2 params. Width/height of surface backing size */ + NSOpenGLContextParameterReclaimResources NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 308, /* 0 params. */ + NSOpenGLContextParameterCurrentRendererID NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 309, /* 1 param. Retrieves the current renderer ID */ + NSOpenGLContextParameterGPUVertexProcessing NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 310, /* 1 param. Currently processing vertices with GPU (get) */ + NSOpenGLContextParameterGPUFragmentProcessing NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 311, /* 1 param. Currently processing fragments with GPU (get) */ + NSOpenGLContextParameterHasDrawable NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 314, /* 1 param. Boolean returned if drawable is attached */ + NSOpenGLContextParameterMPSwapsInFlight NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 315, /* 1 param. Max number of swaps queued by the MP GL engine */ - NSOpenGLContextParameterSwapRectangle API_DEPRECATED("", macos(10.0, 10.14)) = 200, /* 4 params. Set or get the swap rectangle {x, y, w, h} */ - NSOpenGLContextParameterSwapRectangleEnable API_DEPRECATED("", macos(10.0, 10.14)) = 201, /* Enable or disable the swap rectangle */ - NSOpenGLContextParameterRasterizationEnable API_DEPRECATED("", macos(10.0, 10.14)) = 221, /* Enable or disable all rasterization */ - NSOpenGLContextParameterStateValidation API_DEPRECATED("", macos(10.0, 10.14)) = 301, /* Validate state for multi-screen functionality */ - NSOpenGLContextParametectxaceSurfaceVolatile API_DEPRECATED("", macos(10.0, 10.14)) = 306, /* 1 param. Surface volatile state */ - }; + NSOpenGLContextParameterSwapRectangle API_DEPRECATED("", macos(10.0, 10.14)) = 200, /* 4 params. Set or get the swap rectangle {x, y, w, h} */ + NSOpenGLContextParameterSwapRectangleEnable API_DEPRECATED("", macos(10.0, 10.14)) = 201, /* Enable or disable the swap rectangle */ + NSOpenGLContextParameterRasterizationEnable API_DEPRECATED("", macos(10.0, 10.14)) = 221, /* Enable or disable all rasterization */ + NSOpenGLContextParameterStateValidation API_DEPRECATED("", macos(10.0, 10.14)) = 301, /* Validate state for multi-screen functionality */ + NSOpenGLContextParametectxaceSurfaceVolatile API_DEPRECATED("", macos(10.0, 10.14)) = 306, /* 1 param. Surface volatile state */ +}; - void NSOpenGLContext_setValues(NSOpenGLContext* context, const int* vals, NSOpenGLContextParameter param) { - void* func = sel_registerName("setValues:forParameter:"); - ((void (*)(id, SEL, const int*, NSOpenGLContextParameter))objc_msgSend) - (context, func, vals, param); - } +void NSOpenGLContext_setValues(id context, const int* vals, NSOpenGLContextParameter param) { + SEL func = sel_registerName("setValues:forParameter:"); + ((void (*)(id, SEL, const int*, NSOpenGLContextParameter))objc_msgSend) + (context, func, vals, param); +} - void* NSOpenGLPixelFormat_initWithAttributes(const uint32_t* attribs) { - void* func = sel_registerName("initWithAttributes:"); - return (void*) ((id(*)(id, SEL, const uint32_t*))objc_msgSend) - (NSAlloc((id)objc_getClass("NSOpenGLPixelFormat")), func, attribs); - } +void* NSOpenGLPixelFormat_initWithAttributes(const uint32_t* attribs) { + SEL func = sel_registerName("initWithAttributes:"); + return (void*) ((id(*)(id, SEL, const uint32_t*))objc_msgSend) + (NSAlloc((id)objc_getClass("NSOpenGLPixelFormat")), func, attribs); +} - NSOpenGLView* NSOpenGLView_initWithFrame(NSRect frameRect, uint32_t* format) { - void* func = sel_registerName("initWithFrame:pixelFormat:"); - return (NSOpenGLView*) ((id(*)(id, SEL, NSRect, uint32_t*))objc_msgSend) - (NSAlloc((id)objc_getClass("NSOpenGLView")), func, frameRect, format); - } +id NSOpenGLView_initWithFrame(NSRect frameRect, uint32_t* format) { + SEL func = sel_registerName("initWithFrame:pixelFormat:"); + return (id) ((id(*)(id, SEL, NSRect, uint32_t*))objc_msgSend) + (NSAlloc((id)objc_getClass("NSOpenGLView")), func, frameRect, format); +} - void NSCursor_performSelector(NSCursor* cursor, void* selector) { - void* func = sel_registerName("performSelector:"); - objc_msgSend_void_SEL(cursor, func, selector); - } +void NSCursor_performSelector(id cursor, SEL selector) { + SEL func = sel_registerName("performSelector:"); + objc_msgSend_void_SEL(cursor, func, selector); +} - NSPasteboard* NSPasteboard_generalPasteboard(void) { - return (NSPasteboard*) objc_msgSend_id((id)objc_getClass("NSPasteboard"), sel_registerName("generalPasteboard")); - } +id NSPasteboard_generalPasteboard(void) { + return (id) objc_msgSend_id((id)objc_getClass("NSPasteboard"), sel_registerName("generalPasteboard")); +} - NSString** cstrToNSStringArray(char** strs, size_t len) { - static NSString* nstrs[6]; - size_t i; - for (i = 0; i < len; i++) - nstrs[i] = NSString_stringWithUTF8String(strs[i]); +id* cstrToNSStringArray(char** strs, size_t len) { + static id nstrs[6]; + size_t i; + for (i = 0; i < len; i++) + nstrs[i] = NSString_stringWithUTF8String(strs[i]); - return nstrs; - } + return nstrs; +} - const char* NSPasteboard_stringForType(NSPasteboard* pasteboard, NSPasteboardType dataType) { - void* func = sel_registerName("stringForType:"); - return (const char*) NSString_to_char(((id(*)(id, SEL, const char*))objc_msgSend)(pasteboard, func, NSString_stringWithUTF8String(dataType))); - } +const char* NSPasteboard_stringForType(id pasteboard, NSPasteboardType dataType, size_t* len) { + SEL func = sel_registerName("stringForType:"); + id nsstr = NSString_stringWithUTF8String(dataType); + id nsString = ((id(*)(id, SEL, id))objc_msgSend)(pasteboard, func, nsstr); + const char* str = NSString_to_char(nsString); + if (len != NULL) + *len = (size_t)((NSUInteger(*)(id, SEL, int))objc_msgSend)(nsString, sel_registerName("maximumLengthOfBytesUsingEncoding:"), 4); + return str; +} - NSArray* c_array_to_NSArray(void* array, size_t len) { - SEL func = sel_registerName("initWithObjects:count:"); - void* nsclass = objc_getClass("NSArray"); - return ((id (*)(id, SEL, void*, NSUInteger))objc_msgSend) - (NSAlloc(nsclass), func, array, len); - } - - void NSregisterForDraggedTypes(void* view, NSPasteboardType* newTypes, size_t len) { - NSString** ntypes = cstrToNSStringArray((char**)newTypes, len); +id c_array_to_NSArray(void* array, size_t len) { + SEL func = sel_registerName("initWithObjects:count:"); + void* nsclass = objc_getClass("NSArray"); + return ((id (*)(id, SEL, void*, NSUInteger))objc_msgSend) + (NSAlloc(nsclass), func, array, len); +} - NSArray* array = c_array_to_NSArray(ntypes, len); - objc_msgSend_void_id(view, sel_registerName("registerForDraggedTypes:"), array); - NSRelease(array); - } +void NSregisterForDraggedTypes(id view, NSPasteboardType* newTypes, size_t len) { + id* ntypes = cstrToNSStringArray((char**)newTypes, len); - NSInteger NSPasteBoard_declareTypes(NSPasteboard* pasteboard, NSPasteboardType* newTypes, size_t len, void* owner) { - NSString** ntypes = cstrToNSStringArray((char**)newTypes, len); + id array = c_array_to_NSArray(ntypes, len); + objc_msgSend_void_id(view, sel_registerName("registerForDraggedTypes:"), array); + NSRelease(array); +} - void* func = sel_registerName("declareTypes:owner:"); +NSInteger NSPasteBoard_declareTypes(id pasteboard, NSPasteboardType* newTypes, size_t len, void* owner) { + id* ntypes = cstrToNSStringArray((char**)newTypes, len); - NSArray* array = c_array_to_NSArray(ntypes, len); + SEL func = sel_registerName("declareTypes:owner:"); - NSInteger output = ((NSInteger(*)(id, SEL, id, void*))objc_msgSend) - (pasteboard, func, array, owner); - NSRelease(array); + id array = c_array_to_NSArray(ntypes, len); - return output; - } + NSInteger output = ((NSInteger(*)(id, SEL, id, void*))objc_msgSend) + (pasteboard, func, array, owner); + NSRelease(array); - bool NSPasteBoard_setString(NSPasteboard* pasteboard, const char* stringToWrite, NSPasteboardType dataType) { - void* func = sel_registerName("setString:forType:"); - return ((bool (*)(id, SEL, id, NSPasteboardType))objc_msgSend) - (pasteboard, func, NSString_stringWithUTF8String(stringToWrite), NSString_stringWithUTF8String(dataType)); - } + return output; +} - void NSRetain(id obj) { objc_msgSend_void(obj, sel_registerName("retain")); } +bool NSPasteBoard_setString(id pasteboard, const char* stringToWrite, NSPasteboardType dataType) { + SEL func = sel_registerName("setString:forType:"); + return ((bool (*)(id, SEL, id, id))objc_msgSend) + (pasteboard, func, NSString_stringWithUTF8String(stringToWrite), NSString_stringWithUTF8String(dataType)); +} - typedef enum NSApplicationActivationPolicy { - NSApplicationActivationPolicyRegular, - NSApplicationActivationPolicyAccessory, - NSApplicationActivationPolicyProhibited - } NSApplicationActivationPolicy; +#define NSRetain(obj) objc_msgSend_void((id)obj, sel_registerName("retain")) - typedef NS_ENUM(u32, NSBackingStoreType) { - NSBackingStoreRetained = 0, - NSBackingStoreNonretained = 1, - NSBackingStoreBuffered = 2 - }; +typedef enum NSApplicationActivationPolicy { + NSApplicationActivationPolicyRegular, + NSApplicationActivationPolicyAccessory, + NSApplicationActivationPolicyProhibited +} NSApplicationActivationPolicy; - typedef NS_ENUM(u32, NSWindowStyleMask) { - NSWindowStyleMaskBorderless = 0, - NSWindowStyleMaskTitled = 1 << 0, - NSWindowStyleMaskClosable = 1 << 1, - NSWindowStyleMaskMiniaturizable = 1 << 2, - NSWindowStyleMaskResizable = 1 << 3, - NSWindowStyleMaskTexturedBackground = 1 << 8, /* deprecated */ - NSWindowStyleMaskUnifiedTitleAndToolbar = 1 << 12, - NSWindowStyleMaskFullScreen = 1 << 14, - NSWindowStyleMaskFullSizeContentView = 1 << 15, - NSWindowStyleMaskUtilityWindow = 1 << 4, - NSWindowStyleMaskDocModalWindow = 1 << 6, - NSWindowStyleMaskNonactivatingPanel = 1 << 7, - NSWindowStyleMaskHUDWindow = 1 << 13 - }; +typedef RGFW_ENUM(u32, NSBackingStoreType) { + NSBackingStoreRetained = 0, + NSBackingStoreNonretained = 1, + NSBackingStoreBuffered = 2 +}; - NSPasteboardType const NSPasteboardTypeString = "public.utf8-plain-text"; // Replaces NSStringPboardType +typedef RGFW_ENUM(u32, NSWindowStyleMask) { + NSWindowStyleMaskBorderless = 0, + NSWindowStyleMaskTitled = 1 << 0, + NSWindowStyleMaskClosable = 1 << 1, + NSWindowStyleMaskMiniaturizable = 1 << 2, + NSWindowStyleMaskResizable = 1 << 3, + NSWindowStyleMaskTexturedBackground = 1 << 8, /* deprecated */ + NSWindowStyleMaskUnifiedTitleAndToolbar = 1 << 12, + NSWindowStyleMaskFullScreen = 1 << 14, + NSWindowStyleMaskFullSizeContentView = 1 << 15, + NSWindowStyleMaskUtilityWindow = 1 << 4, + NSWindowStyleMaskDocModalWindow = 1 << 6, + NSWindowStyleMaskNonactivatingpanel = 1 << 7, + NSWindowStyleMaskHUDWindow = 1 << 13 +}; + +NSPasteboardType const NSPasteboardTypeString = "public.utf8-plain-text"; // Replaces NSStringPasteboardType - typedef NS_ENUM(i32, NSDragOperation) { - NSDragOperationNone = 0, - NSDragOperationCopy = 1, - NSDragOperationLink = 2, - NSDragOperationGeneric = 4, - NSDragOperationPrivate = 8, - NSDragOperationMove = 16, - NSDragOperationDelete = 32, - NSDragOperationEvery = ULONG_MAX, +typedef RGFW_ENUM(i32, NSDragOperation) { + NSDragOperationNone = 0, + NSDragOperationCopy = 1, + NSDragOperationLink = 2, + NSDragOperationGeneric = 4, + NSDragOperationPrivate = 8, + NSDragOperationMove = 16, + NSDragOperationDelete = 32, + NSDragOperationEvery = ULONG_MAX, - //NSDragOperationAll_Obsolete API_DEPRECATED("", macos(10.0,10.10)) = 15, // Use NSDragOperationEvery - //NSDragOperationAll API_DEPRECATED("", macos(10.0,10.10)) = NSDragOperationAll_Obsolete, // Use NSDragOperationEvery - }; + //NSDragOperationAll_Obsolete API_DEPRECATED("", macos(10.0,10.10)) = 15, // Use NSDragOperationEvery + //NSDragOperationAll API_DEPRECATED("", macos(10.0,10.10)) = NSDragOperationAll_Obsolete, // Use NSDragOperationEvery +}; - void* NSArray_objectAtIndex(NSArray* array, NSUInteger index) { - void* func = sel_registerName("objectAtIndex:"); - return ((id(*)(id, SEL, NSUInteger))objc_msgSend)(array, func, index); - } +void* NSArray_objectAtIndex(id array, NSUInteger index) { + SEL func = sel_registerName("objectAtIndex:"); + return ((id(*)(id, SEL, NSUInteger))objc_msgSend)(array, func, index); +} - const char** NSPasteboard_readObjectsForClasses(NSPasteboard* pasteboard, Class* classArray, size_t len, void* options) { - void* func = sel_registerName("readObjectsForClasses:options:"); +id NSWindow_contentView(id window) { + SEL func = sel_registerName("contentView"); + return objc_msgSend_id(window, func); +} - NSArray* array = c_array_to_NSArray(classArray, len); +/* + End of cocoa wrapper +*/ - NSArray* output = (NSArray*) ((id(*)(id, SEL, id, void*))objc_msgSend) - (pasteboard, func, array, options); - - NSRelease(array); - NSUInteger count = ((NSUInteger(*)(id, SEL))objc_msgSend)(output, sel_registerName("count")); - - const char** res = si_array_init_reserve(sizeof(const char*), count); - - void* path_func = sel_registerName("path"); - - for (NSUInteger i = 0; i < count; i++) { - void* url = NSArray_objectAtIndex(output, i); - NSString* url_str = ((id(*)(id, SEL))objc_msgSend)(url, path_func); - res[i] = NSString_to_char(url_str); - } - - return res; - } - - void* NSWindow_contentView(NSWindow* window) { - void* func = sel_registerName("contentView"); - return objc_msgSend_id(window, func); - } - - /* - End of cocoa wrapper - */ - - char* RGFW_mouseIconSrc[] = {"arrowCursor", "arrowCursor", "IBeamCursor", "crosshairCursor", "pointingHandCursor", "resizeLeftRightCursor", "resizeUpDownCursor", "_windowResizeNorthWestSouthEastCursor", "_windowResizeNorthEastSouthWestCursor", "closedHandCursor", "operationNotAllowedCursor"}; - - void* RGFWnsglFramework = NULL; +const char* RGFW_mouseIconSrc[] = {"arrowCursor", "arrowCursor", "IBeamCursor", "crosshairCursor", "pointingHandCursor", "resizeLeftRightCursor", "resizeUpDownCursor", "_windowResizeNorthWestSouthEastCursor", "_windowResizeNorthEastSouthWestCursor", "closedHandCursor", "operationNotAllowedCursor"}; #ifdef RGFW_OPENGL - void* RGFW_getProcAddress(const char* procname) { - if (RGFWnsglFramework == NULL) - RGFWnsglFramework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl")); +CFBundleRef RGFWnsglFramework = NULL; - CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault, procname, kCFStringEncodingASCII); +void* RGFW_getProcAddress(const char* procname) { + if (RGFWnsglFramework == NULL) + RGFWnsglFramework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl")); - void* symbol = CFBundleGetFunctionPointerForName(RGFWnsglFramework, symbolName); + CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault, procname, kCFStringEncodingASCII); - CFRelease(symbolName); + void* symbol = (void*)CFBundleGetFunctionPointerForName(RGFWnsglFramework, symbolName); - return symbol; - } + CFRelease(symbolName); + + return symbol; +} #endif - CVReturn displayCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* inNow, const CVTimeStamp* inOutputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext) { - RGFW_UNUSED(displayLink) RGFW_UNUSED(inNow) RGFW_UNUSED(inOutputTime) RGFW_UNUSED(flagsIn) RGFW_UNUSED(flagsOut) RGFW_UNUSED(displayLinkContext) - return kCVReturnSuccess; - } - - id NSWindow_delegate(RGFW_window* win) { - return (id) objc_msgSend_id(win->src.window, sel_registerName("delegate")); - } - - u32 RGFW_OnClose(void* self) { - RGFW_window* win = NULL; - object_getInstanceVariable(self, "RGFW_window", (void*)&win); - if (win == NULL) - return true; - - win->event.type = RGFW_quit; - RGFW_windowQuitCallback(win); +id NSWindow_delegate(RGFW_window* win) { + return (id) objc_msgSend_id((id)win->src.window, sel_registerName("delegate")); +} +u32 RGFW_OnClose(id self) { + RGFW_window* win = NULL; + object_getInstanceVariable(self, (const char*)"RGFW_window", (void**)&win); + if (win == NULL) return true; + + win->event.type = RGFW_quit; + RGFW_windowQuitCallback(win); + + return true; +} + +/* NOTE(EimaMei): Fixes the constant clicking when the app is running under a terminal. */ +bool acceptsFirstResponder(void) { return true; } +bool performKeyEquivalent(id event) { RGFW_UNUSED(event); return true; } + +NSDragOperation draggingEntered(id self, SEL sel, id sender) { + RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel); + + return NSDragOperationCopy; +} +NSDragOperation draggingUpdated(id self, SEL sel, id sender) { + RGFW_UNUSED(sel); + + RGFW_window* win = NULL; + object_getInstanceVariable(self, "RGFW_window", (void**)&win); + if (win == NULL) + return 0; + + if (!(win->_flags & RGFW_windowAllowDND)) { + return 0; } - /* NOTE(EimaMei): Fixes the constant clicking when the app is running under a terminal. */ - bool acceptsFirstResponder(void) { return true; } - bool performKeyEquivalent(NSEvent* event) { RGFW_UNUSED(event); return true; } + win->event.type = RGFW_DNDInit; + win->src.dndPassed = 0; - NSDragOperation draggingEntered(id self, SEL sel, id sender) { - RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel); + NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(sender, sel_registerName("draggingLocation")); - return NSDragOperationCopy; - } - NSDragOperation draggingUpdated(id self, SEL sel, id sender) { - RGFW_UNUSED(sel); - - RGFW_window* win = NULL; - object_getInstanceVariable(self, "RGFW_window", (void*)&win); - if (win == NULL) - return 0; - - if (!(win->_winArgs & RGFW_ALLOW_DND)) { - return 0; - } - - win->event.type = RGFW_dnd_init; - win->src.dndPassed = 0; - - NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(sender, sel_registerName("draggingLocation")); - - win->event.point = RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y)); - RGFW_dndInitCallback(win, win->event.point); - - return NSDragOperationCopy; - } - bool prepareForDragOperation(id self) { - RGFW_window* win = NULL; - object_getInstanceVariable(self, "RGFW_window", (void*)&win); - if (win == NULL) - return true; - - if (!(win->_winArgs & RGFW_ALLOW_DND)) { - return false; - } + win->event.point = RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y)); + RGFW_dndInitCallback(win, win->event.point); + return NSDragOperationCopy; +} +bool prepareForDragOperation(id self) { + RGFW_window* win = NULL; + object_getInstanceVariable(self, "RGFW_window", (void**)&win); + if (win == NULL) return true; + + if (!(win->_flags & RGFW_windowAllowDND)) { + return false; } - void RGFW__osxDraggingEnded(id self, SEL sel, id sender) { RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel); return; } + return true; +} - /* NOTE(EimaMei): Usually, you never need 'id self, SEL cmd' for C -> Obj-C methods. This isn't the case. */ - bool performDragOperation(id self, SEL sel, id sender) { - RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel); +void RGFW__osxDraggingEnded(id self, SEL sel, id sender) { RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel); return; } - RGFW_window* win = NULL; - object_getInstanceVariable(self, "RGFW_window", (void*)&win); +/* NOTE(EimaMei): Usually, you never need 'id self, SEL cmd' for C -> Obj-C methods. This isn't the case. */ +bool performDragOperation(id self, SEL sel, id sender) { + RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel); - if (win == NULL) - return false; + RGFW_window* win = NULL; + object_getInstanceVariable(self, "RGFW_window", (void**)&win); - // NSPasteboard* pasteBoard = objc_msgSend_id(sender, sel_registerName("draggingPasteboard")); + if (win == NULL) + return false; - ///////////////////////////// - id pasteBoard = objc_msgSend_id(sender, sel_registerName("draggingPasteboard")); + // id pasteBoard = objc_msgSend_id(sender, sel_registerName("draggingPasteboard")); - // Get the types of data available on the pasteboard - id types = objc_msgSend_id(pasteBoard, sel_registerName("types")); + ///////////////////////////// + id pasteBoard = objc_msgSend_id(sender, sel_registerName("draggingPasteboard")); - // Get the string type for file URLs - id fileURLsType = objc_msgSend_class_char(objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), "NSFilenamesPboardType"); + // Get the types of data available on the pasteboard + id types = objc_msgSend_id(pasteBoard, sel_registerName("types")); - // Check if the pasteboard contains file URLs - if (objc_msgSend_id_bool(types, sel_registerName("containsObject:"), fileURLsType) == 0) { - #ifdef RGFW_DEBUG - printf("No files found on the pasteboard.\n"); - #endif + // Get the string type for file URLs + id fileURLsType = objc_msgSend_class_char(objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), "NSFilenamesPboardType"); - return 0; - } + // Check if the pasteboard contains file URLs + if (objc_msgSend_id_bool(types, sel_registerName("containsObject:"), fileURLsType) == 0) { + #ifdef RGFW_DEBUG + printf("No files found on the pasteboard.\n"); + #endif - id fileURLs = objc_msgSend_id_id(pasteBoard, sel_registerName("propertyListForType:"), fileURLsType); - int count = ((int (*)(id, SEL))objc_msgSend)(fileURLs, sel_registerName("count")); + return 0; + } - if (count == 0) - return 0; + id fileURLs = objc_msgSend_id_id(pasteBoard, sel_registerName("propertyListForType:"), fileURLsType); + int count = ((int (*)(id, SEL))objc_msgSend)(fileURLs, sel_registerName("count")); - for (int i = 0; i < count; i++) { - id fileURL = objc_msgSend_arr(fileURLs, sel_registerName("objectAtIndex:"), i); - const char *filePath = ((const char* (*)(id, SEL))objc_msgSend)(fileURL, sel_registerName("UTF8String")); - strncpy(win->event.droppedFiles[i], filePath, RGFW_MAX_PATH); - win->event.droppedFiles[i][RGFW_MAX_PATH - 1] = '\0'; - } - win->event.droppedFilesCount = count; + if (count == 0) + return 0; - win->event.type = RGFW_dnd; - win->src.dndPassed = 0; - - NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(sender, sel_registerName("draggingLocation")); - win->event.point = RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y)); - - RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount); + for (int i = 0; i < count; i++) { + id fileURL = objc_msgSend_arr(fileURLs, sel_registerName("objectAtIndex:"), i); + const char *filePath = ((const char* (*)(id, SEL))objc_msgSend)(fileURL, sel_registerName("UTF8String")); + RGFW_MEMCPY(win->event.droppedFiles[i], filePath, RGFW_MAX_PATH); + win->event.droppedFiles[i][RGFW_MAX_PATH - 1] = '\0'; + } + win->event.droppedFilesCount = count; + + win->event.type = RGFW_DND; + win->src.dndPassed = 0; + + NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(sender, sel_registerName("draggingLocation")); + win->event.point = RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y)); + + RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount); + + return false; +} + +#ifndef RGFW_NO_IOKIT +#include +#include + +IOHIDDeviceRef RGFW_osxControllers[4] = {NULL}; + +int findControllerIndex(IOHIDDeviceRef device) { + for (int i = 0; i < 4; i++) + if (RGFW_osxControllers[i] == device) + return i; + return -1; +} + +#define RGFW_gamepadEventQueueMAX 11 +RGFW_event RGFW_gamepadEventQueue[RGFW_gamepadEventQueueMAX]; +size_t RGFW_gamepadEventQueueCount = 0; + +void RGFW__osxInputValueChangedCallback(void *context, IOReturn result, void *sender, IOHIDValueRef value) { + RGFW_UNUSED(context); RGFW_UNUSED(result); RGFW_UNUSED(sender); + + if (RGFW_gamepadEventQueueCount >= RGFW_gamepadEventQueueMAX - 1) + return; + + IOHIDElementRef element = IOHIDValueGetElement(value); + + IOHIDDeviceRef device = IOHIDElementGetDevice(element); + size_t index = findControllerIndex(device); + + uint32_t usagePage = IOHIDElementGetUsagePage(element); + uint32_t usage = IOHIDElementGetUsage(element); + + CFIndex intValue = IOHIDValueGetIntegerValue(value); + + u8 RGFW_osx2RGFWSrc[2][RGFW_gamepadFinal] = {{ + 0, RGFW_gamepadSelect, RGFW_gamepadL3, RGFW_gamepadR3, RGFW_gamepadStart, + RGFW_gamepadUp, RGFW_gamepadRight, RGFW_gamepadDown, RGFW_gamepadLeft, + RGFW_gamepadL2, RGFW_gamepadR2, RGFW_gamepadL1, RGFW_gamepadR1, + RGFW_gamepadY, RGFW_gamepadB, RGFW_gamepadA, RGFW_gamepadX, RGFW_gamepadHome}, + {0, RGFW_gamepadA, RGFW_gamepadB, RGFW_gamepadR3, RGFW_gamepadX, + RGFW_gamepadY, RGFW_gamepadRight, RGFW_gamepadL1, RGFW_gamepadR1, + RGFW_gamepadL2, RGFW_gamepadR2, RGFW_gamepadDown, RGFW_gamepadStart, + RGFW_gamepadUp, RGFW_gamepadL3, RGFW_gamepadSelect, RGFW_gamepadStart, RGFW_gamepadHome} + }; + + u8* RGFW_osx2RGFW = RGFW_osx2RGFWSrc[0]; + if (RGFW_gamepads_type[index] == RGFW_gamepadMicrosoft) + RGFW_osx2RGFW = RGFW_osx2RGFWSrc[1]; - return false; + RGFW_event event; + + switch (usagePage) { + case kHIDPage_Button: { + u8 button = 0; + if (usage < sizeof(RGFW_osx2RGFW)) + button = RGFW_osx2RGFW[usage]; + + RGFW_gamepadButtonCallback(RGFW_root, index, button, intValue); + RGFW_gamepadPressed[index][button].prev = RGFW_gamepadPressed[index][button].current; + RGFW_gamepadPressed[index][button].current = intValue; + event.type = intValue ? RGFW_gamepadButtonPressed: RGFW_gamepadButtonReleased; + event.button = button; + event.gamepad = index; + + RGFW_gamepadEventQueue[RGFW_gamepadEventQueueCount] = event; + RGFW_gamepadEventQueueCount++; + break; + } + case kHIDPage_GenericDesktop: { + CFIndex logicalMin = IOHIDElementGetLogicalMin(element); + CFIndex logicalMax = IOHIDElementGetLogicalMax(element); + + if (logicalMax <= logicalMin) return; + if (intValue < logicalMin) intValue = logicalMin; + if (intValue > logicalMax) intValue = logicalMax; + + i8 value = (i8)(-100.0 + ((intValue - logicalMin) * 200.0) / (logicalMax - logicalMin)); + + switch (usage) { + case kHIDUsage_GD_X: RGFW_gamepadAxes[index][0].x = value; event.whichAxis = 0; break; + case kHIDUsage_GD_Y: RGFW_gamepadAxes[index][0].y = value; event.whichAxis = 0; break; + case kHIDUsage_GD_Z: RGFW_gamepadAxes[index][1].x = value; event.whichAxis = 1; break; + case kHIDUsage_GD_Rz: RGFW_gamepadAxes[index][1].y = value; event.whichAxis = 1; break; + default: return; + } + + event.type = RGFW_gamepadAxisMove; + event.gamepad = index; + + event.axis[0] = RGFW_gamepadAxes[index][0]; + event.axis[1] = RGFW_gamepadAxes[index][1]; + + RGFW_gamepadEventQueue[RGFW_gamepadEventQueueCount] = event; + RGFW_gamepadEventQueueCount++; + + RGFW_gamepadAxisCallback(RGFW_root, index, event.axis, 2, event.whichAxis); + } + } +} + +void RGFW__osxDeviceAddedCallback(void* context, IOReturn result, void *sender, IOHIDDeviceRef device) { + RGFW_UNUSED(context); RGFW_UNUSED(result); RGFW_UNUSED(sender); + CFTypeRef usageRef = (CFTypeRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDPrimaryUsageKey)); + int usage = 0; + if (usageRef) + CFNumberGetValue((CFNumberRef)usageRef, kCFNumberIntType, (void*)&usage); + + if (usage != kHIDUsage_GD_Joystick && usage != kHIDUsage_GD_GamePad && usage != kHIDUsage_GD_MultiAxisController) { + return; } - static void NSMoveToResourceDir(void) { - /* sourced from glfw */ - char resourcesPath[255]; + for (size_t i = 0; i < 4; i++) { + if (RGFW_osxControllers[i] != NULL) + continue; - CFBundleRef bundle = CFBundleGetMainBundle(); - if (!bundle) - return; + RGFW_osxControllers[i] = device; - CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(bundle); - CFStringRef last = CFURLCopyLastPathComponent(resourcesURL); + IOHIDDeviceRegisterInputValueCallback(device, RGFW__osxInputValueChangedCallback, NULL); - if ( - CFStringCompare(CFSTR("Resources"), last, 0) != kCFCompareEqualTo || - CFURLGetFileSystemRepresentation(resourcesURL, true, (u8*) resourcesPath, 255) == 0 - ) { - CFRelease(last); - CFRelease(resourcesURL); - return; - } + CFStringRef deviceName = (CFStringRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey)); + if (deviceName) + CFStringGetCString(deviceName, RGFW_gamepads_name[i], sizeof(RGFW_gamepads_name[i]), kCFStringEncodingUTF8); + RGFW_gamepads_type[i] = RGFW_gamepadUnknown; + if (strstr(RGFW_gamepads_name[i], "Microsoft") || strstr(RGFW_gamepads_name[i], "X-Box") || strstr(RGFW_gamepads_name[i], "Xbox")) + RGFW_gamepads_type[i] = RGFW_gamepadMicrosoft; + else if (strstr(RGFW_gamepads_name[i], "PlayStation") || strstr(RGFW_gamepads_name[i], "PS3") || strstr(RGFW_gamepads_name[i], "PS4") || strstr(RGFW_gamepads_name[i], "PS5")) + RGFW_gamepads_type[i] = RGFW_gamepadSony; + else if (strstr(RGFW_gamepads_name[i], "Nintendo")) + RGFW_gamepads_type[i] = RGFW_gamepadNintendo; + else if (strstr(RGFW_gamepads_name[i], "Logitech")) + RGFW_gamepads_type[i] = RGFW_gamepadLogitech; + + RGFW_gamepads[i] = i; + RGFW_gamepadCount++; + + RGFW_event ev; + ev.type = RGFW_gamepadConnected; + ev.gamepad = i; + RGFW_gamepadEventQueue[RGFW_gamepadEventQueueCount] = ev; + RGFW_gamepadEventQueueCount++; + RGFW_gamepadCallback(RGFW_root, i, 1); + break; + } +} + +void RGFW__osxDeviceRemovedCallback(void *context, IOReturn result, void *sender, IOHIDDeviceRef device) { + RGFW_UNUSED(context); RGFW_UNUSED(result); RGFW_UNUSED(sender); RGFW_UNUSED(device); + CFNumberRef usageRef = (CFNumberRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDPrimaryUsageKey)); + int usage = 0; + if (usageRef) + CFNumberGetValue(usageRef, kCFNumberIntType, &usage); + + if (usage != kHIDUsage_GD_Joystick && usage != kHIDUsage_GD_GamePad && usage != kHIDUsage_GD_MultiAxisController) { + return; + } + + i32 index = findControllerIndex(device); + if (index != -1) + RGFW_osxControllers[index] = NULL; + + RGFW_event ev; + ev.type = RGFW_gamepadDisconnected; + ev.gamepad = index; + RGFW_gamepadEventQueue[RGFW_gamepadEventQueueCount] = ev; + RGFW_gamepadEventQueueCount++; + RGFW_gamepadCallback(RGFW_root, index, 0); + + RGFW_gamepadCount--; +} + +RGFWDEF void RGFW_osxInitIOKit(void); +void RGFW_osxInitIOKit(void) { + IOHIDManagerRef hidManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); + if (!hidManager) { + fprintf(stderr, "Failed to create IOHIDManager.\n"); + return; + } + + CFMutableDictionaryRef matchingDictionary = CFDictionaryCreateMutable( + kCFAllocatorDefault, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks + ); + if (!matchingDictionary) { + fprintf(stderr, "Failed to create matching dictionary.\n"); + CFRelease(hidManager); + return; + } + + CFDictionarySetValue( + matchingDictionary, + CFSTR(kIOHIDDeviceUsagePageKey), + CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, (int[]){kHIDPage_GenericDesktop}) + ); + + IOHIDManagerSetDeviceMatching(hidManager, matchingDictionary); + + IOHIDManagerRegisterDeviceMatchingCallback(hidManager, RGFW__osxDeviceAddedCallback, NULL); + IOHIDManagerRegisterDeviceRemovalCallback(hidManager, RGFW__osxDeviceRemovedCallback, NULL); + + IOHIDManagerScheduleWithRunLoop(hidManager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); + + IOHIDManagerOpen(hidManager, kIOHIDOptionsTypeNone); + + // Execute the run loop once in order to register any initially-attached joysticks + CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, false); +} +#endif + +void NSMoveToResourceDir(void) { + char resourcesPath[255]; + + CFBundleRef bundle = CFBundleGetMainBundle(); + if (!bundle) + return; + + CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(bundle); + CFStringRef last = CFURLCopyLastPathComponent(resourcesURL); + + if ( + CFStringCompare(CFSTR("Resources"), last, 0) != kCFCompareEqualTo || + CFURLGetFileSystemRepresentation(resourcesURL, true, (u8*) resourcesPath, 255) == 0 + ) { CFRelease(last); CFRelease(resourcesURL); - - chdir(resourcesPath); + return; } + CFRelease(last); + CFRelease(resourcesURL); - NSSize RGFW__osxWindowResize(void* self, SEL sel, NSSize frameSize) { - RGFW_UNUSED(sel); + chdir(resourcesPath); +} - RGFW_window* win = NULL; - object_getInstanceVariable(self, "RGFW_window", (void*)&win); - if (win == NULL) - return frameSize; - - win->r.w = frameSize.width; - win->r.h = frameSize.height; - win->event.type = RGFW_windowResized; - RGFW_windowResizeCallback(win, win->r); + +NSSize RGFW__osxWindowResize(id self, SEL sel, NSSize frameSize) { + RGFW_UNUSED(sel); + + RGFW_window* win = NULL; + object_getInstanceVariable(self, "RGFW_window", (void**)&win); + if (win == NULL) return frameSize; - } - void RGFW__osxWindowMove(void* self, SEL sel) { - RGFW_UNUSED(sel); + win->r.w = frameSize.width; + win->r.h = frameSize.height; + win->event.type = RGFW_windowResized; + RGFW_windowResizeCallback(win, win->r); + return frameSize; +} - RGFW_window* win = NULL; - object_getInstanceVariable(self, "RGFW_window", (void*)&win); - if (win == NULL) - return; - - NSRect frame = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)(win->src.window, sel_registerName("frame")); - win->r.x = (i32) frame.origin.x; - win->r.y = (i32) frame.origin.y; +void RGFW__osxWindowMove(id self, SEL sel) { + RGFW_UNUSED(sel); - win->event.type = RGFW_windowMoved; - RGFW_windowMoveCallback(win, win->r); - } + RGFW_window* win = NULL; + object_getInstanceVariable(self, "RGFW_window", (void**)&win); + if (win == NULL) + return; - void RGFW__osxUpdateLayer(void* self, SEL sel) { - RGFW_UNUSED(sel); + NSRect frame = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)((id)win->src.window, sel_registerName("frame")); + win->r.x = (i32) frame.origin.x; + win->r.y = (i32) frame.origin.y; - RGFW_window* win = NULL; - object_getInstanceVariable(self, "RGFW_window", (void*)&win); - if (win == NULL) - return; - - win->event.type = RGFW_windowRefresh; - RGFW_windowRefreshCallback(win); - } + win->event.type = RGFW_windowMoved; + RGFW_windowMoveCallback(win, win->r); +} - RGFWDEF void RGFW_init_buffer(RGFW_window* win); - void RGFW_init_buffer(RGFW_window* win) { - #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) - if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0) - RGFW_bufferSize = RGFW_getScreenSize(); - - win->buffer = RGFW_MALLOC(RGFW_bufferSize.w * RGFW_bufferSize.h * 4); +void RGFW__osxUpdateLayer(id self, SEL sel) { + RGFW_UNUSED(sel); - #ifdef RGFW_OSMESA - win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL); - OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h); - #endif - #else + RGFW_window* win = NULL; + object_getInstanceVariable(self, "RGFW_window", (void**)&win); + if (win == NULL) + return; + + win->event.type = RGFW_windowRefresh; + RGFW_windowRefreshCallback(win); +} + +RGFWDEF void RGFW_init_buffer(RGFW_window* win); +void RGFW_init_buffer(RGFW_window* win) { + #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) + if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0) + RGFW_bufferSize = RGFW_getScreenSize(); + + win->buffer = RGFW_alloc(RGFW_bufferSize.w * RGFW_bufferSize.h * 4); + win->_flags |= RGFW_BUFFER_ALLOC; + #ifdef RGFW_OSMESA + win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL); + OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h); + #endif + #else RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ + #endif +} + +void RGFW_window_cocoaSetLayer(RGFW_window* win, void* layer) { + objc_msgSend_void_id((id)win->src.view, sel_registerName("setLayer"), (id)layer); +} + +void* RGFW_cocoaGetLayer(void) { + return objc_msgSend_class((id)objc_getClass("CAMetalLayer"), (SEL)sel_registerName("layer")); +} + + +NSPasteboardType const NSPasteboardTypeURL = "public.url"; +NSPasteboardType const NSPasteboardTypeFileURL = "public.file-url"; + +RGFW_window* RGFW_createWindowPtr(const char* name, RGFW_rect rect, RGFW_windowFlags flags, RGFW_window* win) { + static u8 RGFW_loaded = 0; + + /* NOTE(EimaMei): Why does Apple hate good code? Like wtf, who thought of methods being a great idea??? + Imagine a universe, where MacOS had a proper system API (we would probably have like 20% better performance). + */ + si_func_to_SEL_with_name("NSObject", "windowShouldClose", (void*)RGFW_OnClose); + + /* NOTE(EimaMei): Fixes the 'Boop' sfx from constantly playing each time you click a key. Only a problem when running in the terminal. */ + si_func_to_SEL("NSWindow", acceptsFirstResponder); + si_func_to_SEL("NSWindow", performKeyEquivalent); + + // RR Create an autorelease pool + id pool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc")); + pool = objc_msgSend_id(pool, sel_registerName("init")); + + if (NSApp == NULL) { + NSApp = objc_msgSend_id((id)objc_getClass("NSApplication"), sel_registerName("sharedApplication")); + + ((void (*)(id, SEL, NSUInteger))objc_msgSend) + (NSApp, sel_registerName("setActivationPolicy:"), NSApplicationActivationPolicyRegular); + + #ifndef RGFW_NO_IOKIT + RGFW_osxInitIOKit(); #endif } + RGFW_window_basic_init(win, rect, flags); - void RGFW_window_cocoaSetLayer(RGFW_window* win, void* layer) { - objc_msgSend_void_id(win->src.view, sel_registerName("setLayer"), layer); + RGFW_window_setMouseDefault(win); + + NSRect windowRect; + windowRect.origin.x = win->r.x; + windowRect.origin.y = win->r.y; + windowRect.size.width = win->r.w; + windowRect.size.height = win->r.h; + + NSBackingStoreType macArgs = NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSBackingStoreBuffered | NSWindowStyleMaskTitled; + + if (!(flags & RGFW_windowNoResize)) + macArgs |= NSWindowStyleMaskResizable; + if (!(flags & RGFW_windowNoBorder)) + macArgs |= NSWindowStyleMaskTitled; + else + macArgs = NSWindowStyleMaskBorderless; + { + void* nsclass = objc_getClass("NSWindow"); + SEL func = sel_registerName("initWithContentRect:styleMask:backing:defer:"); + + win->src.window = ((id(*)(id, SEL, NSRect, NSWindowStyleMask, NSBackingStoreType, bool))objc_msgSend) + (NSAlloc(nsclass), func, windowRect, macArgs, macArgs, false); } - void* RGFW_cocoaGetLayer(void) { - return objc_msgSend_class(objc_getClass("CAMetalLayer"), sel_registerName("layer")); - } + id str = NSString_stringWithUTF8String(name); + objc_msgSend_void_id((id)win->src.window, sel_registerName("setTitle:"), str); - - NSPasteboardType const NSPasteboardTypeURL = "public.url"; - NSPasteboardType const NSPasteboardTypeFileURL = "public.file-url"; - - RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) { - static u8 RGFW_loaded = 0; - - /* NOTE(EimaMei): Why does Apple hate good code? Like wtf, who thought of methods being a great idea??? - Imagine a universe, where MacOS had a proper system API (we would probably have like 20% better performance). - */ - si_func_to_SEL_with_name("NSObject", "windowShouldClose", RGFW_OnClose); - - /* NOTE(EimaMei): Fixes the 'Boop' sfx from constantly playing each time you click a key. Only a problem when running in the terminal. */ - si_func_to_SEL("NSWindow", acceptsFirstResponder); - si_func_to_SEL("NSWindow", performKeyEquivalent); - - // RR Create an autorelease pool - id pool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc")); - pool = objc_msgSend_id(pool, sel_registerName("init")); - - if (NSApp == NULL) { - NSApp = objc_msgSend_id((id)objc_getClass("NSApplication"), sel_registerName("sharedApplication")); - - ((void (*)(id, SEL, NSUInteger))objc_msgSend) - (NSApp, sel_registerName("setActivationPolicy:"), NSApplicationActivationPolicyRegular); - } - - RGFW_window* win = RGFW_window_basic_init(rect, args); - - RGFW_window_setMouseDefault(win); - - NSRect windowRect; - windowRect.origin.x = win->r.x; - windowRect.origin.y = win->r.y; - windowRect.size.width = win->r.w; - windowRect.size.height = win->r.h; - - NSBackingStoreType macArgs = NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSBackingStoreBuffered | NSWindowStyleMaskTitled; - - if (!(args & RGFW_NO_RESIZE)) - macArgs |= NSWindowStyleMaskResizable; - if (!(args & RGFW_NO_BORDER)) - macArgs |= NSWindowStyleMaskTitled; - else - macArgs = NSWindowStyleMaskBorderless; - { - void* nsclass = objc_getClass("NSWindow"); - void* func = sel_registerName("initWithContentRect:styleMask:backing:defer:"); - - win->src.window = ((id(*)(id, SEL, NSRect, NSWindowStyleMask, NSBackingStoreType, bool))objc_msgSend) - (NSAlloc(nsclass), func, windowRect, macArgs, macArgs, false); - } - - NSString* str = NSString_stringWithUTF8String(name); - objc_msgSend_void_id(win->src.window, sel_registerName("setTitle:"), str); - -#ifdef RGFW_EGL - if ((args & RGFW_NO_INIT_API) == 0) + #ifdef RGFW_EGL + if ((flags & RGFW_windowNoInitAPI) == 0) RGFW_createOpenGLContext(win); -#endif + #endif -#ifdef RGFW_OPENGL - if ((args & RGFW_NO_INIT_API) == 0) { - void* attrs = RGFW_initFormatAttribs(args & RGFW_OPENGL_SOFTWARE); - void* format = NSOpenGLPixelFormat_initWithAttributes(attrs); + #ifdef RGFW_OPENGL + + if ((flags & RGFW_windowNoInitAPI) == 0) { + void* attrs = RGFW_initFormatAttribs(flags & RGFW_windowOpenglSoftware); + void* format = NSOpenGLPixelFormat_initWithAttributes((uint32_t*)attrs); if (format == NULL) { + #ifdef RGFW_DEBUG printf("Failed to load pixel format for OpenGL\n"); + #endif void* attrs = RGFW_initFormatAttribs(1); - format = NSOpenGLPixelFormat_initWithAttributes(attrs); + format = NSOpenGLPixelFormat_initWithAttributes((uint32_t*)attrs); + + #ifdef RGFW_DEBUG if (format == NULL) printf("and loading software rendering OpenGL failed\n"); else printf("Switching to software rendering\n"); + #endif } - - /* the pixel format can be passed directly to opengl context creation to create a context + + /* the pixel format can be passed directly to opengl context creation to create a context this is because the format also includes information about the opengl version (which may be a bad thing) */ - win->src.view = NSOpenGLView_initWithFrame((NSRect){{0, 0}, {win->r.w, win->r.h}}, format); + win->src.view = NSOpenGLView_initWithFrame((NSRect){{0, 0}, {win->r.w, win->r.h}}, (uint32_t*)format); objc_msgSend_void(win->src.view, sel_registerName("prepareOpenGL")); win->src.ctx = objc_msgSend_id(win->src.view, sel_registerName("openGLContext")); } else -#endif + #endif { NSRect contentRect = (NSRect){{0, 0}, {win->r.w, win->r.h}}; win->src.view = ((id(*)(id, SEL, NSRect))objc_msgSend) @@ -7339,920 +7942,992 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ contentRect); } - void* contentView = NSWindow_contentView(win->src.window); - objc_msgSend_void_bool(contentView, sel_registerName("setWantsLayer:"), true); + void* contentView = NSWindow_contentView((id)win->src.window); + objc_msgSend_void_bool(contentView, sel_registerName("setWantsLayer:"), true); - objc_msgSend_void_id(win->src.window, sel_registerName("setContentView:"), win->src.view); + objc_msgSend_void_id((id)win->src.window, sel_registerName("setContentView:"), win->src.view); -#ifdef RGFW_OPENGL - if ((args & RGFW_NO_INIT_API) == 0) + #ifdef RGFW_OPENGL + if ((flags & RGFW_windowNoInitAPI) == 0) objc_msgSend_void(win->src.ctx, sel_registerName("makeCurrentContext")); -#endif - if (args & RGFW_TRANSPARENT_WINDOW) { -#ifdef RGFW_OPENGL - if ((args & RGFW_NO_INIT_API) == 0) { - i32 opacity = 0; - #define NSOpenGLCPSurfaceOpacity 236 - NSOpenGLContext_setValues(win->src.ctx, &opacity, NSOpenGLCPSurfaceOpacity); - } -#endif + #endif - objc_msgSend_void_bool(win->src.window, sel_registerName("setOpaque:"), false); - - objc_msgSend_void_id(win->src.window, sel_registerName("setBackgroundColor:"), - NSColor_colorWithSRGB(0, 0, 0, 0)); - } - - win->src.display = CGMainDisplayID(); - CVDisplayLinkCreateWithCGDisplay(win->src.display, (CVDisplayLinkRef*)&win->src.displayLink); - CVDisplayLinkSetOutputCallback(win->src.displayLink, displayCallback, win); - CVDisplayLinkStart(win->src.displayLink); - - RGFW_init_buffer(win); - - #ifndef RGFW_NO_MONITOR - if (args & RGFW_SCALE_TO_MONITOR) - RGFW_window_scaleToMonitor(win); + if (flags & RGFW_windowTransparent) { + #ifdef RGFW_OPENGL + if ((flags & RGFW_windowNoInitAPI) == 0) { + i32 opacity = 0; + #define NSOpenGLCPSurfaceOpacity 236 + NSOpenGLContext_setValues((id)win->src.ctx, &opacity, NSOpenGLCPSurfaceOpacity); + } #endif - if (args & RGFW_CENTER) { - RGFW_area screenR = RGFW_getScreenSize(); - RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2)); - } + objc_msgSend_void_bool(win->src.window, sel_registerName("setOpaque:"), false); - if (args & RGFW_HIDE_MOUSE) - RGFW_window_showMouse(win, 0); - - if (args & RGFW_COCOA_MOVE_TO_RESOURCE_DIR) - NSMoveToResourceDir(); - - Class delegateClass = objc_allocateClassPair(objc_getClass("NSObject"), "WindowDelegate", 0); - - class_addIvar( - delegateClass, "RGFW_window", - sizeof(RGFW_window*), rint(log2(sizeof(RGFW_window*))), - "L" - ); - - class_addMethod(delegateClass, sel_registerName("windowWillResize:toSize:"), (IMP) RGFW__osxWindowResize, "{NSSize=ff}@:{NSSize=ff}"); - class_addMethod(delegateClass, sel_registerName("updateLayer:"), (IMP) RGFW__osxUpdateLayer, ""); - class_addMethod(delegateClass, sel_registerName("windowWillMove:"), (IMP) RGFW__osxWindowMove, ""); - class_addMethod(delegateClass, sel_registerName("windowDidMove:"), (IMP) RGFW__osxWindowMove, ""); - class_addMethod(delegateClass, sel_registerName("draggingEntered:"), (IMP)draggingEntered, "l@:@"); - class_addMethod(delegateClass, sel_registerName("draggingUpdated:"), (IMP)draggingUpdated, "l@:@"); - class_addMethod(delegateClass, sel_registerName("draggingExited:"), (IMP)RGFW__osxDraggingEnded, "v@:@"); - class_addMethod(delegateClass, sel_registerName("draggingEnded:"), (IMP)RGFW__osxDraggingEnded, "v@:@"); - class_addMethod(delegateClass, sel_registerName("prepareForDragOperation:"), (IMP)prepareForDragOperation, "B@:@"); - class_addMethod(delegateClass, sel_registerName("performDragOperation:"), (IMP)performDragOperation, "B@:@"); - - id delegate = objc_msgSend_id(NSAlloc(delegateClass), sel_registerName("init")); - - object_setInstanceVariable(delegate, "RGFW_window", win); - - objc_msgSend_void_id(win->src.window, sel_registerName("setDelegate:"), delegate); - - if (args & RGFW_ALLOW_DND) { - win->_winArgs |= RGFW_ALLOW_DND; - - NSPasteboardType types[] = {NSPasteboardTypeURL, NSPasteboardTypeFileURL, NSPasteboardTypeString}; - NSregisterForDraggedTypes(win->src.window, types, 3); - } - - // Show the window - objc_msgSend_void_bool(NSApp, sel_registerName("activateIgnoringOtherApps:"), true); - ((id(*)(id, SEL, SEL))objc_msgSend)(win->src.window, sel_registerName("makeKeyAndOrderFront:"), NULL); - objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), true); - - if (!RGFW_loaded) { - objc_msgSend_void(win->src.window, sel_registerName("makeMainWindow")); - - RGFW_loaded = 1; - } - - objc_msgSend_void(win->src.window, sel_registerName("makeKeyWindow")); - - objc_msgSend_void(NSApp, sel_registerName("finishLaunching")); - - if (RGFW_root == NULL) - RGFW_root = win; - - NSRetain(win->src.window); - NSRetain(NSApp); - - return win; + objc_msgSend_void_id((id)win->src.window, sel_registerName("setBackgroundColor:"), + NSColor_colorWithSRGB(0, 0, 0, 0)); } - void RGFW_window_setBorder(RGFW_window* win, u8 border) { - NSBackingStoreType storeType = NSWindowStyleMaskBorderless; - if (!border) { - storeType = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable; - } - if (!(win->_winArgs & RGFW_NO_RESIZE)) { - storeType |= NSWindowStyleMaskResizable; - } - - ((void (*)(id, SEL, NSBackingStoreType))objc_msgSend)(win->src.window, sel_registerName("setStyleMask:"), storeType); + RGFW_init_buffer(win); - objc_msgSend_void_bool(win->src.window, sel_registerName("setHasShadow:"), border); + #ifndef RGFW_NO_MONITOR + if (flags & RGFW_windowScaleToMonitor) + RGFW_window_scaleToMonitor(win); + #endif + + if (flags & RGFW_windowCenter) { + RGFW_area screenR = RGFW_getScreenSize(); + RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2)); } - RGFW_area RGFW_getScreenSize(void) { - static CGDirectDisplayID display = 0; + if (flags & RGFW_windowHideMouse) + RGFW_window_showMouse(win, 0); - if (display == 0) - display = CGMainDisplayID(); + if (flags & RGFW_windowCocoaCHDirToRes) + NSMoveToResourceDir(); - return RGFW_AREA(CGDisplayPixelsWide(display), CGDisplayPixelsHigh(display)); + Class delegateClass = objc_allocateClassPair(objc_getClass("NSObject"), "WindowDelegate", 0); + + class_addIvar( + delegateClass, "RGFW_window", + sizeof(RGFW_window*), rint(log2(sizeof(RGFW_window*))), + "L" + ); + + class_addMethod(delegateClass, sel_registerName("windowWillResize:toSize:"), (IMP) RGFW__osxWindowResize, "{NSSize=ff}@:{NSSize=ff}"); + class_addMethod(delegateClass, sel_registerName("updateLayer:"), (IMP) RGFW__osxUpdateLayer, ""); + class_addMethod(delegateClass, sel_registerName("windowWillMove:"), (IMP) RGFW__osxWindowMove, ""); + class_addMethod(delegateClass, sel_registerName("windowDidMove:"), (IMP) RGFW__osxWindowMove, ""); + class_addMethod(delegateClass, sel_registerName("draggingEntered:"), (IMP)draggingEntered, "l@:@"); + class_addMethod(delegateClass, sel_registerName("draggingUpdated:"), (IMP)draggingUpdated, "l@:@"); + class_addMethod(delegateClass, sel_registerName("draggingExited:"), (IMP)RGFW__osxDraggingEnded, "v@:@"); + class_addMethod(delegateClass, sel_registerName("draggingEnded:"), (IMP)RGFW__osxDraggingEnded, "v@:@"); + class_addMethod(delegateClass, sel_registerName("prepareForDragOperation:"), (IMP)prepareForDragOperation, "B@:@"); + class_addMethod(delegateClass, sel_registerName("performDragOperation:"), (IMP)performDragOperation, "B@:@"); + + id delegate = objc_msgSend_id(NSAlloc(delegateClass), sel_registerName("init")); + + object_setInstanceVariable(delegate, "RGFW_window", win); + + objc_msgSend_void_id((id)win->src.window, sel_registerName("setDelegate:"), delegate); + + if (flags & RGFW_windowAllowDND) { + win->_flags |= RGFW_windowAllowDND; + + NSPasteboardType types[] = {NSPasteboardTypeURL, NSPasteboardTypeFileURL, NSPasteboardTypeString}; + NSregisterForDraggedTypes((id)win->src.window, types, 3); } - RGFW_point RGFW_getGlobalMousePoint(void) { - assert(RGFW_root != NULL); + // Show the window + objc_msgSend_void_bool(NSApp, sel_registerName("activateIgnoringOtherApps:"), true); + ((id(*)(id, SEL, SEL))objc_msgSend)((id)win->src.window, sel_registerName("makeKeyAndOrderFront:"), (SEL)NULL); + objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), true); - CGEventRef e = CGEventCreate(NULL); - CGPoint point = CGEventGetLocation(e); - CFRelease(e); + if (!RGFW_loaded) { + objc_msgSend_void(win->src.window, sel_registerName("makeMainWindow")); - return RGFW_POINT((u32) point.x, (u32) point.y); /*!< the point is loaded during event checks */ + RGFW_loaded = 1; } - RGFW_point RGFW_window_getMousePoint(RGFW_window* win) { - NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(win->src.window, sel_registerName("mouseLocationOutsideOfEventStream")); + objc_msgSend_void(win->src.window, sel_registerName("makeKeyWindow")); - return RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y)); + objc_msgSend_void(NSApp, sel_registerName("finishLaunching")); + + NSRetain(win->src.window); + NSRetain(NSApp); + + #ifdef RGFW_DEBUG + printf("RGFW INFO: a window with a rect of {%i, %i, %i, %i} \n", win->r.x, win->r.y, win->r.w, win->r.h); + #endif + return win; +} + +void RGFW_window_setBorder(RGFW_window* win, u8 border) { + NSBackingStoreType storeType = NSWindowStyleMaskBorderless; + if (!border) { + storeType = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable; + } + if (!(win->_flags & RGFW_windowNoResize)) { + storeType |= NSWindowStyleMaskResizable; } - u32 RGFW_keysPressed[10]; /*10 keys at a time*/ - typedef NS_ENUM(u32, NSEventType) { /* various types of events */ - NSEventTypeLeftMouseDown = 1, - NSEventTypeLeftMouseUp = 2, - NSEventTypeRightMouseDown = 3, - NSEventTypeRightMouseUp = 4, - NSEventTypeMouseMoved = 5, - NSEventTypeLeftMouseDragged = 6, - NSEventTypeRightMouseDragged = 7, - NSEventTypeMouseEntered = 8, - NSEventTypeMouseExited = 9, - NSEventTypeKeyDown = 10, - NSEventTypeKeyUp = 11, - NSEventTypeFlagsChanged = 12, - NSEventTypeAppKitDefined = 13, - NSEventTypeSystemDefined = 14, - NSEventTypeApplicationDefined = 15, - NSEventTypePeriodic = 16, - NSEventTypeCursorUpdate = 17, - NSEventTypeScrollWheel = 22, - NSEventTypeTabletPoint = 23, - NSEventTypeTabletProximity = 24, - NSEventTypeOtherMouseDown = 25, - NSEventTypeOtherMouseUp = 26, - NSEventTypeOtherMouseDragged = 27, - /* The following event types are available on some hardware on 10.5.2 and later */ - NSEventTypeGesture API_AVAILABLE(macos(10.5)) = 29, - NSEventTypeMagnify API_AVAILABLE(macos(10.5)) = 30, - NSEventTypeSwipe API_AVAILABLE(macos(10.5)) = 31, - NSEventTypeRotate API_AVAILABLE(macos(10.5)) = 18, - NSEventTypeBeginGesture API_AVAILABLE(macos(10.5)) = 19, - NSEventTypeEndGesture API_AVAILABLE(macos(10.5)) = 20, + ((void (*)(id, SEL, NSBackingStoreType))objc_msgSend)((id)win->src.window, sel_registerName("setStyleMask:"), storeType); - NSEventTypeSmartMagnify API_AVAILABLE(macos(10.8)) = 32, - NSEventTypeQuickLook API_AVAILABLE(macos(10.8)) = 33, + objc_msgSend_void_bool(win->src.window, sel_registerName("setHasShadow:"), border); +} - NSEventTypePressure API_AVAILABLE(macos(10.10.3)) = 34, - NSEventTypeDirectTouch API_AVAILABLE(macos(10.10)) = 37, +RGFW_area RGFW_getScreenSize(void) { + static CGDirectDisplayID display = 0; - NSEventTypeChangeMode API_AVAILABLE(macos(10.15)) = 38, - }; + if (display == 0) + display = CGMainDisplayID(); - typedef NS_ENUM(unsigned long long, NSEventMask) { /* masks for the types of events */ - NSEventMaskLeftMouseDown = 1ULL << NSEventTypeLeftMouseDown, - NSEventMaskLeftMouseUp = 1ULL << NSEventTypeLeftMouseUp, - NSEventMaskRightMouseDown = 1ULL << NSEventTypeRightMouseDown, - NSEventMaskRightMouseUp = 1ULL << NSEventTypeRightMouseUp, - NSEventMaskMouseMoved = 1ULL << NSEventTypeMouseMoved, - NSEventMaskLeftMouseDragged = 1ULL << NSEventTypeLeftMouseDragged, - NSEventMaskRightMouseDragged = 1ULL << NSEventTypeRightMouseDragged, - NSEventMaskMouseEntered = 1ULL << NSEventTypeMouseEntered, - NSEventMaskMouseExited = 1ULL << NSEventTypeMouseExited, - NSEventMaskKeyDown = 1ULL << NSEventTypeKeyDown, - NSEventMaskKeyUp = 1ULL << NSEventTypeKeyUp, - NSEventMaskFlagsChanged = 1ULL << NSEventTypeFlagsChanged, - NSEventMaskAppKitDefined = 1ULL << NSEventTypeAppKitDefined, - NSEventMaskSystemDefined = 1ULL << NSEventTypeSystemDefined, - NSEventMaskApplicationDefined = 1ULL << NSEventTypeApplicationDefined, - NSEventMaskPeriodic = 1ULL << NSEventTypePeriodic, - NSEventMaskCursorUpdate = 1ULL << NSEventTypeCursorUpdate, - NSEventMaskScrollWheel = 1ULL << NSEventTypeScrollWheel, - NSEventMaskTabletPoint = 1ULL << NSEventTypeTabletPoint, - NSEventMaskTabletProximity = 1ULL << NSEventTypeTabletProximity, - NSEventMaskOtherMouseDown = 1ULL << NSEventTypeOtherMouseDown, - NSEventMaskOtherMouseUp = 1ULL << NSEventTypeOtherMouseUp, - NSEventMaskOtherMouseDragged = 1ULL << NSEventTypeOtherMouseDragged, - /* The following event masks are available on some hardware on 10.5.2 and later */ - NSEventMaskGesture API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeGesture, - NSEventMaskMagnify API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeMagnify, - NSEventMaskSwipe API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeSwipe, - NSEventMaskRotate API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeRotate, - NSEventMaskBeginGesture API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeBeginGesture, - NSEventMaskEndGesture API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeEndGesture, + return RGFW_AREA(CGDisplayPixelsWide(display), CGDisplayPixelsHigh(display)); +} - /* Note: You can only use these event masks on 64 bit. In other words, you cannot setup a local, nor global, event monitor for these event types on 32 bit. Also, you cannot search the event queue for them (nextEventMatchingMask:...) on 32 bit. - */ - NSEventMaskSmartMagnify API_AVAILABLE(macos(10.8)) = 1ULL << NSEventTypeSmartMagnify, - NSEventMaskPressure API_AVAILABLE(macos(10.10.3)) = 1ULL << NSEventTypePressure, - NSEventMaskDirectTouch API_AVAILABLE(macos(10.12.2)) = 1ULL << NSEventTypeDirectTouch, +RGFW_point RGFW_getGlobalMousePoint(void) { + RGFW_ASSERT(RGFW_root != NULL); - NSEventMaskChangeMode API_AVAILABLE(macos(10.15)) = 1ULL << NSEventTypeChangeMode, + CGEventRef e = CGEventCreate(NULL); + CGPoint point = CGEventGetLocation(e); + CFRelease(e); - NSEventMaskAny = ULONG_MAX, + return RGFW_POINT((u32) point.x, (u32) point.y); /*!< the point is loaded during event checks */ +} - }; +RGFW_point RGFW_window_getMousePoint(RGFW_window* win) { + NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)((id)win->src.window, sel_registerName("mouseLocationOutsideOfEventStream")); - typedef enum NSEventModifierFlags { - NSEventModifierFlagCapsLock = 1 << 16, - NSEventModifierFlagShift = 1 << 17, - NSEventModifierFlagControl = 1 << 18, - NSEventModifierFlagOption = 1 << 19, - NSEventModifierFlagCommand = 1 << 20, - NSEventModifierFlagNumericPad = 1 << 21 - } NSEventModifierFlags; + return RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y)); +} - void RGFW_stopCheckEvents(void) { - id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc")); - eventPool = objc_msgSend_id(eventPool, sel_registerName("init")); +u32 RGFW_keysPressed[10]; /*10 keys at a time*/ +typedef RGFW_ENUM(u32, NSEventType) { /* various types of events */ + NSEventTypeLeftMouseDown = 1, + NSEventTypeLeftMouseUp = 2, + NSEventTypeRightMouseDown = 3, + NSEventTypeRightMouseUp = 4, + NSEventTypeMouseMoved = 5, + NSEventTypeLeftMouseDragged = 6, + NSEventTypeRightMouseDragged = 7, + NSEventTypeMouseEntered = 8, + NSEventTypeMouseExited = 9, + NSEventTypeKeyDown = 10, + NSEventTypeKeyUp = 11, + NSEventTypeFlagsChanged = 12, + NSEventTypeAppKitDefined = 13, + NSEventTypeSystemDefined = 14, + NSEventTypeApplicationDefined = 15, + NSEventTypePeriodic = 16, + NSEventTypeCursorUpdate = 17, + NSEventTypeScrollWheel = 22, + NSEventTypeTabletPoint = 23, + NSEventTypeTabletProximity = 24, + NSEventTypeOtherMouseDown = 25, + NSEventTypeOtherMouseUp = 26, + NSEventTypeOtherMouseDragged = 27, + /* The following event types are available on some hardware on 10.5.2 and later */ + NSEventTypeGesture API_AVAILABLE(macos(10.5)) = 29, + NSEventTypeMagnify API_AVAILABLE(macos(10.5)) = 30, + NSEventTypeSwipe API_AVAILABLE(macos(10.5)) = 31, + NSEventTypeRotate API_AVAILABLE(macos(10.5)) = 18, + NSEventTypeBeginGesture API_AVAILABLE(macos(10.5)) = 19, + NSEventTypeEndGesture API_AVAILABLE(macos(10.5)) = 20, - NSEvent* e = (NSEvent*) ((id(*)(id, SEL, NSEventType, NSPoint, NSEventModifierFlags, void*, NSInteger, void**, short, NSInteger, NSInteger))objc_msgSend) - (NSApp, sel_registerName("otherEventWithType:location:modifierFlags:timestamp:windowNumber:context:subtype:data1:data2:"), - NSEventTypeApplicationDefined, (NSPoint){0, 0}, 0, 0, 0, NULL, 0, 0, 0); + NSEventTypeSmartMagnify API_AVAILABLE(macos(10.8)) = 32, + NSEventTypeQuickLook API_AVAILABLE(macos(10.8)) = 33, + NSEventTypePressure API_AVAILABLE(macos(10.10.3)) = 34, + NSEventTypeDirectTouch API_AVAILABLE(macos(10.10)) = 37, + + NSEventTypeChangeMode API_AVAILABLE(macos(10.15)) = 38, +}; + +typedef RGFW_ENUM(unsigned long long, NSEventMask) { /* masks for the types of events */ + NSEventMaskLeftMouseDown = 1ULL << NSEventTypeLeftMouseDown, + NSEventMaskLeftMouseUp = 1ULL << NSEventTypeLeftMouseUp, + NSEventMaskRightMouseDown = 1ULL << NSEventTypeRightMouseDown, + NSEventMaskRightMouseUp = 1ULL << NSEventTypeRightMouseUp, + NSEventMaskMouseMoved = 1ULL << NSEventTypeMouseMoved, + NSEventMaskLeftMouseDragged = 1ULL << NSEventTypeLeftMouseDragged, + NSEventMaskRightMouseDragged = 1ULL << NSEventTypeRightMouseDragged, + NSEventMaskMouseEntered = 1ULL << NSEventTypeMouseEntered, + NSEventMaskMouseExited = 1ULL << NSEventTypeMouseExited, + NSEventMaskKeyDown = 1ULL << NSEventTypeKeyDown, + NSEventMaskKeyUp = 1ULL << NSEventTypeKeyUp, + NSEventMaskFlagsChanged = 1ULL << NSEventTypeFlagsChanged, + NSEventMaskAppKitDefined = 1ULL << NSEventTypeAppKitDefined, + NSEventMaskSystemDefined = 1ULL << NSEventTypeSystemDefined, + NSEventMaskApplicationDefined = 1ULL << NSEventTypeApplicationDefined, + NSEventMaskPeriodic = 1ULL << NSEventTypePeriodic, + NSEventMaskCursorUpdate = 1ULL << NSEventTypeCursorUpdate, + NSEventMaskScrollWheel = 1ULL << NSEventTypeScrollWheel, + NSEventMaskTabletPoint = 1ULL << NSEventTypeTabletPoint, + NSEventMaskTabletProximity = 1ULL << NSEventTypeTabletProximity, + NSEventMaskOtherMouseDown = 1ULL << NSEventTypeOtherMouseDown, + NSEventMaskOtherMouseUp = 1ULL << NSEventTypeOtherMouseUp, + NSEventMaskOtherMouseDragged = 1ULL << NSEventTypeOtherMouseDragged, + /* The following event masks are available on some hardware on 10.5.2 and later */ + NSEventMaskGesture API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeGesture, + NSEventMaskMagnify API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeMagnify, + NSEventMaskSwipe API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeSwipe, + NSEventMaskRotate API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeRotate, + NSEventMaskBeginGesture API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeBeginGesture, + NSEventMaskEndGesture API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeEndGesture, + + /* Note: You can only use these event masks on 64 bit. In other words, you cannot setup a local, nor global, event monitor for these event types on 32 bit. Also, you cannot search the event queue for them (nextEventMatchingMask:...) on 32 bit. + */ + NSEventMaskSmartMagnify API_AVAILABLE(macos(10.8)) = 1ULL << NSEventTypeSmartMagnify, + NSEventMaskPressure API_AVAILABLE(macos(10.10.3)) = 1ULL << NSEventTypePressure, + NSEventMaskDirectTouch API_AVAILABLE(macos(10.12.2)) = 1ULL << NSEventTypeDirectTouch, + + NSEventMaskChangeMode API_AVAILABLE(macos(10.15)) = 1ULL << NSEventTypeChangeMode, + + NSEventMaskAny = ULONG_MAX, + +}; + +typedef enum NSEventModifierFlags { + NSEventModifierFlagCapsLock = 1 << 16, + NSEventModifierFlagShift = 1 << 17, + NSEventModifierFlagControl = 1 << 18, + NSEventModifierFlagOption = 1 << 19, + NSEventModifierFlagCommand = 1 << 20, + NSEventModifierFlagNumericPad = 1 << 21 +} NSEventModifierFlags; + +void RGFW_stopCheckEvents(void) { + id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc")); + eventPool = objc_msgSend_id(eventPool, sel_registerName("init")); + + id e = (id) ((id(*)(id, SEL, NSEventType, NSPoint, NSEventModifierFlags, void*, NSInteger, void**, short, NSInteger, NSInteger))objc_msgSend) + (NSApp, sel_registerName("otherEventWithType:location:modifierFlags:timestamp:windowNumber:context:subtype:data1:data2:"), + NSEventTypeApplicationDefined, (NSPoint){0, 0}, (NSEventModifierFlags)0, NULL, (NSInteger)0, NULL, 0, 0, 0); + + ((void (*)(id, SEL, id, bool))objc_msgSend) + (NSApp, sel_registerName("postEvent:atStart:"), e, 1); + + objc_msgSend_bool_void(eventPool, sel_registerName("drain")); +} + +void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) { + RGFW_UNUSED(win); + + id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc")); + eventPool = objc_msgSend_id(eventPool, sel_registerName("init")); + + void* date = (void*) ((id(*)(Class, SEL, double))objc_msgSend) + (objc_getClass("NSDate"), sel_registerName("dateWithTimeIntervalSinceNow:"), waitMS); + + id e = (id) ((id(*)(id, SEL, NSEventMask, void*, id, bool))objc_msgSend) + (NSApp, sel_registerName("nextEventMatchingMask:untilDate:inMode:dequeue:"), + ULONG_MAX, date, NSString_stringWithUTF8String("kCFRunLoopDefaultMode"), true); + + + if (e) { ((void (*)(id, SEL, id, bool))objc_msgSend) (NSApp, sel_registerName("postEvent:atStart:"), e, 1); - - objc_msgSend_bool_void(eventPool, sel_registerName("drain")); } - void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) { - RGFW_UNUSED(win); - - id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc")); - eventPool = objc_msgSend_id(eventPool, sel_registerName("init")); + objc_msgSend_bool_void(eventPool, sel_registerName("drain")); +} - void* date = (void*) ((id(*)(Class, SEL, double))objc_msgSend) - (objc_getClass("NSDate"), sel_registerName("dateWithTimeIntervalSinceNow:"), waitMS); +RGFW_event* RGFW_window_checkEvent(RGFW_window* win) { + RGFW_ASSERT(win != NULL); - NSEvent* e = (NSEvent*) ((id(*)(id, SEL, NSEventMask, void*, NSString*, bool))objc_msgSend) - (NSApp, sel_registerName("nextEventMatchingMask:untilDate:inMode:dequeue:"), - ULONG_MAX, date, NSString_stringWithUTF8String("kCFRunLoopDefaultMode"), true); + if (win->event.type == RGFW_quit) + return NULL; - - if (e) { - objc_msgSend_void_id(NSApp, sel_registerName("sendEvent:"), e); - } - - objc_msgSend_bool_void(eventPool, sel_registerName("drain")); - } - - RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) { - assert(win != NULL); - - if (win->event.type == RGFW_quit) - return NULL; - - if ((win->event.type == RGFW_dnd || win->event.type == RGFW_dnd_init) && win->src.dndPassed == 0) { - win->src.dndPassed = 1; - return &win->event; - } - - id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc")); - eventPool = objc_msgSend_id(eventPool, sel_registerName("init")); - - static void* eventFunc = NULL; - if (eventFunc == NULL) - eventFunc = sel_registerName("nextEventMatchingMask:untilDate:inMode:dequeue:"); - - if ((win->event.type == RGFW_windowMoved || win->event.type == RGFW_windowResized || win->event.type == RGFW_windowRefresh) && win->event.keyCode != 120) { - win->event.keyCode = 120; - objc_msgSend_bool_void(eventPool, sel_registerName("drain")); - return &win->event; - } - - void* date = NULL; - - NSEvent* e = (NSEvent*) ((id(*)(id, SEL, NSEventMask, void*, NSString*, bool))objc_msgSend) - (NSApp, eventFunc, ULONG_MAX, date, NSString_stringWithUTF8String("kCFRunLoopDefaultMode"), true); - - if (e == NULL) { - objc_msgSend_bool_void(eventPool, sel_registerName("drain")); - return NULL; - } - - if (objc_msgSend_id(e, sel_registerName("window")) != win->src.window) { - ((void (*)(id, SEL, id, bool))objc_msgSend) - (NSApp, sel_registerName("postEvent:atStart:"), e, 0); - - objc_msgSend_bool_void(eventPool, sel_registerName("drain")); - return NULL; - } - - if (win->event.droppedFilesCount) { - u32 i; - for (i = 0; i < win->event.droppedFilesCount; i++) - win->event.droppedFiles[i][0] = '\0'; - } - - win->event.droppedFilesCount = 0; - win->event.type = 0; - - switch (objc_msgSend_uint(e, sel_registerName("type"))) { - case NSEventTypeMouseEntered: { - win->event.type = RGFW_mouseEnter; - NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(e, sel_registerName("locationInWindow")); - - win->event.point = RGFW_POINT((i32) p.x, (i32) (win->r.h - p.y)); - RGFW_mouseNotifyCallBack(win, win->event.point, 1); - break; - } - - case NSEventTypeMouseExited: - win->event.type = RGFW_mouseLeave; - RGFW_mouseNotifyCallBack(win, win->event.point, 0); - break; - - case NSEventTypeKeyDown: { - u32 key = (u16) objc_msgSend_uint(e, sel_registerName("keyCode")); - win->event.keyCode = RGFW_apiKeyCodeToRGFW(key); - RGFW_keyboard[win->event.keyCode].prev = RGFW_keyboard[win->event.keyCode].current; - - win->event.type = RGFW_keyPressed; - char* str = (char*)(const char*) NSString_to_char(objc_msgSend_id(e, sel_registerName("characters"))); - strncpy(win->event.keyName, str, 16); - win->event.repeat = RGFW_isPressed(win, win->event.keyCode); - RGFW_keyboard[win->event.keyCode].current = 1; - - RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 1); - break; - } - - case NSEventTypeKeyUp: { - u32 key = (u16) objc_msgSend_uint(e, sel_registerName("keyCode")); - win->event.keyCode = RGFW_apiKeyCodeToRGFW(key);; - - RGFW_keyboard[win->event.keyCode].prev = RGFW_keyboard[win->event.keyCode].current; - - win->event.type = RGFW_keyReleased; - char* str = (char*)(const char*) NSString_to_char(objc_msgSend_id(e, sel_registerName("characters"))); - strncpy(win->event.keyName, str, 16); - - RGFW_keyboard[win->event.keyCode].current = 0; - RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 0); - break; - } - - case NSEventTypeFlagsChanged: { - u32 flags = objc_msgSend_uint(e, sel_registerName("modifierFlags")); - RGFW_updateLockState(win, ((u32)(flags & NSEventModifierFlagCapsLock) % 255), ((flags & NSEventModifierFlagNumericPad) % 255)); - - u8 i; - for (i = 0; i < 9; i++) - RGFW_keyboard[i + RGFW_CapsLock].prev = 0; - - for (i = 0; i < 5; i++) { - u32 shift = (1 << (i + 16)); - u32 key = i + RGFW_CapsLock; - - if ((flags & shift) && !RGFW_wasPressed(win, key)) { - RGFW_keyboard[key].current = 1; - - if (key != RGFW_CapsLock) - RGFW_keyboard[key+ 4].current = 1; - - win->event.type = RGFW_keyPressed; - win->event.keyCode = key; - break; - } - - if (!(flags & shift) && RGFW_wasPressed(win, key)) { - RGFW_keyboard[key].current = 0; - - if (key != RGFW_CapsLock) - RGFW_keyboard[key + 4].current = 0; - - win->event.type = RGFW_keyReleased; - win->event.keyCode = key; - break; - } - } - - RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, win->event.type == RGFW_keyPressed); - - break; - } - case NSEventTypeLeftMouseDragged: - case NSEventTypeOtherMouseDragged: - case NSEventTypeRightMouseDragged: - case NSEventTypeMouseMoved: - win->event.type = RGFW_mousePosChanged; - NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(e, sel_registerName("locationInWindow")); - win->event.point = RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y)); - - if ((win->_winArgs & RGFW_HOLD_MOUSE)) { - p.x = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaX")); - p.y = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaY")); - - win->event.point = RGFW_POINT((i32)p.x, (i32)p.y); - } - - RGFW_mousePosCallback(win, win->event.point); - break; - - case NSEventTypeLeftMouseDown: - win->event.button = RGFW_mouseLeft; - win->event.type = RGFW_mouseButtonPressed; - RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; - RGFW_mouseButtons[win->event.button].current = 1; - RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); - break; - - case NSEventTypeOtherMouseDown: - win->event.button = RGFW_mouseMiddle; - win->event.type = RGFW_mouseButtonPressed; - RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; - RGFW_mouseButtons[win->event.button].current = 1; - RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); - break; - - case NSEventTypeRightMouseDown: - win->event.button = RGFW_mouseRight; - win->event.type = RGFW_mouseButtonPressed; - RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; - RGFW_mouseButtons[win->event.button].current = 1; - RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); - break; - - case NSEventTypeLeftMouseUp: - win->event.button = RGFW_mouseLeft; - win->event.type = RGFW_mouseButtonReleased; - RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; - RGFW_mouseButtons[win->event.button].current = 0; - RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); - break; - - case NSEventTypeOtherMouseUp: - win->event.button = RGFW_mouseMiddle; - RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; - RGFW_mouseButtons[win->event.button].current = 0; - win->event.type = RGFW_mouseButtonReleased; - RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); - break; - - case NSEventTypeRightMouseUp: - win->event.button = RGFW_mouseRight; - RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; - RGFW_mouseButtons[win->event.button].current = 0; - win->event.type = RGFW_mouseButtonReleased; - RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); - break; - - case NSEventTypeScrollWheel: { - double deltaY = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaY")); - - if (deltaY > 0) { - win->event.button = RGFW_mouseScrollUp; - } - else if (deltaY < 0) { - win->event.button = RGFW_mouseScrollDown; - } - - RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; - RGFW_mouseButtons[win->event.button].current = 1; - - win->event.scroll = deltaY; - - win->event.type = RGFW_mouseButtonPressed; - RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); - break; - } - - default: - break; - } - - objc_msgSend_void_id(NSApp, sel_registerName("sendEvent:"), e); + if ((win->event.type == RGFW_DND || win->event.type == RGFW_DNDInit) && win->src.dndPassed == 0) { + win->src.dndPassed = 1; ((void(*)(id, SEL))objc_msgSend)(NSApp, sel_registerName("updateWindows")); - - objc_msgSend_bool_void(eventPool, sel_registerName("drain")); return &win->event; } + #ifndef RGFW_NO_IOKIT + if (RGFW_gamepadEventQueueCount && win == RGFW_root) { + static u8 index = 0; - void RGFW_window_move(RGFW_window* win, RGFW_point v) { - assert(win != NULL); + /* check queued events */ + RGFW_gamepadEventQueueCount--; - win->r.x = v.x; - win->r.y = v.y; - ((void(*)(id, SEL, NSRect, bool, bool))objc_msgSend) - (win->src.window, sel_registerName("setFrame:display:animate:"), (NSRect){{win->r.x, win->r.y}, {win->r.w, win->r.h}}, true, true); - } + RGFW_event ev = RGFW_gamepadEventQueue[index]; + win->event.type = ev.type; + win->event.gamepad = ev.gamepad; + win->event.button = ev.button; + win->event.whichAxis = ev.whichAxis; + for (size_t i = 0; i < 4; i++) + win->event.axis[i] = ev.axis[i]; - void RGFW_window_resize(RGFW_window* win, RGFW_area a) { - assert(win != NULL); + if (RGFW_gamepadEventQueueCount) index++; + else index = 0; - win->r.w = a.w; - win->r.h = a.h; - ((void(*)(id, SEL, NSRect, bool, bool))objc_msgSend) - (win->src.window, sel_registerName("setFrame:display:animate:"), (NSRect){{win->r.x, win->r.y}, {win->r.w, win->r.h}}, true, true); - } - - void RGFW_window_minimize(RGFW_window* win) { - assert(win != NULL); - - objc_msgSend_void_SEL(win->src.window, sel_registerName("performMiniaturize:"), NULL); - } - - void RGFW_window_restore(RGFW_window* win) { - assert(win != NULL); - - objc_msgSend_void_SEL(win->src.window, sel_registerName("deminiaturize:"), NULL); - } - - void RGFW_window_setName(RGFW_window* win, char* name) { - assert(win != NULL); - - NSString* str = NSString_stringWithUTF8String(name); - objc_msgSend_void_id(win->src.window, sel_registerName("setTitle:"), str); - } - - #ifndef RGFW_NO_PASSTHROUGH - void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) { - objc_msgSend_void_bool(win->src.window, sel_registerName("setIgnoresMouseEvents:"), passthrough); + ((void(*)(id, SEL))objc_msgSend)(NSApp, sel_registerName("updateWindows")); + return &win->event; } #endif - void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) { - if (a.w == 0 && a.h == 0) - return; + id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc")); + eventPool = objc_msgSend_id(eventPool, sel_registerName("init")); - ((void (*)(id, SEL, NSSize))objc_msgSend) - (win->src.window, sel_registerName("setMinSize:"), (NSSize){a.w, a.h}); + static SEL eventFunc = (SEL)NULL; + if (eventFunc == NULL) + eventFunc = sel_registerName("nextEventMatchingMask:untilDate:inMode:dequeue:"); + + if ((win->event.type == RGFW_windowMoved || win->event.type == RGFW_windowResized || win->event.type == RGFW_windowRefresh) && win->event.key != 120) { + win->event.key = 120; + objc_msgSend_bool_void(eventPool, sel_registerName("drain")); + ((void(*)(id, SEL))objc_msgSend)(NSApp, sel_registerName("updateWindows")); + return &win->event; } - void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) { - if (a.w == 0 && a.h == 0) - return; + void* date = NULL; - ((void (*)(id, SEL, NSSize))objc_msgSend) - (win->src.window, sel_registerName("setMaxSize:"), (NSSize){a.w, a.h}); + id e = (id) ((id(*)(id, SEL, NSEventMask, void*, id, bool))objc_msgSend) + (NSApp, eventFunc, ULONG_MAX, date, NSString_stringWithUTF8String("kCFRunLoopDefaultMode"), true); + + if (e == NULL) { + objc_msgSend_bool_void(eventPool, sel_registerName("drain")); + objc_msgSend_void_id(NSApp, sel_registerName("sendEvent:"), e); + ((void(*)(id, SEL))objc_msgSend)(NSApp, sel_registerName("updateWindows")); + return NULL; } - void RGFW_window_setIcon(RGFW_window* win, u8* data, RGFW_area area, i32 channels) { - assert(win != NULL); + if (objc_msgSend_id(e, sel_registerName("window")) != win->src.window) { + ((void (*)(id, SEL, id, bool))objc_msgSend) + (NSApp, sel_registerName("postEvent:atStart:"), e, 0); - /* code by EimaMei */ - // Make a bitmap representation, then copy the loaded image into it. - void* representation = NSBitmapImageRep_initWithBitmapData(NULL, area.w, area.h, 8, channels, (channels == 4), false, "NSCalibratedRGBColorSpace", 1 << 1, area.w * channels, 8 * channels); - memcpy(NSBitmapImageRep_bitmapData(representation), data, area.w * area.h * channels); - - // Add ze representation. - void* dock_image = NSImage_initWithSize((NSSize){area.w, area.h}); - NSImage_addRepresentation(dock_image, (void*) representation); - - // Finally, set the dock image to it. - objc_msgSend_void_id(NSApp, sel_registerName("setApplicationIconImage:"), dock_image); - // Free the garbage. - release(dock_image); - release(representation); + objc_msgSend_void_id(NSApp, sel_registerName("sendEvent:"), e); + objc_msgSend_bool_void(eventPool, sel_registerName("drain")); + ((void(*)(id, SEL))objc_msgSend)(NSApp, sel_registerName("updateWindows")); + return NULL; } - NSCursor* NSCursor_arrowStr(char* str) { - void* nclass = objc_getClass("NSCursor"); - void* func = sel_registerName(str); - return (NSCursor*) objc_msgSend_id(nclass, func); + if (win->event.droppedFilesCount) { + u32 i; + for (i = 0; i < win->event.droppedFilesCount; i++) + win->event.droppedFiles[i][0] = '\0'; } - void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) { - assert(win != NULL); + win->event.droppedFilesCount = 0; + win->event.type = 0; - if (image == NULL) { - objc_msgSend_void(NSCursor_arrowStr("arrowCursor"), sel_registerName("set")); - return; + switch (objc_msgSend_uint(e, sel_registerName("type"))) { + case NSEventTypeMouseEntered: { + win->event.type = RGFW_mouseEnter; + NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(e, sel_registerName("locationInWindow")); + + win->event.point = RGFW_POINT((i32) p.x, (i32) (win->r.h - p.y)); + RGFW_mouseNotifyCallBack(win, win->event.point, 1); + break; } - /* NOTE(EimaMei): Code by yours truly. */ - // Make a bitmap representation, then copy the loaded image into it. - void* representation = NSBitmapImageRep_initWithBitmapData(NULL, a.w, a.h, 8, channels, (channels == 4), false, "NSCalibratedRGBColorSpace", 1 << 1, a.w * channels, 8 * channels); - memcpy(NSBitmapImageRep_bitmapData(representation), image, a.w * a.h * channels); + case NSEventTypeMouseExited: + win->event.type = RGFW_mouseLeave; + RGFW_mouseNotifyCallBack(win, win->event.point, 0); + break; - // Add ze representation. - void* cursor_image = NSImage_initWithSize((NSSize){a.w, a.h}); - NSImage_addRepresentation(cursor_image, representation); + case NSEventTypeKeyDown: { + u32 key = (u16) objc_msgSend_uint(e, sel_registerName("keyCode")); - // Finally, set the cursor image. - void* cursor = NSCursor_initWithImage(cursor_image, (NSPoint){0.0, 0.0}); + u32 mappedKey = *((u32*)((char*)(const char*) NSString_to_char(objc_msgSend_id(e, sel_registerName("charactersIgnoringModifiers"))))); + if (((u8)mappedKey) == 239) + mappedKey = 0; - objc_msgSend_void(cursor, sel_registerName("set")); + win->event.keyChar = (u8)mappedKey; - // Free the garbage. - release(cursor_image); - release(representation); - } + win->event.key = RGFW_apiKeyToRGFW(key); + RGFW_keyboard[win->event.key].prev = RGFW_keyboard[win->event.key].current; - void RGFW_window_setMouseDefault(RGFW_window* win) { - RGFW_window_setMouseStandard(win, RGFW_MOUSE_ARROW); - } + win->event.type = RGFW_keyPressed; + win->event.repeat = RGFW_isPressed(win, win->event.key); + RGFW_keyboard[win->event.key].current = 1; - void RGFW_window_showMouse(RGFW_window* win, i8 show) { - RGFW_UNUSED(win); - - if (show) { - CGDisplayShowCursor(kCGDirectMainDisplay); + RGFW_keyCallback(win, win->event.key, win->event.keyChar, win->event.keyMod, 1); + break; } - else { - CGDisplayHideCursor(kCGDirectMainDisplay); + + case NSEventTypeKeyUp: { + u32 key = (u16) objc_msgSend_uint(e, sel_registerName("keyCode")); + + u32 mappedKey = *((u32*)((char*)(const char*) NSString_to_char(objc_msgSend_id(e, sel_registerName("charactersIgnoringModifiers"))))); + if (((u8)mappedKey) == 239) + mappedKey = 0; + + win->event.keyChar = (u8)mappedKey; + + win->event.key = RGFW_apiKeyToRGFW(key); + + RGFW_keyboard[win->event.key].prev = RGFW_keyboard[win->event.key].current; + + win->event.type = RGFW_keyReleased; + + RGFW_keyboard[win->event.key].current = 0; + RGFW_keyCallback(win, win->event.key, win->event.keyChar, win->event.keyMod, 0); + break; } + + case NSEventTypeFlagsChanged: { + u32 flags = objc_msgSend_uint(e, sel_registerName("modifierFlags")); + RGFW_updateKeyModsPro(win, ((u32)(flags & NSEventModifierFlagCapsLock) % 255), ((flags & NSEventModifierFlagNumericPad) % 255), + ((flags & NSEventModifierFlagControl) % 255), ((flags & NSEventModifierFlagOption) % 255), + ((flags & NSEventModifierFlagShift) % 255), ((flags & NSEventModifierFlagCommand) % 255)); + u8 i; + for (i = 0; i < 9; i++) + RGFW_keyboard[i + RGFW_capsLock].prev = 0; + + for (i = 0; i < 5; i++) { + u32 shift = (1 << (i + 16)); + u32 key = i + RGFW_capsLock; + + if ((flags & shift) && !RGFW_wasPressed(win, key)) { + RGFW_keyboard[key].current = 1; + + if (key != RGFW_capsLock) + RGFW_keyboard[key+ 4].current = 1; + + win->event.type = RGFW_keyPressed; + win->event.key = key; + break; + } + + if (!(flags & shift) && RGFW_wasPressed(win, key)) { + RGFW_keyboard[key].current = 0; + + if (key != RGFW_capsLock) + RGFW_keyboard[key + 4].current = 0; + + win->event.type = RGFW_keyReleased; + win->event.key = key; + break; + } + } + + RGFW_keyCallback(win, win->event.key, win->event.keyChar, win->event.keyMod, win->event.type == RGFW_keyPressed); + + break; + } + case NSEventTypeLeftMouseDragged: + case NSEventTypeOtherMouseDragged: + case NSEventTypeRightMouseDragged: + case NSEventTypeMouseMoved: { + win->event.type = RGFW_mousePosChanged; + NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(e, sel_registerName("locationInWindow")); + win->event.point = RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y)); + + if ((win->_flags & RGFW_HOLD_MOUSE)) { + p.x = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaX")); + p.y = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaY")); + + win->event.point = RGFW_POINT((i32)p.x, (i32)p.y); + } + + RGFW_mousePosCallback(win, win->event.point); + break; + } + case NSEventTypeLeftMouseDown: + win->event.button = RGFW_mouseLeft; + win->event.type = RGFW_mouseButtonPressed; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 1; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); + break; + + case NSEventTypeOtherMouseDown: + win->event.button = RGFW_mouseMiddle; + win->event.type = RGFW_mouseButtonPressed; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 1; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); + break; + + case NSEventTypeRightMouseDown: + win->event.button = RGFW_mouseRight; + win->event.type = RGFW_mouseButtonPressed; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 1; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); + break; + + case NSEventTypeLeftMouseUp: + win->event.button = RGFW_mouseLeft; + win->event.type = RGFW_mouseButtonReleased; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 0; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); + break; + + case NSEventTypeOtherMouseUp: + win->event.button = RGFW_mouseMiddle; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 0; + win->event.type = RGFW_mouseButtonReleased; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); + break; + + case NSEventTypeRightMouseUp: + win->event.button = RGFW_mouseRight; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 0; + win->event.type = RGFW_mouseButtonReleased; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); + break; + + case NSEventTypeScrollWheel: { + double deltaY = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaY")); + + if (deltaY > 0) { + win->event.button = RGFW_mouseScrollUp; + } + else if (deltaY < 0) { + win->event.button = RGFW_mouseScrollDown; + } + + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 1; + + win->event.scroll = deltaY; + + win->event.type = RGFW_mouseButtonPressed; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); + break; + } + + default: + objc_msgSend_void_id(NSApp, sel_registerName("sendEvent:"), e); + ((void(*)(id, SEL))objc_msgSend)(NSApp, sel_registerName("updateWindows")); + return RGFW_window_checkEvent(win); } - void RGFW_window_setMouseStandard(RGFW_window* win, u8 stdMouses) { - if (stdMouses > ((sizeof(RGFW_mouseIconSrc)) / (sizeof(char*)))) - return; - - char* mouseStr = RGFW_mouseIconSrc[stdMouses]; - void* mouse = NSCursor_arrowStr(mouseStr); + objc_msgSend_void_id(NSApp, sel_registerName("sendEvent:"), e); + ((void(*)(id, SEL))objc_msgSend)(NSApp, sel_registerName("updateWindows")); - if (mouse == NULL) - return; + objc_msgSend_bool_void(eventPool, sel_registerName("drain")); + return &win->event; +} - RGFW_UNUSED(win); + +void RGFW_window_move(RGFW_window* win, RGFW_point v) { + RGFW_ASSERT(win != NULL); + + win->r.x = v.x; + win->r.y = v.y; + ((void(*)(id, SEL, NSRect, bool, bool))objc_msgSend) + ((id)win->src.window, sel_registerName("setFrame:display:animate:"), (NSRect){{win->r.x, win->r.y}, {win->r.w, win->r.h}}, true, true); +} + +void RGFW_window_resize(RGFW_window* win, RGFW_area a) { + RGFW_ASSERT(win != NULL); + + win->r.w = a.w; + win->r.h = a.h; + ((void(*)(id, SEL, NSRect, bool, bool))objc_msgSend) + ((id)win->src.window, sel_registerName("setFrame:display:animate:"), (NSRect){{win->r.x, win->r.y}, {win->r.w, win->r.h}}, true, true); +} + +void RGFW_window_minimize(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + + objc_msgSend_void_SEL(win->src.window, sel_registerName("performMiniaturize:"), NULL); +} + +void RGFW_window_restore(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + + objc_msgSend_void_SEL(win->src.window, sel_registerName("deminiaturize:"), NULL); +} + +void RGFW_window_setName(RGFW_window* win, const char* name) { + RGFW_ASSERT(win != NULL); + + id str = NSString_stringWithUTF8String(name); + objc_msgSend_void_id((id)win->src.window, sel_registerName("setTitle:"), str); +} + +#ifndef RGFW_NO_PASSTHROUGH +void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) { + objc_msgSend_void_bool(win->src.window, sel_registerName("setIgnoresMouseEvents:"), passthrough); +} +#endif + +void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) { + if (a.w == 0 && a.h == 0) + return; + + ((void (*)(id, SEL, NSSize))objc_msgSend) + ((id)win->src.window, sel_registerName("setMinSize:"), (NSSize){a.w, a.h}); +} + +void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) { + if (a.w == 0 && a.h == 0) + return; + + ((void (*)(id, SEL, NSSize))objc_msgSend) + ((id)win->src.window, sel_registerName("setMaxSize:"), (NSSize){a.w, a.h}); +} + +b32 RGFW_window_setIcon(RGFW_window* win, u8* data, RGFW_area area, i32 channels) { + RGFW_ASSERT(win != NULL); + + /* code by EimaMei */ + // Make a bitmap representation, then copy the loaded image into it. + id representation = NSBitmapImageRep_initWithBitmapData(NULL, area.w, area.h, 8, channels, (channels == 4), false, "NSCalibratedRGBColorSpace", 1 << 1, area.w * channels, 8 * channels); + RGFW_MEMCPY(NSBitmapImageRep_bitmapData(representation), data, area.w * area.h * channels); + + // Add ze representation. + id dock_image = NSImage_initWithSize((NSSize){area.w, area.h}); + NSImage_addRepresentation(dock_image, representation); + + // Finally, set the dock image to it. + objc_msgSend_void_id(NSApp, sel_registerName("setApplicationIconImage:"), dock_image); + // Free the garbage. + NSRelease(dock_image); + NSRelease(representation); + + return 1; +} + +id NSCursor_arrowStr(const char* str) { + void* nclass = objc_getClass("NSCursor"); + SEL func = sel_registerName(str); + return (id) objc_msgSend_id(nclass, func); +} + +RGFW_mouse* RGFW_loadMouse(u8* icon, RGFW_area a, i32 channels) { + if (icon == NULL) { + objc_msgSend_void(NSCursor_arrowStr("arrowCursor"), sel_registerName("set")); + return NULL; + } + + /* NOTE(EimaMei): Code by yours truly. */ + // Make a bitmap representation, then copy the loaded image into it. + id representation = NSBitmapImageRep_initWithBitmapData(NULL, a.w, a.h, 8, channels, (channels == 4), false, "NSCalibratedRGBColorSpace", 1 << 1, a.w * channels, 8 * channels); + RGFW_MEMCPY(NSBitmapImageRep_bitmapData(representation), icon, a.w * a.h * channels); + + // Add ze representation. + id cursor_image = NSImage_initWithSize((NSSize){a.w, a.h}); + NSImage_addRepresentation(cursor_image, representation); + + // Finally, set the cursor image. + id cursor = NSCursor_initWithImage(cursor_image, (NSPoint){0.0, 0.0}); + + // Free the garbage. + NSRelease(cursor_image); + NSRelease(representation); + + return (void*)cursor; +} + +void RGFW_window_setMouse(RGFW_window* win, RGFW_mouse* mouse) { + RGFW_ASSERT(win); RGFW_ASSERT(mouse); + objc_msgSend_void((id)mouse, sel_registerName("set")); +} + +void RGFW_freeMouse(RGFW_mouse* mouse) { + RGFW_ASSERT(mouse); + NSRelease((id)mouse); +} + +b32 RGFW_window_setMouseDefault(RGFW_window* win) { + return RGFW_window_setMouseStandard(win, RGFW_mouseArrow); +} + +void RGFW_window_showMouse(RGFW_window* win, i8 show) { + RGFW_UNUSED(win); + + if (show) { CGDisplayShowCursor(kCGDirectMainDisplay); - objc_msgSend_void(mouse, sel_registerName("set")); } - - void RGFW_releaseCursor(RGFW_window* win) { - RGFW_UNUSED(win); - CGAssociateMouseAndMouseCursorPosition(1); + else { + CGDisplayHideCursor(kCGDirectMainDisplay); } +} - void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) { - RGFW_UNUSED(win) +b32 RGFW_window_setMouseStandard(RGFW_window* win, u8 stdMouses) { + if (stdMouses > ((sizeof(RGFW_mouseIconSrc)) / (sizeof(char*)))) + return 0; - CGWarpMouseCursorPosition(CGPointMake(r.x + (r.w / 2), r.y + (r.h / 2))); - CGAssociateMouseAndMouseCursorPosition(0); - } + const char* mouseStr = RGFW_mouseIconSrc[stdMouses]; + id mouse = NSCursor_arrowStr(mouseStr); - void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v) { - RGFW_UNUSED(win); - - CGWarpMouseCursorPosition(CGPointMake(v.x, v.y)); - } + if (mouse == NULL) + return 0; + + RGFW_UNUSED(win); + CGDisplayShowCursor(kCGDirectMainDisplay); + objc_msgSend_void(mouse, sel_registerName("set")); + + return 1; +} + +void RGFW_releaseCursor(RGFW_window* win) { + RGFW_UNUSED(win); + CGAssociateMouseAndMouseCursorPosition(1); +} + +void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) { + RGFW_UNUSED(win); + + CGWarpMouseCursorPosition(CGPointMake(r.x + (r.w / 2), r.y + (r.h / 2))); + CGAssociateMouseAndMouseCursorPosition(0); +} + +void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v) { + RGFW_UNUSED(win); + + win->_lastMousePoint = RGFW_POINT(v.x - win->r.x, v.y - win->r.y); + CGWarpMouseCursorPosition(CGPointMake(v.x, v.y)); +} - void RGFW_window_hide(RGFW_window* win) { - objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), false); - } +void RGFW_window_hide(RGFW_window* win) { + objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), false); +} - void RGFW_window_show(RGFW_window* win) { - ((id(*)(id, SEL, SEL))objc_msgSend)(win->src.window, sel_registerName("makeKeyAndOrderFront:"), NULL); - objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), true); - } +void RGFW_window_show(RGFW_window* win) { + ((id(*)(id, SEL, SEL))objc_msgSend)((id)win->src.window, sel_registerName("makeKeyAndOrderFront:"), NULL); + objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), true); +} - u8 RGFW_window_isFullscreen(RGFW_window* win) { - assert(win != NULL); +u8 RGFW_window_isFullscreen(RGFW_window* win) { + RGFW_ASSERT(win != NULL); - NSWindowStyleMask mask = (NSWindowStyleMask) objc_msgSend_uint(win->src.window, sel_registerName("styleMask")); - return (mask & NSWindowStyleMaskFullScreen) == NSWindowStyleMaskFullScreen; - } + NSWindowStyleMask mask = (NSWindowStyleMask) objc_msgSend_uint(win->src.window, sel_registerName("styleMask")); + return (mask & NSWindowStyleMaskFullScreen) == NSWindowStyleMaskFullScreen; +} - u8 RGFW_window_isHidden(RGFW_window* win) { - assert(win != NULL); +u8 RGFW_window_isHidden(RGFW_window* win) { + RGFW_ASSERT(win != NULL); - bool visible = objc_msgSend_bool(win->src.window, sel_registerName("isVisible")); - return visible == NO && !RGFW_window_isMinimized(win); - } + bool visible = objc_msgSend_bool(win->src.window, sel_registerName("isVisible")); + return visible == NO && !RGFW_window_isMinimized(win); +} - u8 RGFW_window_isMinimized(RGFW_window* win) { - assert(win != NULL); +u8 RGFW_window_isMinimized(RGFW_window* win) { + RGFW_ASSERT(win != NULL); - return objc_msgSend_bool(win->src.window, sel_registerName("isMiniaturized")) == YES; - } + return objc_msgSend_bool(win->src.window, sel_registerName("isMiniaturized")) == YES; +} - u8 RGFW_window_isMaximized(RGFW_window* win) { - assert(win != NULL); +u8 RGFW_window_isMaximized(RGFW_window* win) { + RGFW_ASSERT(win != NULL); - return objc_msgSend_bool(win->src.window, sel_registerName("isZoomed")); - } + return objc_msgSend_bool(win->src.window, sel_registerName("isZoomed")); +} - static RGFW_monitor RGFW_NSCreateMonitor(CGDirectDisplayID display) { - RGFW_monitor monitor; +id RGFW_getNSScreenForDisplayID(CGDirectDisplayID display) { + Class NSScreenClass = objc_getClass("NSScreen"); - CGRect bounds = CGDisplayBounds(display); - monitor.rect = RGFW_RECT((int) bounds.origin.x, (int) bounds.origin.y, (int) bounds.size.width, (int) bounds.size.height); + id screens = objc_msgSend_id(NSScreenClass, sel_registerName("screens")); - CGSize screenSizeMM = CGDisplayScreenSize(display); - monitor.physW = screenSizeMM.width; - monitor.physH = screenSizeMM.height; + NSUInteger count = (NSUInteger)objc_msgSend_uint(screens, sel_registerName("count")); - monitor.scaleX = ((monitor.rect.w / (screenSizeMM.width / 25.4)) / 96) + 0.25; - monitor.scaleY = ((monitor.rect.h / (screenSizeMM.height / 25.4)) / 96) + 0.25; + for (NSUInteger i = 0; i < count; i++) { + id screen = ((id (*)(id, SEL, int))objc_msgSend) (screens, sel_registerName("objectAtIndex:"), (int)i); + id description = objc_msgSend_id(screen, sel_registerName("deviceDescription")); + id screenNumberKey = NSString_stringWithUTF8String("NSScreenNumber"); + id screenNumber = objc_msgSend_id_id(description, sel_registerName("objectForKey:"), screenNumberKey); - return monitor; - } - - - static RGFW_monitor RGFW_monitors[7]; - - RGFW_monitor* RGFW_getMonitors(void) { - static CGDirectDisplayID displays[7]; - u32 count; - - if (CGGetActiveDisplayList(6, displays, &count) != kCGErrorSuccess) - return NULL; - - for (u32 i = 0; i < count; i++) - RGFW_monitors[i] = RGFW_NSCreateMonitor(displays[i]); - - return RGFW_monitors; - } - - RGFW_monitor RGFW_getPrimaryMonitor(void) { - CGDirectDisplayID primary = CGMainDisplayID(); - return RGFW_NSCreateMonitor(primary); - } - - RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { - return RGFW_NSCreateMonitor(win->src.display); - } - - char* RGFW_readClipboard(size_t* size) { - char* clip = (char*)NSPasteboard_stringForType(NSPasteboard_generalPasteboard(), NSPasteboardTypeString); - - size_t clip_len = 1; - - if (clip != NULL) { - clip_len = strlen(clip) + 1; + if ((CGDirectDisplayID)objc_msgSend_uint(screenNumber, sel_registerName("unsignedIntValue")) == display) { + return screen; } + } - char* str = (char*)RGFW_MALLOC(sizeof(char) * clip_len); - - if (clip != NULL) { - strncpy(str, clip, clip_len); - } + return NULL; +} + +RGFW_monitor RGFW_NSCreateMonitor(CGDirectDisplayID display, id screen) { + RGFW_monitor monitor; + + const char name[] = "MacOS\0"; + RGFW_MEMCPY(monitor.name, name, 6); + + CGRect bounds = CGDisplayBounds(display); + monitor.rect = RGFW_RECT((int) bounds.origin.x, (int) bounds.origin.y, (int) bounds.size.width, (int) bounds.size.height); + + CGSize screenSizeMM = CGDisplayScreenSize(display); + monitor.physW = (float)screenSizeMM.width / 25.4f; + monitor.physH = (float)screenSizeMM.height / 25.4f; + + float ppi_width = (monitor.rect.w/monitor.physW); + float ppi_height = (monitor.rect.h/monitor.physH); + + monitor.pixelRatio = ((CGFloat (*)(id, SEL))abi_objc_msgSend_fpret) (screen, sel_registerName("backingScaleFactor")); + float dpi = 96.0f * monitor.pixelRatio; + + monitor.scaleX = ((i32)(((float) (ppi_width) / dpi) * 10.0f)) / 10.0f; + monitor.scaleY = ((i32)(((float) (ppi_height) / dpi) * 10.0f)) / 10.0f; + + #ifdef RGFW_DEBUG + printf("RGFW INFO: monitor found: scale (%s):\n rect: {%i, %i, %i, %i}\n physical size:%f %f\n scale: %f %f\n pixelRatio: %f\n", monitor.name, monitor.rect.x, monitor.rect.y, monitor.rect.w, monitor.rect.h, monitor.physW, monitor.physH, monitor.scaleX, monitor.scaleY, monitor.pixelRatio); + #endif + + return monitor; +} + + +RGFW_monitor RGFW_monitors[7]; + +RGFW_monitor* RGFW_getMonitors(void) { + static CGDirectDisplayID displays[7]; + u32 count; + + if (CGGetActiveDisplayList(6, displays, &count) != kCGErrorSuccess) + return NULL; + + for (u32 i = 0; i < count; i++) + RGFW_monitors[i] = RGFW_NSCreateMonitor(displays[i], RGFW_getNSScreenForDisplayID(displays[i])); + + return RGFW_monitors; +} + +RGFW_monitor RGFW_getPrimaryMonitor(void) { + CGDirectDisplayID primary = CGMainDisplayID(); + return RGFW_NSCreateMonitor(primary, RGFW_getNSScreenForDisplayID(primary)); +} + +RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { + id screen = objc_msgSend_id(win->src.window, sel_registerName("screen")); + id description = objc_msgSend_id(screen, sel_registerName("deviceDescription")); + id screenNumberKey = NSString_stringWithUTF8String("NSScreenNumber"); + id screenNumber = objc_msgSend_id_id(description, sel_registerName("objectForKey:"), screenNumberKey); + + CGDirectDisplayID display = (CGDirectDisplayID)objc_msgSend_uint(screenNumber, sel_registerName("unsignedIntValue")); + + return RGFW_NSCreateMonitor(display, screen); +} + +RGFW_ssize_t RGFW_readClipboardPtr(char* str, size_t strCapacity) { + size_t clip_len; + char* clip = (char*)NSPasteboard_stringForType(NSPasteboard_generalPasteboard(), NSPasteboardTypeString, &clip_len); + if (clip == NULL) return -1; + + if (str != NULL) { + if (strCapacity < clip_len) + return 0; + + RGFW_MEMCPY(str, clip, clip_len); str[clip_len] = '\0'; - - if (size != NULL) - *size = clip_len; - return str; } - void RGFW_writeClipboard(const char* text, u32 textLen) { - RGFW_UNUSED(textLen); + return (RGFW_ssize_t)clip_len; +} - NSPasteboardType array[] = { NSPasteboardTypeString, NULL }; - NSPasteBoard_declareTypes(NSPasteboard_generalPasteboard(), array, 1, NULL); +void RGFW_writeClipboard(const char* text, u32 textLen) { + RGFW_UNUSED(textLen); - NSPasteBoard_setString(NSPasteboard_generalPasteboard(), text, NSPasteboardTypeString); - } + NSPasteboardType array[] = { NSPasteboardTypeString, NULL }; + NSPasteBoard_declareTypes(NSPasteboard_generalPasteboard(), array, 1, NULL); - u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber) { - RGFW_UNUSED(jsNumber); - - assert(win != NULL); - - return RGFW_registerJoystickF(win, (char*) ""); - } - - u16 RGFW_registerJoystickF(RGFW_window* win, char* file) { - RGFW_UNUSED(file); - - assert(win != NULL); - - return RGFW_joystickCount - 1; - } + NSPasteBoard_setString(NSPasteboard_generalPasteboard(), text, NSPasteboardTypeString); +} #ifdef RGFW_OPENGL void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) { - assert(win != NULL); + RGFW_ASSERT(win != NULL); objc_msgSend_void(win->src.ctx, sel_registerName("makeCurrentContext")); } #endif #if !defined(RGFW_EGL) + void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { - assert(win != NULL); + RGFW_ASSERT(win != NULL); #if defined(RGFW_OPENGL) - - NSOpenGLContext_setValues(win->src.ctx, &swapInterval, 222); + + NSOpenGLContext_setValues((id)win->src.ctx, &swapInterval, 222); #else RGFW_UNUSED(swapInterval); #endif } + #endif - - // Function to create a CGImageRef from an array of bytes - CGImageRef createImageFromBytes(unsigned char *buffer, int width, int height) - { - // Define color space - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - // Create bitmap context - CGContextRef context = CGBitmapContextCreate( - buffer, - width, height, - 8, - RGFW_bufferSize.w * 4, - colorSpace, - kCGImageAlphaPremultipliedLast); - // Create image from bitmap context - CGImageRef image = CGBitmapContextCreateImage(context); - // Release the color space and context - CGColorSpaceRelease(colorSpace); - CGContextRelease(context); - - return image; - } - void RGFW_window_swapBuffers(RGFW_window* win) { - assert(win != NULL); - /* clear the window*/ +// Function to create a CGImageRef from an array of bytes +CGImageRef createImageFromBytes(unsigned char *buffer, int width, int height) +{ + // Define color space + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + // Create bitmap context + CGContextRef context = CGBitmapContextCreate( + buffer, + width, height, + 8, + RGFW_bufferSize.w * 4, + colorSpace, + kCGImageAlphaPremultipliedLast); + // Create image from bitmap context + CGImageRef image = CGBitmapContextCreateImage(context); + // Release the color space and context + CGColorSpaceRelease(colorSpace); + CGContextRelease(context); - if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) { + return image; +} + +void RGFW_window_swapBuffers(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + /* clear the window*/ + + if (!(win->_flags & RGFW_NO_CPU_RENDER)) { #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) - #ifdef RGFW_OSMESA - RGFW_OSMesa_reorganize(); - #endif + id view = NSWindow_contentView((id)win->src.window); + id layer = objc_msgSend_id(view, sel_registerName("layer")); - void* view = NSWindow_contentView(win->src.window); - void* layer = objc_msgSend_id(view, sel_registerName("layer")); + ((void(*)(id, SEL, NSRect))objc_msgSend)(layer, + sel_registerName("setFrame:"), + (NSRect){{0, 0}, {win->r.w, win->r.h}}); - ((void(*)(id, SEL, NSRect))objc_msgSend)(layer, - sel_registerName("setFrame:"), - (NSRect){{0, 0}, {win->r.w, win->r.h}}); + CGImageRef image = createImageFromBytes(win->buffer, win->r.w, win->r.h); + // Get the current graphics context + id graphicsContext = objc_msgSend_class(objc_getClass("NSGraphicsContext"), sel_registerName("currentContext")); + // Get the CGContext from the current NSGraphicsContext + id cgContext = objc_msgSend_id(graphicsContext, sel_registerName("graphicsPort")); + // Draw the image in the context + NSRect bounds = (NSRect){{0,0}, {win->r.w, win->r.h}}; + CGContextDrawImage((void*)cgContext, *(CGRect*)&bounds, image); + // Flush the graphics context to ensure the drawing is displayed + objc_msgSend_id(graphicsContext, sel_registerName("flushGraphics")); - CGImageRef image = createImageFromBytes(win->buffer, win->r.w, win->r.h); - // Get the current graphics context - id graphicsContext = objc_msgSend_class(objc_getClass("NSGraphicsContext"), sel_registerName("currentContext")); - // Get the CGContext from the current NSGraphicsContext - id cgContext = objc_msgSend_id(graphicsContext, sel_registerName("graphicsPort")); - // Draw the image in the context - NSRect bounds = (NSRect){{0,0}, {win->r.w, win->r.h}}; - CGContextDrawImage((void*)cgContext, *(CGRect*)&bounds, image); - // Flush the graphics context to ensure the drawing is displayed - objc_msgSend_id(graphicsContext, sel_registerName("flushGraphics")); - - objc_msgSend_void_id(layer, sel_registerName("setContents:"), (id)image); - objc_msgSend_id(layer, sel_registerName("setNeedsDisplay")); - - CGImageRelease(image); + objc_msgSend_void_id(layer, sel_registerName("setContents:"), (id)image); + objc_msgSend_id(layer, sel_registerName("setNeedsDisplay")); + + CGImageRelease(image); #endif - } - - if (!(win->_winArgs & RGFW_NO_GPU_RENDER)) { - #ifdef RGFW_EGL - eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface); - #elif defined(RGFW_OPENGL) - objc_msgSend_void(win->src.ctx, sel_registerName("flushBuffer")); - #endif - } } - void RGFW_window_close(RGFW_window* win) { - assert(win != NULL); - release(win->src.view); + if (!(win->_flags & RGFW_NO_GPU_RENDER)) { + #ifdef RGFW_EGL + eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface); + #elif defined(RGFW_OPENGL) + objc_msgSend_void(win->src.ctx, sel_registerName("flushBuffer")); + #endif + } +} -#ifdef RGFW_ALLOC_DROPFILES +void RGFW_window_close(RGFW_window* win) { + RGFW_ASSERT(win != NULL); + NSRelease(win->src.view); + + #ifdef RGFW_ALLOC_DROPFILES { u32 i; for (i = 0; i < RGFW_MAX_DROPS; i++) - RGFW_FREE(win->event.droppedFiles[i]); + win->_mem.free(win->_mem.userdata, win->event.droppedFiles[i]); - RGFW_FREE(win->event.droppedFiles); + win->_mem.free(win->_mem.userdata, win->event.droppedFiles); } -#endif - -#ifdef RGFW_BUFFER - release(win->src.bitmap); - release(win->src.image); -#endif + #endif - CVDisplayLinkStop(win->src.displayLink); - CVDisplayLinkRelease(win->src.displayLink); + #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) + NSRelease(win->src.bitmap); + NSRelease(win->src.image); + if ((win->_flags & RGFW_BUFFER_ALLOC)) + win->_mem.free(win->_mem.userdata, win->buffer); + #endif - RGFW_FREE(win); + RGFW_clipboard_switch(NULL); + + if ((win->_flags & RGFW_WINDOW_ALLOC)) + win->_mem.free(win->_mem.userdata, win); +} + +u64 RGFW_getTimeNS(void) { + static mach_timebase_info_data_t timebase_info; + if (timebase_info.denom == 0) { + mach_timebase_info(&timebase_info); } + return mach_absolute_time() * timebase_info.numer / timebase_info.denom; +} - u64 RGFW_getTimeNS(void) { - static mach_timebase_info_data_t timebase_info; - if (timebase_info.denom == 0) { - mach_timebase_info(&timebase_info); - } - return mach_absolute_time() * timebase_info.numer / timebase_info.denom; - } - - u64 RGFW_getTime(void) { - static mach_timebase_info_data_t timebase_info; - if (timebase_info.denom == 0) { - mach_timebase_info(&timebase_info); - } - return (double) mach_absolute_time() * (double) timebase_info.numer / ((double) timebase_info.denom * 1e9); +u64 RGFW_getTime(void) { + static mach_timebase_info_data_t timebase_info; + if (timebase_info.denom == 0) { + mach_timebase_info(&timebase_info); } + return (double) mach_absolute_time() * (double) timebase_info.numer / ((double) timebase_info.denom * 1e9); +} #endif /* RGFW_MACOS */ /* @@ -8264,42 +8939,9 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */ */ #ifdef RGFW_WEBASM -RGFW_Event RGFW_events[20]; +RGFW_event RGFW_events[20]; size_t RGFW_eventLen = 0; -EM_BOOL Emscripten_on_keydown(int eventType, const EmscriptenKeyboardEvent* e, void* userData) { - RGFW_UNUSED(eventType); RGFW_UNUSED(userData); - - RGFW_events[RGFW_eventLen].type = RGFW_keyPressed; - memcpy(RGFW_events[RGFW_eventLen].keyName, e->key, 16); - RGFW_events[RGFW_eventLen].keyCode = RGFW_apiKeyCodeToRGFW(e->keyCode); - RGFW_events[RGFW_eventLen].lockState = 0; - RGFW_eventLen++; - - RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].prev = RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].current; - RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].current = 1; - RGFW_keyCallback(RGFW_root, RGFW_apiKeyCodeToRGFW(e->keyCode), RGFW_events[RGFW_eventLen].keyName, 0, 1); - - return EM_TRUE; -} - -EM_BOOL Emscripten_on_keyup(int eventType, const EmscriptenKeyboardEvent* e, void* userData) { - RGFW_UNUSED(eventType); RGFW_UNUSED(userData); - - RGFW_events[RGFW_eventLen].type = RGFW_keyReleased; - memcpy(RGFW_events[RGFW_eventLen].keyName, e->key, 16); - RGFW_events[RGFW_eventLen].keyCode = RGFW_apiKeyCodeToRGFW(e->keyCode); - RGFW_events[RGFW_eventLen].lockState = 0; - RGFW_eventLen++; - - RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].prev = RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].current; - RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].current = 0; - - RGFW_keyCallback(RGFW_root, RGFW_apiKeyCodeToRGFW(e->keyCode), RGFW_events[RGFW_eventLen].keyName, 0, 0); - - return EM_TRUE; -} - EM_BOOL Emscripten_on_resize(int eventType, const EmscriptenUiEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); @@ -8311,16 +8953,47 @@ EM_BOOL Emscripten_on_resize(int eventType, const EmscriptenUiEvent* e, void* us } EM_BOOL Emscripten_on_fullscreenchange(int eventType, const EmscriptenFullscreenChangeEvent* e, void* userData) { + static u8 fullscreen = RGFW_FALSE; + static RGFW_rect ogRect; + + if (fullscreen == RGFW_FALSE) { + ogRect = RGFW_root->r; + } + + fullscreen = !fullscreen; + RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_events[RGFW_eventLen].type = RGFW_windowResized; RGFW_eventLen++; - RGFW_root->r = RGFW_RECT(0, 0, e->elementWidth, e->elementHeight); + RGFW_root->r = RGFW_RECT(0, 0, e->screenWidth, e->screenHeight); + + EM_ASM("Module.canvas.focus();"); + + if (fullscreen == RGFW_FALSE) { + RGFW_root->r = RGFW_RECT(0, 0, ogRect.w, ogRect.h); + // emscripten_request_fullscreen("#canvas", 0); + } else { + #if __EMSCRIPTEN_major__ >= 1 && __EMSCRIPTEN_minor__ >= 29 && __EMSCRIPTEN_tiny__ >= 0 + EmscriptenFullscreenStrategy FSStrat = {0}; + FSStrat.scaleMode = EMSCRIPTEN_FULLSCREEN_SCALE_STRETCH;//EMSCRIPTEN_FULLSCREEN_SCALE_ASPECT;// : EMSCRIPTEN_FULLSCREEN_SCALE_STRETCH; + FSStrat.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_HIDEF; + FSStrat.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT; + emscripten_request_fullscreen_strategy("#canvas", 1, &FSStrat); + #else + emscripten_request_fullscreen("#canvas", 1); + #endif + } + + emscripten_set_canvas_element_size("#canvas", RGFW_root->r.w, RGFW_root->r.h); + RGFW_windowResizeCallback(RGFW_root, RGFW_root->r); - return EM_TRUE; + return EM_TRUE; } + + EM_BOOL Emscripten_on_focusin(int eventType, const EmscriptenFocusEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_UNUSED(e); @@ -8348,14 +9021,14 @@ EM_BOOL Emscripten_on_mousemove(int eventType, const EmscriptenMouseEvent* e, vo RGFW_events[RGFW_eventLen].type = RGFW_mousePosChanged; - if ((RGFW_root->_winArgs & RGFW_HOLD_MOUSE)) { + if ((RGFW_root->_flags & RGFW_HOLD_MOUSE)) { RGFW_point p = RGFW_POINT(e->movementX, e->movementY); RGFW_events[RGFW_eventLen].point = p; } else RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->targetX, e->targetY); RGFW_eventLen++; - + RGFW_mousePosCallback(RGFW_root, RGFW_events[RGFW_eventLen].point); return EM_TRUE; } @@ -8365,15 +9038,15 @@ EM_BOOL Emscripten_on_mousedown(int eventType, const EmscriptenMouseEvent* e, vo RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonPressed; RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->targetX, e->targetY); - RGFW_events[RGFW_eventLen].button = e->button + 1; + RGFW_events[RGFW_eventLen].button = e->button + 1; RGFW_events[RGFW_eventLen].scroll = 0; - RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current; + RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current; RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 1; RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 1); RGFW_eventLen++; - + return EM_TRUE; } @@ -8382,10 +9055,10 @@ EM_BOOL Emscripten_on_mouseup(int eventType, const EmscriptenMouseEvent* e, void RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonReleased; RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->targetX, e->targetY); - RGFW_events[RGFW_eventLen].button = e->button + 1; + RGFW_events[RGFW_eventLen].button = e->button + 1; RGFW_events[RGFW_eventLen].scroll = 0; - RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current; + RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current; RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 0; RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 0); @@ -8398,10 +9071,10 @@ EM_BOOL Emscripten_on_wheel(int eventType, const EmscriptenWheelEvent* e, void* RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonPressed; RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->mouse.targetX, e->mouse.targetY); - RGFW_events[RGFW_eventLen].button = RGFW_mouseScrollUp + (e->deltaY < 0); - RGFW_events[RGFW_eventLen].scroll = e->deltaY; + RGFW_events[RGFW_eventLen].button = RGFW_mouseScrollUp + (e->deltaY < 0); + RGFW_events[RGFW_eventLen].scroll = e->deltaY < 0 ? 1 : -1; - RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current; + RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current; RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 1; RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 1); @@ -8410,18 +9083,18 @@ EM_BOOL Emscripten_on_wheel(int eventType, const EmscriptenWheelEvent* e, void* return EM_TRUE; } -EM_BOOL Emscripten_on_touchstart(int eventType, const EmscriptenTouchEvent* e, void* userData) { +EM_BOOL Emscripten_on_touchstart(int eventType, const EmscriptenTouchEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); - size_t i; - for (i = 0; i < (size_t)e->numTouches; i++) { + size_t i; + for (i = 0; i < (size_t)e->numTouches; i++) { RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonPressed; RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->touches[i].targetX, e->touches[i].targetY); - RGFW_events[RGFW_eventLen].button = 1; + RGFW_events[RGFW_eventLen].button = 1; RGFW_events[RGFW_eventLen].scroll = 0; - RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current; + RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current; RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 1; RGFW_mousePosCallback(RGFW_root, RGFW_events[RGFW_eventLen].point); @@ -8432,11 +9105,11 @@ EM_BOOL Emscripten_on_touchstart(int eventType, const EmscriptenTouchEvent* e, v return EM_TRUE; } -EM_BOOL Emscripten_on_touchmove(int eventType, const EmscriptenTouchEvent* e, void* userData) { +EM_BOOL Emscripten_on_touchmove(int eventType, const EmscriptenTouchEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); - - size_t i; - for (i = 0; i < (size_t)e->numTouches; i++) { + + size_t i; + for (i = 0; i < (size_t)e->numTouches; i++) { RGFW_events[RGFW_eventLen].type = RGFW_mousePosChanged; RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->touches[i].targetX, e->touches[i].targetY); @@ -8448,17 +9121,17 @@ EM_BOOL Emscripten_on_touchmove(int eventType, const EmscriptenTouchEvent* e, vo EM_BOOL Emscripten_on_touchend(int eventType, const EmscriptenTouchEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); - - size_t i; - for (i = 0; i < (size_t)e->numTouches; i++) { + + size_t i; + for (i = 0; i < (size_t)e->numTouches; i++) { RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonReleased; RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->touches[i].targetX, e->touches[i].targetY); - RGFW_events[RGFW_eventLen].button = 1; + RGFW_events[RGFW_eventLen].button = 1; RGFW_events[RGFW_eventLen].scroll = 0; - RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current; + RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current; RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 0; - + RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 0); RGFW_eventLen++; } @@ -8467,28 +9140,190 @@ EM_BOOL Emscripten_on_touchend(int eventType, const EmscriptenTouchEvent* e, voi EM_BOOL Emscripten_on_touchcancel(int eventType, const EmscriptenTouchEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_UNUSED(e); return EM_TRUE; } -EM_BOOL Emscripten_on_gamepad(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData) { +EM_BOOL Emscripten_on_gamepad(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); if (gamepadEvent->index >= 4) return 0; - RGFW_joysticks[gamepadEvent->index] = gamepadEvent->connected; + size_t i = gamepadEvent->index; + if (gamepadEvent->connected) { + RGFW_MEMCPY(RGFW_gamepads_name[gamepadEvent->index], gamepadEvent->id, sizeof(RGFW_gamepads_name[gamepadEvent->index])); + RGFW_gamepads_type[i] = RGFW_gamepadUnknown; + if (strstr(RGFW_gamepads_name[i], "Microsoft") || strstr(RGFW_gamepads_name[i], "X-Box")) + RGFW_gamepads_type[i] = RGFW_gamepadMicrosoft; + else if (strstr(RGFW_gamepads_name[i], "PlayStation") || strstr(RGFW_gamepads_name[i], "PS3") || strstr(RGFW_gamepads_name[i], "PS4") || strstr(RGFW_gamepads_name[i], "PS5")) + RGFW_gamepads_type[i] = RGFW_gamepadSony; + else if (strstr(RGFW_gamepads_name[i], "Nintendo")) + RGFW_gamepads_type[i] = RGFW_gamepadNintendo; + else if (strstr(RGFW_gamepads_name[i], "Logitech")) + RGFW_gamepads_type[i] = RGFW_gamepadLogitech; + + RGFW_gamepadCount++; + RGFW_events[RGFW_eventLen].type = RGFW_gamepadConnected; + } else { + RGFW_gamepadCount--; + RGFW_events[RGFW_eventLen].type = RGFW_gamepadDisconnected; + } + + RGFW_events[RGFW_eventLen].gamepad = gamepadEvent->index; + RGFW_eventLen++; + + RGFW_gamepadCallback(RGFW_root, gamepadEvent->index, gamepadEvent->connected); + + RGFW_gamepads[gamepadEvent->index] = gamepadEvent->connected; return 1; // The event was consumed by the callback handler } +u32 RGFW_webasmPhysicalToRGFW(u32 hash) { + switch(hash) { /* 0x0000 */ + case 0x67243A2DU /* Escape */: return RGFW_escape; /* 0x0001 */ + case 0x67251058U /* Digit0 */: return RGFW_0; /* 0x0002 */ + case 0x67251059U /* Digit1 */: return RGFW_1; /* 0x0003 */ + case 0x6725105AU /* Digit2 */: return RGFW_2; /* 0x0004 */ + case 0x6725105BU /* Digit3 */: return RGFW_3; /* 0x0005 */ + case 0x6725105CU /* Digit4 */: return RGFW_4; /* 0x0006 */ + case 0x6725105DU /* Digit5 */: return RGFW_5; /* 0x0007 */ + case 0x6725105EU /* Digit6 */: return RGFW_6; /* 0x0008 */ + case 0x6725105FU /* Digit7 */: return RGFW_7; /* 0x0009 */ + case 0x67251050U /* Digit8 */: return RGFW_8; /* 0x000A */ + case 0x67251051U /* Digit9 */: return RGFW_9; /* 0x000B */ + case 0x92E14DD3U /* Minus */: return RGFW_minus; /* 0x000C */ + case 0x92E1FBACU /* Equal */: return RGFW_equals; /* 0x000D */ + case 0x36BF1CB5U /* Backspace */: return RGFW_backSpace; /* 0x000E */ + case 0x7B8E51E2U /* Tab */: return RGFW_tab; /* 0x000F */ + case 0x2C595B51U /* KeyQ */: return RGFW_q; /* 0x0010 */ + case 0x2C595B57U /* KeyW */: return RGFW_w; /* 0x0011 */ + case 0x2C595B45U /* KeyE */: return RGFW_e; /* 0x0012 */ + case 0x2C595B52U /* KeyR */: return RGFW_r; /* 0x0013 */ + case 0x2C595B54U /* KeyT */: return RGFW_t; /* 0x0014 */ + case 0x2C595B59U /* KeyY */: return RGFW_y; /* 0x0015 */ + case 0x2C595B55U /* KeyU */: return RGFW_u; /* 0x0016 */ + case 0x2C595B4FU /* KeyO */: return RGFW_o; /* 0x0018 */ + case 0x2C595B50U /* KeyP */: return RGFW_p; /* 0x0019 */ + case 0x45D8158CU /* BracketLeft */: return RGFW_closeBracket; /* 0x001A */ + case 0xDEEABF7CU /* BracketRight */: return RGFW_bracket; /* 0x001B */ + case 0x92E1C5D2U /* Enter */: return RGFW_return; /* 0x001C */ + case 0xE058958CU /* ControlLeft */: return RGFW_controlL; /* 0x001D */ + case 0x2C595B41U /* KeyA */: return RGFW_a; /* 0x001E */ + case 0x2C595B53U /* KeyS */: return RGFW_s; /* 0x001F */ + case 0x2C595B44U /* KeyD */: return RGFW_d; /* 0x0020 */ + case 0x2C595B46U /* KeyF */: return RGFW_f; /* 0x0021 */ + case 0x2C595B47U /* KeyG */: return RGFW_g; /* 0x0022 */ + case 0x2C595B48U /* KeyH */: return RGFW_h; /* 0x0023 */ + case 0x2C595B4AU /* KeyJ */: return RGFW_j; /* 0x0024 */ + case 0x2C595B4BU /* KeyK */: return RGFW_k; /* 0x0025 */ + case 0x2C595B4CU /* KeyL */: return RGFW_l; /* 0x0026 */ + case 0x2707219EU /* Semicolon */: return RGFW_semicolon; /* 0x0027 */ + case 0x92E0B58DU /* Quote */: return RGFW_apostrophe; /* 0x0028 */ + case 0x36BF358DU /* Backquote */: return RGFW_backtick; /* 0x0029 */ + case 0x26B1958CU /* ShiftLeft */: return RGFW_shiftL; /* 0x002A */ + case 0x36BF2438U /* Backslash */: return RGFW_backSlash; /* 0x002B */ + case 0x2C595B5AU /* KeyZ */: return RGFW_z; /* 0x002C */ + case 0x2C595B58U /* KeyX */: return RGFW_x; /* 0x002D */ + case 0x2C595B43U /* KeyC */: return RGFW_c; /* 0x002E */ + case 0x2C595B56U /* KeyV */: return RGFW_v; /* 0x002F */ + case 0x2C595B42U /* KeyB */: return RGFW_b; /* 0x0030 */ + case 0x2C595B4EU /* KeyN */: return RGFW_n; /* 0x0031 */ + case 0x2C595B4DU /* KeyM */: return RGFW_m; /* 0x0032 */ + case 0x92E1A1C1U /* Comma */: return RGFW_comma; /* 0x0033 */ + case 0x672FFAD4U /* Period */: return RGFW_period; /* 0x0034 */ + case 0x92E0A438U /* Slash */: return RGFW_slash; /* 0x0035 */ + case 0xC5A6BF7CU /* ShiftRight */: return RGFW_shiftR; + case 0x5D64DA91U /* NumpadMultiply */: return RGFW_multiply; + case 0xC914958CU /* AltLeft */: return RGFW_altL; /* 0x0038 */ + case 0x92E09CB5U /* Space */: return RGFW_space; /* 0x0039 */ + case 0xB8FAE73BU /* CapsLock */: return RGFW_capsLock; /* 0x003A */ + case 0x7174B789U /* F1 */: return RGFW_F1; /* 0x003B */ + case 0x7174B78AU /* F2 */: return RGFW_F2; /* 0x003C */ + case 0x7174B78BU /* F3 */: return RGFW_F3; /* 0x003D */ + case 0x7174B78CU /* F4 */: return RGFW_F4; /* 0x003E */ + case 0x7174B78DU /* F5 */: return RGFW_F5; /* 0x003F */ + case 0x7174B78EU /* F6 */: return RGFW_F6; /* 0x0040 */ + case 0x7174B78FU /* F7 */: return RGFW_F7; /* 0x0041 */ + case 0x7174B780U /* F8 */: return RGFW_F8; /* 0x0042 */ + case 0x7174B781U /* F9 */: return RGFW_F9; /* 0x0043 */ + case 0x7B8E57B0U /* F10 */: return RGFW_F10; /* 0x0044 */ + case 0xC925FCDFU /* Numpad7 */: return RGFW_multiply; /* 0x0047 */ + case 0xC925FCD0U /* Numpad8 */: return RGFW_KP_8; /* 0x0048 */ + case 0xC925FCD1U /* Numpad9 */: return RGFW_KP_9; /* 0x0049 */ + case 0x5EA3E8A4U /* NumpadSubtract */: return RGFW_minus; /* 0x004A */ + case 0xC925FCDCU /* Numpad4 */: return RGFW_KP_4; /* 0x004B */ + case 0xC925FCDDU /* Numpad5 */: return RGFW_KP_5; /* 0x004C */ + case 0xC925FCDEU /* Numpad6 */: return RGFW_KP_6; /* 0x004D */ + case 0xC925FCD9U /* Numpad1 */: return RGFW_KP_1; /* 0x004F */ + case 0xC925FCDAU /* Numpad2 */: return RGFW_KP_2; /* 0x0050 */ + case 0xC925FCDBU /* Numpad3 */: return RGFW_KP_3; /* 0x0051 */ + case 0xC925FCD8U /* Numpad0 */: return RGFW_KP_0; /* 0x0052 */ + case 0x95852DACU /* NumpadDecimal */: return RGFW_period; /* 0x0053 */ + case 0x7B8E57B1U /* F11 */: return RGFW_F11; /* 0x0057 */ + case 0x7B8E57B2U /* F12 */: return RGFW_F12; /* 0x0058 */ + case 0x7393FBACU /* NumpadEqual */: return RGFW_KP_Return; + case 0xB88EBF7CU /* AltRight */: return RGFW_altR; /* 0xE038 */ + case 0xC925873BU /* NumLock */: return RGFW_numLock; /* 0xE045 */ + case 0x2C595F45U /* Home */: return RGFW_home; /* 0xE047 */ + case 0xC91BB690U /* ArrowUp */: return RGFW_up; /* 0xE048 */ + case 0x672F9210U /* PageUp */: return RGFW_pageUp; /* 0xE049 */ + case 0x3799258CU /* ArrowLeft */: return RGFW_left; /* 0xE04B */ + case 0x4CE33F7CU /* ArrowRight */: return RGFW_right; /* 0xE04D */ + case 0x7B8E55DCU /* End */: return RGFW_end; /* 0xE04F */ + case 0x3799379EU /* ArrowDown */: return RGFW_down; /* 0xE050 */ + case 0xBA90179EU /* PageDown */: return RGFW_pageDown; /* 0xE051 */ + case 0x6723CB2CU /* Insert */: return RGFW_insert; /* 0xE052 */ + case 0x6725C50DU /* Delete */: return RGFW_delete; /* 0xE053 */ + case 0x6723658CU /* OSLeft */: return RGFW_superL; /* 0xE05B */ + case 0x39643F7CU /* MetaRight */: return RGFW_superR; /* 0xE05C */ + } + + return 0; +} + +void EMSCRIPTEN_KEEPALIVE RGFW_handleKeyEvent(char* key, char* code, b8 press) { + const char* iCode = code; + + u32 hash = 0; + while(*iCode) hash = ((hash ^ 0x7E057D79U) << 3) ^ (unsigned int)*iCode++; + + u32 physicalKey = RGFW_webasmPhysicalToRGFW(hash); + + u8 mappedKey = (u8)(*((u32*)key)); + + if (*((u16*)key) != mappedKey) { + mappedKey = 0; + if (*((u32*)key) == *((u32*)"Tab")) mappedKey = RGFW_tab; + } + + RGFW_events[RGFW_eventLen].type = press ? RGFW_keyPressed : RGFW_keyReleased; + RGFW_events[RGFW_eventLen].key = physicalKey; + RGFW_events[RGFW_eventLen].keyChar = mappedKey; + RGFW_events[RGFW_eventLen].keyMod = RGFW_root->event.keyMod; + RGFW_eventLen++; + + RGFW_keyboard[physicalKey].prev = RGFW_keyboard[physicalKey].current; + RGFW_keyboard[physicalKey].current = press; + + RGFW_keyCallback(RGFW_root, physicalKey, mappedKey, RGFW_root->event.keyMod, press); + + RGFW_free(key); + RGFW_free(code); +} + +void EMSCRIPTEN_KEEPALIVE RGFW_handleKeyMods(b8 capital, b8 numlock, b8 control, b8 alt, b8 shift, b8 super) { + RGFW_updateKeyModsPro(RGFW_root, capital, numlock, control, alt, shift, super); +} + void EMSCRIPTEN_KEEPALIVE Emscripten_onDrop(size_t count) { - if (!(RGFW_root->_winArgs & RGFW_ALLOW_DND)) + if (!(RGFW_root->_flags & RGFW_windowAllowDND)) return; - RGFW_events[RGFW_eventLen].droppedFilesCount = count; + RGFW_events[RGFW_eventLen].droppedFilesCount = count; RGFW_dndCallback(RGFW_root, RGFW_events[RGFW_eventLen].droppedFiles, count); RGFW_eventLen++; } b8 RGFW_stopCheckEvents_bool = RGFW_FALSE; -void RGFW_stopCheckEvents(void) { +void RGFW_stopCheckEvents(void) { RGFW_stopCheckEvents_bool = RGFW_TRUE; } @@ -8497,15 +9332,15 @@ void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) { if (waitMS == 0) return; - + u32 start = (u32)(((u64)RGFW_getTimeNS()) / 1e+6); - while ((RGFW_eventLen == 0) && RGFW_stopCheckEvents_bool == RGFW_FALSE && + while ((RGFW_eventLen == 0) && RGFW_stopCheckEvents_bool == RGFW_FALSE && (waitMS < 0 || (RGFW_getTimeNS() / 1e+6) - start < waitMS) ) { emscripten_sleep(0); } - + RGFW_stopCheckEvents_bool = RGFW_FALSE; } @@ -8514,8 +9349,9 @@ void RGFW_init_buffer(RGFW_window* win) { #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0) RGFW_bufferSize = RGFW_getScreenSize(); - - win->buffer = RGFW_MALLOC(RGFW_bufferSize.w * RGFW_bufferSize.h * 4); + + win->buffer = RGFW_alloc(RGFW_bufferSize.w * RGFW_bufferSize.h * 4); + win->_flags |= RGFW_BUFFER_ALLOC; #ifdef RGFW_OSMESA win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL); OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h); @@ -8525,20 +9361,19 @@ void RGFW_init_buffer(RGFW_window* win) { #endif } -void EMSCRIPTEN_KEEPALIVE RGFW_makeSetValue(size_t index, char* file) { +void EMSCRIPTEN_KEEPALIVE RGFW_makeSetValue(size_t index, char* file) { /* This seems like a terrible idea, don't replicate this unless you hate yourself or the OS */ - /* TODO: find a better way to do this, - strcpy doesn't seem to work, maybe because of asyncio + /* TODO: find a better way to do this */ - RGFW_events[RGFW_eventLen].type = RGFW_dnd; - char** arr = (char**)&RGFW_events[RGFW_eventLen].droppedFiles[index]; - *arr = file; + RGFW_events[RGFW_eventLen].type = RGFW_DND; + RGFW_MEMCPY((char*)RGFW_events[RGFW_eventLen].droppedFiles[index], file, RGFW_MAX_PATH); } #include #include #include +#include void EMSCRIPTEN_KEEPALIVE RGFW_mkdir(char* name) { mkdir(name, 0755); } @@ -8551,54 +9386,50 @@ void EMSCRIPTEN_KEEPALIVE RGFW_writeFile(const char *path, const char *data, siz fclose(file); } -RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) { - RGFW_UNUSED(name) +RGFW_window* RGFW_createWindowPtr(const char* name, RGFW_rect rect, RGFW_windowFlags flags, RGFW_window* win) { + RGFW_UNUSED(name); - RGFW_UNUSED(RGFW_initFormatAttribs); - - RGFW_window* win = RGFW_window_basic_init(rect, args); - -#ifndef RGFW_WEBGPU - EmscriptenWebGLContextAttributes attrs; - attrs.alpha = EM_TRUE; - attrs.depth = EM_TRUE; - attrs.alpha = EM_TRUE; - attrs.stencil = RGFW_STENCIL; - attrs.antialias = RGFW_SAMPLES; - attrs.premultipliedAlpha = EM_TRUE; - attrs.preserveDrawingBuffer = EM_FALSE; - - if (RGFW_DOUBLE_BUFFER == 0) - attrs.renderViaOffscreenBackBuffer = 0; - else - attrs.renderViaOffscreenBackBuffer = RGFW_AUX_BUFFERS; - - attrs.failIfMajorPerformanceCaveat = EM_FALSE; - attrs.majorVersion = (RGFW_majorVersion == 0) ? 1 : RGFW_majorVersion; - attrs.minorVersion = RGFW_minorVersion; - - attrs.enableExtensionsByDefault = EM_TRUE; - attrs.explicitSwapControl = EM_TRUE; + RGFW_window_basic_init(win, rect, flags); - emscripten_webgl_init_context_attributes(&attrs); - win->src.ctx = emscripten_webgl_create_context("#canvas", &attrs); - emscripten_webgl_make_context_current(win->src.ctx); + #ifndef RGFW_WEBGPU + EmscriptenWebGLContextAttributes attrs; + attrs.alpha = EM_TRUE; + attrs.depth = EM_TRUE; + attrs.alpha = EM_TRUE; + attrs.stencil = RGFW_STENCIL; + attrs.antialias = RGFW_SAMPLES; + attrs.premultipliedAlpha = EM_TRUE; + attrs.preserveDrawingBuffer = EM_FALSE; - #ifdef LEGACY_GL_EMULATION - EM_ASM("Module.useWebGL = true; GLImmediate.init();"); + if (RGFW_DOUBLE_BUFFER == 0) + attrs.renderViaOffscreenBackBuffer = 0; + else + attrs.renderViaOffscreenBackBuffer = RGFW_AUX_BUFFERS; + + attrs.failIfMajorPerformanceCaveat = EM_FALSE; + attrs.majorVersion = (RGFW_majorVersion == 0) ? 1 : RGFW_majorVersion; + attrs.minorVersion = RGFW_minorVersion; + + attrs.enableExtensionsByDefault = EM_TRUE; + attrs.explicitSwapControl = EM_TRUE; + + emscripten_webgl_init_context_attributes(&attrs); + win->src.ctx = emscripten_webgl_create_context("#canvas", &attrs); + emscripten_webgl_make_context_current(win->src.ctx); + + #ifdef LEGACY_GL_EMULATION + EM_ASM("Module.useWebGL = true; GLImmediate.init();"); + #endif + #else + win->src.ctx = wgpuCreateInstance(NULL); + win->src.device = emscripten_webgpu_get_device(); + win->src.queue = wgpuDeviceGetQueue(win->src.device); #endif -#else - win->src.ctx = wgpuCreateInstance(NULL); - win->src.device = emscripten_webgpu_get_device(); - win->src.queue = wgpuDeviceGetQueue(win->src.device); -#endif emscripten_set_canvas_element_size("#canvas", rect.w, rect.h); emscripten_set_window_title(name); /* load callbacks */ - emscripten_set_keydown_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_keydown); - emscripten_set_keyup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_keyup); emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_resize); emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, NULL, EM_FALSE, Emscripten_on_fullscreenchange); emscripten_set_mousemove_callback("#canvas", NULL, EM_FALSE, Emscripten_on_mousemove); @@ -8613,11 +9444,26 @@ RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) { emscripten_set_focusout_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_focusout); emscripten_set_gamepadconnected_callback(NULL, 1, Emscripten_on_gamepad); emscripten_set_gamepaddisconnected_callback(NULL, 1, Emscripten_on_gamepad); - - if (args & RGFW_ALLOW_DND) { - win->_winArgs |= RGFW_ALLOW_DND; + + if (flags & RGFW_windowAllowDND) { + win->_flags |= RGFW_windowAllowDND; } + EM_ASM({ + window.addEventListener("keydown", + (event) => { + Module._RGFW_handleKeyMods(event.getModifierState("CapsLock"), event.getModifierState("NumLock"), event.getModifierState("Control"), event.getModifierState("Alt"), event.getModifierState("Shift"), event.getModifierState("Meta")); + Module._RGFW_handleKeyEvent(stringToNewUTF8(event.key), stringToNewUTF8(event.code), 1); + }, + true); + window.addEventListener("keyup", + (event) => { + Module._RGFW_handleKeyMods(event.getModifierState("CapsLock"), event.getModifierState("NumLock"), event.getModifierState("Control"), event.getModifierState("Alt"), event.getModifierState("Shift"), event.getModifierState("Meta")); + Module._RGFW_handleKeyEvent(stringToNewUTF8(event.key), stringToNewUTF8(event.code), 0); + }, + true); + }); + EM_ASM({ var canvas = document.getElementById('canvas'); canvas.addEventListener('drop', function(e) { @@ -8637,29 +9483,29 @@ RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) { var path = '/' + drop_dir + '/' + file.name.replace("//", '_'); var reader = new FileReader(); - + reader.onloadend = (e) => { if (reader.readyState != 2) { out('failed to read dropped file: '+file.name+': '+reader.error); } else { var data = e.target.result; - + _RGFW_writeFile(path, new Uint8Array(data), file.size); } }; - reader.readAsArrayBuffer(file); + reader.readAsArrayBuffer(file); // This works weird on modern opengl var filename = stringToNewUTF8(path); filenamesArray.push(filename); - + Module._RGFW_makeSetValue(i, filename); } - + Module._Emscripten_onDrop(count); - + for (var i = 0; i < count; ++i) { _free(filenamesArray[i]); } @@ -8670,31 +9516,34 @@ RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) { RGFW_init_buffer(win); glViewport(0, 0, rect.w, rect.h); - - RGFW_root = win; - if (args & RGFW_HIDE_MOUSE) { + if (flags & RGFW_windowHideMouse) { RGFW_window_showMouse(win, 0); } - if (args & RGFW_FULLSCREEN) { + if (flags & RGFW_windowFullscreen) { RGFW_window_resize(win, RGFW_getScreenSize()); } + #ifdef RGFW_DEBUG + printf("RGFW INFO: a window with a rect of {%i, %i, %i, %i} \n", win->r.x, win->r.y, win->r.w, win->r.h); + #endif + return win; } -RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) { +RGFW_event* RGFW_window_checkEvent(RGFW_window* win) { static u8 index = 0; - - if (index == 0) - RGFW_resetKey(); + if (index == 0) { + RGFW_resetKey(); + } + + emscripten_sample_gamepad_data(); /* check gamepads */ for (int i = 0; (i < emscripten_get_num_gamepads()) && (i < 4); i++) { - if (RGFW_joysticks[i] == 0) - continue;; - + if (RGFW_gamepads[i] == 0) + continue; EmscriptenGamepadEvent gamepadState; if (emscripten_get_gamepad_status(i, &gamepadState) != EMSCRIPTEN_RESULT_SUCCESS) @@ -8703,33 +9552,50 @@ RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) { // Register buttons data for every connected gamepad for (int j = 0; (j < gamepadState.numButtons) && (j < 16); j++) { u32 map[] = { - RGFW_JS_A, RGFW_JS_X, RGFW_JS_B, RGFW_JS_Y, - RGFW_JS_L1, RGFW_JS_R1, RGFW_JS_L2, RGFW_JS_R2, - RGFW_JS_SELECT, RGFW_JS_START, - 0, 0, - RGFW_JS_UP, RGFW_JS_DOWN, RGFW_JS_LEFT, RGFW_JS_RIGHT + RGFW_gamepadA, RGFW_gamepadB, RGFW_gamepadX, RGFW_gamepadY, + RGFW_gamepadL1, RGFW_gamepadR1, RGFW_gamepadL2, RGFW_gamepadR2, + RGFW_gamepadSelect, RGFW_gamepadStart, + RGFW_gamepadL3, RGFW_gamepadR3, + RGFW_gamepadUp, RGFW_gamepadDown, RGFW_gamepadLeft, RGFW_gamepadRight, RGFW_gamepadHome }; - u32 button = map[j]; - if (RGFW_jsPressed[i][button] != gamepadState.digitalButton[j]) { - win->event.type = RGFW_jsButtonPressed; - win->event.joystick = i; + + u32 button = map[j]; + if (button == 404) + continue; + + if (RGFW_gamepadPressed[i][button].current != gamepadState.digitalButton[j]) { + if (gamepadState.digitalButton[j]) + win->event.type = RGFW_gamepadButtonPressed; + else + win->event.type = RGFW_gamepadButtonReleased; + + win->event.gamepad = i; win->event.button = map[j]; + + RGFW_gamepadPressed[i][button].prev = RGFW_gamepadPressed[i][button].current; + RGFW_gamepadPressed[i][button].current = gamepadState.digitalButton[j]; + + RGFW_gamepadButtonCallback(win, win->event.gamepad, win->event.button, gamepadState.digitalButton[j]); return &win->event; } - - RGFW_jsPressed[i][button] = gamepadState.digitalButton[j]; } for (int j = 0; (j < gamepadState.numAxes) && (j < 4); j += 2) { - win->event.axisesCount = gamepadState.numAxes; - if (win->event.axis[j].x != gamepadState.axis[j] || - win->event.axis[j].y != gamepadState.axis[j + 1] + win->event.axisesCount = gamepadState.numAxes / 2; + if (RGFW_gamepadAxes[i][(size_t)(j / 2)].x != (i8)(gamepadState.axis[j] * 100.0f) || + RGFW_gamepadAxes[i][(size_t)(j / 2)].y != (i8)(gamepadState.axis[j + 1] * 100.0f) ) { - win->event.axis[j].x = gamepadState.axis[j]; - win->event.axis[j].y = gamepadState.axis[j + 1]; - win->event.type = RGFW_jsAxisMove; - win->event.joystick = i; + + RGFW_gamepadAxes[i][(size_t)(j / 2)].x = (i8)(gamepadState.axis[j] * 100.0f); + RGFW_gamepadAxes[i][(size_t)(j / 2)].y = (i8)(gamepadState.axis[j + 1] * 100.0f); + win->event.axis[(size_t)(j / 2)] = RGFW_gamepadAxes[i][(size_t)(j / 2)]; + + win->event.type = RGFW_gamepadAxisMove; + win->event.gamepad = i; + win->event.whichAxis = j / 2; + + RGFW_gamepadAxisCallback(win, win->event.gamepad, win->event.axis, win->event.axisesCount, win->event.whichAxis); return &win->event; } } @@ -8738,7 +9604,7 @@ RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) { /* check queued events */ if (RGFW_eventLen == 0) return NULL; - + RGFW_events[index].frameTime = win->event.frameTime; RGFW_events[index].frameTime2 = win->event.frameTime2; RGFW_events[index].inFocus = win->event.inFocus; @@ -8756,14 +9622,17 @@ RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) { } void RGFW_window_resize(RGFW_window* win, RGFW_area a) { - RGFW_UNUSED(win) + RGFW_UNUSED(win); emscripten_set_canvas_element_size("#canvas", a.w, a.h); } /* NOTE: I don't know if this is possible */ void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v) { RGFW_UNUSED(win); RGFW_UNUSED(v); } /* this one might be possible but it looks iffy */ -void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) { RGFW_UNUSED(win); RGFW_UNUSED(channels) RGFW_UNUSED(a) RGFW_UNUSED(image) } +RGFW_mouse* RGFW_loadMouse(u8* icon, RGFW_area a, i32 channels) { RGFW_UNUSED(channels); RGFW_UNUSED(a); RGFW_UNUSED(icon); return NULL; } + +void RGFW_window_setMouse(RGFW_window* win, RGFW_mouse* mouse) { RGFW_UNUSED(win); RGFW_UNUSED(mouse); } +void RGFW_freeMouse(RGFW_mouse* mouse) { RGFW_UNUSED(mouse); } const char RGFW_CURSORS[11][12] = { "default", @@ -8779,13 +9648,14 @@ const char RGFW_CURSORS[11][12] = { "not-allowed" }; -void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) { - RGFW_UNUSED(win) +b32 RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) { + RGFW_UNUSED(win); EM_ASM( { document.getElementById("canvas").style.cursor = UTF8ToString($0); }, RGFW_CURSORS[mouse]); + return 1; } -void RGFW_window_setMouseDefault(RGFW_window* win) { - RGFW_window_setMouseStandard(win, RGFW_MOUSE_NORMAL); +b32 RGFW_window_setMouseDefault(RGFW_window* win) { + return RGFW_window_setMouseStandard(win, RGFW_mouseNormal); } void RGFW_window_showMouse(RGFW_window* win, i8 show) { @@ -8808,7 +9678,7 @@ RGFW_point RGFW_getGlobalMousePoint(void) { RGFW_point RGFW_window_getMousePoint(RGFW_window* win) { RGFW_UNUSED(win); - + EmscriptenMouseEvent mouseEvent; emscripten_get_mouse_status(&mouseEvent); return RGFW_POINT( mouseEvent.targetX, mouseEvent.targetY); @@ -8828,45 +9698,39 @@ void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) { } void RGFW_writeClipboard(const char* text, u32 textLen) { - RGFW_UNUSED(textLen) + RGFW_UNUSED(textLen); EM_ASM({ navigator.clipboard.writeText(UTF8ToString($0)); }, text); } -char* RGFW_readClipboard(size_t* size) { +RGFW_ssize_t RGFW_readClipboardPtr(char* str, size_t strCapacity) { + RGFW_UNUSED(str); RGFW_UNUSED(strCapacity); /* placeholder code for later I'm not sure if this is possible do the the async stuff */ - - if (size != NULL) - *size = 0; - - char* str = (char*)malloc(1); - str[0] = '\0'; - - return str; + return 0; } void RGFW_window_swapBuffers(RGFW_window* win) { RGFW_UNUSED(win); - + #ifdef RGFW_BUFFER - if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) { + if (!(win->_flags & RGFW_NO_CPU_RENDER)) { glEnable(GL_TEXTURE_2D); GLuint texture; glGenTextures(1,&texture); glBindTexture(GL_TEXTURE_2D,texture); - + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, RGFW_bufferSize.w, RGFW_bufferSize.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, win->buffer); - + float ratioX = ((float)win->r.w / (float)RGFW_bufferSize.w); float ratioY = ((float)win->r.h / (float)RGFW_bufferSize.h); @@ -8912,7 +9776,15 @@ void RGFW_window_close(RGFW_window* win) { emscripten_webgl_destroy_context(win->src.ctx); #endif - free(win); + #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) + if ((win->_flags & RGFW_BUFFER_ALLOC)) + win->_mem.free(win->_mem.userdata, win->buffer); + #endif + + RGFW_clipboard_switch(NULL); + + if ((win->_flags & RGFW_WINDOW_ALLOC)) + win->_mem.free(win->_mem.userdata, win); } int RGFW_innerWidth(void) { return EM_ASM_INT({ return window.innerWidth; }); } @@ -8922,7 +9794,7 @@ RGFW_area RGFW_getScreenSize(void) { return RGFW_AREA(RGFW_innerWidth(), RGFW_innerHeight()); } -void* RGFW_getProcAddress(const char* procname) { +void* RGFW_getProcAddress(const char* procname) { return emscripten_webgl_get_proc_address(procname); } @@ -8943,14 +9815,14 @@ void RGFW_releaseCursor(RGFW_window* win) { emscripten_exit_pointerlock(); } -void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) { +void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) { RGFW_UNUSED(win); RGFW_UNUSED(r); emscripten_request_pointerlock("#canvas", 1); } -void RGFW_window_setName(RGFW_window* win, char* name) { +void RGFW_window_setName(RGFW_window* win, const char* name) { RGFW_UNUSED(win); emscripten_set_window_title(name); } @@ -8958,53 +9830,60 @@ void RGFW_window_setName(RGFW_window* win, char* name) { /* unsupported functions */ RGFW_monitor* RGFW_getMonitors(void) { return NULL; } RGFW_monitor RGFW_getPrimaryMonitor(void) { return (RGFW_monitor){}; } -void RGFW_window_move(RGFW_window* win, RGFW_point v) { RGFW_UNUSED(win) RGFW_UNUSED(v) } -void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) { RGFW_UNUSED(win) RGFW_UNUSED(a) } -void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) { RGFW_UNUSED(win) RGFW_UNUSED(a) } -void RGFW_window_minimize(RGFW_window* win) { RGFW_UNUSED(win)} -void RGFW_window_restore(RGFW_window* win) { RGFW_UNUSED(win) } -void RGFW_window_setBorder(RGFW_window* win, b8 border) { RGFW_UNUSED(win) RGFW_UNUSED(border) } -void RGFW_window_setIcon(RGFW_window* win, u8* icon, RGFW_area a, i32 channels) { RGFW_UNUSED(win) RGFW_UNUSED(icon) RGFW_UNUSED(a) RGFW_UNUSED(channels) } -void RGFW_window_hide(RGFW_window* win) { RGFW_UNUSED(win) } -void RGFW_window_show(RGFW_window* win) {RGFW_UNUSED(win) } -b8 RGFW_window_isHidden(RGFW_window* win) { RGFW_UNUSED(win) return 0; } -b8 RGFW_window_isMinimized(RGFW_window* win) { RGFW_UNUSED(win) return 0; } -b8 RGFW_window_isMaximized(RGFW_window* win) { RGFW_UNUSED(win) return 0; } -RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { RGFW_UNUSED(win) return (RGFW_monitor){}; } - +void RGFW_window_move(RGFW_window* win, RGFW_point v) { RGFW_UNUSED(win); RGFW_UNUSED(v); } +void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) { RGFW_UNUSED(win); RGFW_UNUSED(a); } +void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) { RGFW_UNUSED(win); RGFW_UNUSED(a); } +void RGFW_window_minimize(RGFW_window* win) { RGFW_UNUSED(win); } +void RGFW_window_restore(RGFW_window* win) { RGFW_UNUSED(win); } +void RGFW_window_setBorder(RGFW_window* win, b8 border) { RGFW_UNUSED(win); RGFW_UNUSED(border); } +b32 RGFW_window_setIcon(RGFW_window* win, u8* icon, RGFW_area a, i32 channels) { RGFW_UNUSED(win); RGFW_UNUSED(icon); RGFW_UNUSED(a); RGFW_UNUSED(channels); return 0; } +void RGFW_window_hide(RGFW_window* win) { RGFW_UNUSED(win); } +void RGFW_window_show(RGFW_window* win) {RGFW_UNUSED(win); } +b8 RGFW_window_isHidden(RGFW_window* win) { RGFW_UNUSED(win); return 0; } +b8 RGFW_window_isMinimized(RGFW_window* win) { RGFW_UNUSED(win); return 0; } +b8 RGFW_window_isMaximized(RGFW_window* win) { RGFW_UNUSED(win); return 0; } +RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { RGFW_UNUSED(win); return (RGFW_monitor){}; } #endif /* end of web asm defines */ /* unix (macOS, linux, web asm) only stuff */ #if defined(RGFW_X11) || defined(RGFW_MACOS) || defined(RGFW_WEBASM) || defined(RGFW_WAYLAND) + /* unix threading */ #ifndef RGFW_NO_THREADS #include - RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args) { - RGFW_UNUSED(args); - - RGFW_thread t; - pthread_create((pthread_t*) &t, NULL, *ptr, NULL); - return t; - } - void RGFW_cancelThread(RGFW_thread thread) { pthread_cancel((pthread_t) thread); } - void RGFW_joinThread(RGFW_thread thread) { pthread_join((pthread_t) thread, NULL); } -#ifdef __linux__ - void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { pthread_setschedprio((pthread_t)thread, priority); } +RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args) { + RGFW_UNUSED(args); + + RGFW_thread t; + pthread_create((pthread_t*) &t, NULL, *ptr, NULL); + return t; +} +void RGFW_cancelThread(RGFW_thread thread) { pthread_cancel((pthread_t) thread); } +void RGFW_joinThread(RGFW_thread thread) { pthread_join((pthread_t) thread, NULL); } + +#if defined(__linux__) +void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { pthread_setschedprio((pthread_t)thread, priority); } +#else +void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { RGFW_UNUSED(thread); RGFW_UNUSED(priority); } #endif #endif #ifndef RGFW_WEBASM -/* unix sleep */ - void RGFW_sleep(u64 ms) { - struct timespec time; - time.tv_sec = 0; - time.tv_nsec = ms * 1e+6; - nanosleep(&time, NULL); - } +/* unix sleep */ +void RGFW_sleep(u64 ms) { + struct timespec time; + time.tv_sec = 0; + time.tv_nsec = ms * 1e+6; + + #ifndef RGFW_NO_UNIX_CLOCK + nanosleep(&time, NULL); + #endif +} + #endif #endif /* end of unix / mac stuff*/ @@ -9012,4 +9891,7 @@ RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { RGFW_UNUSED(win) return #if defined(__cplusplus) && !defined(__EMSCRIPTEN__) } + #ifdef __clang__ + #pragma clang diagnostic pop + #endif #endif diff --git a/src/external/win32_clipboard.h b/src/external/win32_clipboard.h new file mode 100644 index 000000000..832856432 --- /dev/null +++ b/src/external/win32_clipboard.h @@ -0,0 +1,374 @@ +#if !defined(_WIN32) +# error "This module is only made for Windows OS" +#endif + +#ifndef WIN32_CLIPBOARD_ +#define WIN32_CLIPBOARD_ +unsigned char* Win32GetClipboardImageData(int* width, int* height, unsigned long long int *dataSize); +#endif // WIN32_CLIPBOARD_ + +#ifdef WIN32_CLIPBOARD_IMPLEMENTATION +#include +#include +#include +#include + +// NOTE: These search for architecture is taken from "Windows.h", and it's necessary if we really don't wanna import windows.h +// and still make it compile on msvc, because import indirectly importing "winnt.h" (e.g. ) can cause problems is these are not defined. +#if !defined(_X86_) && !defined(_68K_) && !defined(_MPPC_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && !defined(_ARM64_) && !defined(_ARM64EC_) && defined(_M_IX86) +#define _X86_ +#if !defined(_CHPE_X86_ARM64_) && defined(_M_HYBRID) +#define _CHPE_X86_ARM64_ +#endif +#endif + +#if !defined(_AMD64_) && !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && !defined(_ARM64_) && (defined(_M_AMD64) || defined(_M_ARM64EC)) +#define _AMD64_ +#endif + +#if !defined(_ARM_) && !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM64_) && !defined(_ARM64EC_) && defined(_M_ARM) +#define _ARM_ +#endif + +#if !defined(_ARM64_) && !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && !defined(_ARM64EC_) && defined(_M_ARM64) +#define _ARM64_ +#endif + +#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_ARM_) && !defined(_ARM64_) && !defined(_ARM64EC_) && defined(_M_ARM64EC) +#define _ARM64EC_ +#endif + +#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && !defined(_ARM64_) && !defined(_ARM64EC_) && defined(_M_M68K) +#define _68K_ +#endif + +#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && !defined(_ARM64_) && !defined(_ARM64EC_) && defined(_M_MPPC) +#define _MPPC_ +#endif + +#if !defined(_IA64_) && !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_M_IX86) && !defined(_AMD64_) && !defined(_ARM_) && !defined(_ARM64_) && !defined(_ARM64EC_) && defined(_M_IA64) +#define _IA64_ +#endif + + +#define WIN32_LEAN_AND_MEAN +// #include +// #include +// #include +#include +// #include + +#ifndef WINAPI +#if defined(_ARM_) +#define WINAPI +#else +#define WINAPI __stdcall +#endif +#endif + +#ifndef WINAPI +#if defined(_ARM_) +#define WINAPI +#else +#define WINAPI __stdcall +#endif +#endif + +#ifndef WINBASEAPI +#ifndef _KERNEL32_ +#define WINBASEAPI DECLSPEC_IMPORT +#else +#define WINBASEAPI +#endif +#endif + +#ifndef WINUSERAPI +#ifndef _USER32_ +#define WINUSERAPI __declspec (dllimport) +#else +#define WINUSERAPI +#endif +#endif + +typedef int WINBOOL; + + + +// typedef HANDLE HGLOBAL; + +#ifndef HWND +#define HWND void* +#endif + + +#if !defined(_WINUSER_) || !defined(WINUSER_ALREADY_INCLUDED) +WINUSERAPI WINBOOL WINAPI OpenClipboard(HWND hWndNewOwner); +WINUSERAPI WINBOOL WINAPI CloseClipboard(VOID); +WINUSERAPI DWORD WINAPI GetClipboardSequenceNumber(VOID); +WINUSERAPI HWND WINAPI GetClipboardOwner(VOID); +WINUSERAPI HWND WINAPI SetClipboardViewer(HWND hWndNewViewer); +WINUSERAPI HWND WINAPI GetClipboardViewer(VOID); +WINUSERAPI WINBOOL WINAPI ChangeClipboardChain(HWND hWndRemove, HWND hWndNewNext); +WINUSERAPI HANDLE WINAPI SetClipboardData(UINT uFormat, HANDLE hMem); +WINUSERAPI HANDLE WINAPI GetClipboardData(UINT uFormat); +WINUSERAPI UINT WINAPI RegisterClipboardFormatA(LPCSTR lpszFormat); +WINUSERAPI UINT WINAPI RegisterClipboardFormatW(LPCWSTR lpszFormat); +WINUSERAPI int WINAPI CountClipboardFormats(VOID); +WINUSERAPI UINT WINAPI EnumClipboardFormats(UINT format); +WINUSERAPI int WINAPI GetClipboardFormatNameA(UINT format, LPSTR lpszFormatName, int cchMaxCount); +WINUSERAPI int WINAPI GetClipboardFormatNameW(UINT format, LPWSTR lpszFormatName, int cchMaxCount); +WINUSERAPI WINBOOL WINAPI EmptyClipboard(VOID); +WINUSERAPI WINBOOL WINAPI IsClipboardFormatAvailable(UINT format); +WINUSERAPI int WINAPI GetPriorityClipboardFormat(UINT *paFormatPriorityList, int cFormats); +WINUSERAPI HWND WINAPI GetOpenClipboardWindow(VOID); +#endif + +#ifndef HGLOBAL +#define HGLOBAL void* +#endif + +#if !defined(_WINBASE_) || !defined(WINBASE_ALREADY_INCLUDED) +WINBASEAPI SIZE_T WINAPI GlobalSize (HGLOBAL hMem); +WINBASEAPI LPVOID WINAPI GlobalLock (HGLOBAL hMem); +WINBASEAPI WINBOOL WINAPI GlobalUnlock (HGLOBAL hMem); +#endif + + +#if !defined(_WINGDI_) || !defined(WINGDI_ALREADY_INCLUDED) +#ifndef BITMAPINFOHEADER_ALREADY_DEFINED +#define BITMAPINFOHEADER_ALREADY_DEFINED +// Does this header need to be packed ? by the windowps header it doesnt seem to be +#pragma pack(push, 1) +typedef struct tagBITMAPINFOHEADER { + DWORD biSize; + LONG biWidth; + LONG biHeight; + WORD biPlanes; + WORD biBitCount; + DWORD biCompression; + DWORD biSizeImage; + LONG biXPelsPerMeter; + LONG biYPelsPerMeter; + DWORD biClrUsed; + DWORD biClrImportant; +} BITMAPINFOHEADER,*LPBITMAPINFOHEADER,*PBITMAPINFOHEADER; +#pragma pack(pop) +#endif + +#ifndef BITMAPFILEHEADER_ALREADY_DEFINED +#define BITMAPFILEHEADER_ALREADY_DEFINED +#pragma pack(push, 1) +typedef struct tagBITMAPFILEHEADER { + WORD bfType; + DWORD bfSize; + WORD bfReserved1; + WORD bfReserved2; + DWORD bfOffBits; +} BITMAPFILEHEADER,*LPBITMAPFILEHEADER,*PBITMAPFILEHEADER; +#pragma pack(pop) +#endif + +#ifndef RGBQUAD_ALREADY_DEFINED +#define RGBQUAD_ALREADY_DEFINED +typedef struct tagRGBQUAD { + BYTE rgbBlue; + BYTE rgbGreen; + BYTE rgbRed; + BYTE rgbReserved; +} RGBQUAD, *LPRGBQUAD; +#endif + + +// https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-wmf/4e588f70-bd92-4a6f-b77f-35d0feaf7a57 +#define BI_RGB 0x0000 +#define BI_RLE8 0x0001 +#define BI_RLE4 0x0002 +#define BI_BITFIELDS 0x0003 +#define BI_JPEG 0x0004 +#define BI_PNG 0x0005 +#define BI_CMYK 0x000B +#define BI_CMYKRLE8 0x000C +#define BI_CMYKRLE4 0x000D + +#endif + +// https://learn.microsoft.com/en-us/windows/win32/dataxchg/standard-clipboard-formats +#define CF_DIB 8 + +// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setsystemcursor +// #define OCR_NORMAL 32512 // Normal select +// #define OCR_IBEAM 32513 // Text select +// #define OCR_WAIT 32514 // Busy +// #define OCR_CROSS 32515 // Precision select +// #define OCR_UP 32516 // Alternate select +// #define OCR_SIZENWSE 32642 // Diagonal resize 1 +// #define OCR_SIZENESW 32643 // Diagonal resize 2 +// #define OCR_SIZEWE 32644 // Horizontal resize +// #define OCR_SIZENS 32645 // Vertical resize +// #define OCR_SIZEALL 32646 // Move +// #define OCR_NO 32648 // Unavailable +// #define OCR_HAND 32649 // Link select +// #define OCR_APPSTARTING 32650 // + + +//---------------------------------------------------------------------------------- +// Module Internal Functions Declaration +//---------------------------------------------------------------------------------- + + +static BOOL OpenClipboardRetrying(HWND handle); // Open clipboard with a number of retries +static int GetPixelDataOffset(BITMAPINFOHEADER bih); + +unsigned char* Win32GetClipboardImageData(int* width, int* height, unsigned long long int *dataSize) +{ + HWND win = NULL; // Get from somewhere but is doesnt seem to matter + const char* msgString = ""; + int severity = LOG_INFO; + BYTE* bmpData = NULL; + if (!OpenClipboardRetrying(win)) { + severity = LOG_ERROR; + msgString = "Couldn't open clipboard"; + goto end; + } + + HGLOBAL clipHandle = (HGLOBAL)GetClipboardData(CF_DIB); + if (!clipHandle) { + severity = LOG_ERROR; + msgString = "Clipboard data is not an Image"; + goto close; + } + + BITMAPINFOHEADER *bmpInfoHeader = (BITMAPINFOHEADER *)GlobalLock(clipHandle); + if (!bmpInfoHeader) { + // Mapping from HGLOBAL to our local *address space* failed + severity = LOG_ERROR; + msgString = "Clipboard data failed to be locked"; + goto unlock; + } + + *width = bmpInfoHeader->biWidth; + *height = bmpInfoHeader->biHeight; + + SIZE_T clipDataSize = GlobalSize(clipHandle); + if (clipDataSize < sizeof(BITMAPINFOHEADER)) { + // Format CF_DIB needs space for BITMAPINFOHEADER struct. + msgString = "Clipboard has Malformed data"; + severity = LOG_ERROR; + goto unlock; + } + + // Denotes where the pixel data starts from the bmpInfoHeader pointer + int pixelOffset = GetPixelDataOffset(*bmpInfoHeader); + + //--------------------------------------------------------------------------------// + // + // The rest of the section is about create the bytes for a correct BMP file + // Then we copy the data and to a pointer + // + //--------------------------------------------------------------------------------// + + BITMAPFILEHEADER bmpFileHeader = {0}; + SIZE_T bmpFileSize = sizeof(bmpFileHeader) + clipDataSize; + *dataSize = bmpFileSize; + + bmpFileHeader.bfType = 0x4D42; //https://stackoverflow.com/questions/601430/multibyte-character-constants-and-bitmap-file-header-type-constants#601536 + + bmpFileHeader.bfSize = (DWORD)bmpFileSize; // Up to 4GB works fine + bmpFileHeader.bfOffBits = sizeof(bmpFileHeader) + pixelOffset; + + // + // Each process has a default heap provided by the system + // Memory objects allocated by GlobalAlloc and LocalAlloc are in private, + // committed pages with read/write access that cannot be accessed by other processes. + // + // This may be wrong since we might be allocating in a DLL and freeing from another module, the main application + // that may cause heap corruption. We could create a FreeImage function + // + bmpData = malloc(sizeof(bmpFileHeader) + clipDataSize); + // First we add the header for a bmp file + memcpy(bmpData, &bmpFileHeader, sizeof(bmpFileHeader)); + // Then we add the header for the bmp itself + the pixel data + memcpy(bmpData + sizeof(bmpFileHeader), bmpInfoHeader, clipDataSize); + msgString = "Clipboad image acquired successfully"; + + +unlock: + GlobalUnlock(clipHandle); +close: + CloseClipboard(); +end: + + TRACELOG(severity, msgString); + return bmpData; +} + +static BOOL OpenClipboardRetrying(HWND hWnd) +{ + static const int maxTries = 20; + static const int sleepTimeMS = 60; + for (int _ = 0; _ < maxTries; ++_) + { + // Might be being hold by another process + // Or yourself forgot to CloseClipboard + if (OpenClipboard(hWnd)) { + return true; + } + Sleep(sleepTimeMS); + } + return false; +} + +// Based off of researching microsoft docs and reponses from this question https://stackoverflow.com/questions/30552255/how-to-read-a-bitmap-from-the-windows-clipboard#30552856 +// https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapinfoheader +// Get the byte offset where does the pixels data start (from a packed DIB) +static int GetPixelDataOffset(BITMAPINFOHEADER bih) +{ + int offset = 0; + const unsigned int rgbaSize = sizeof(RGBQUAD); + + // biSize Specifies the number of bytes required by the structure + // We expect to always be 40 because it should be packed + if (40 == bih.biSize && 40 == sizeof(BITMAPINFOHEADER)) + { + // + // biBitCount Specifies the number of bits per pixel. + // Might exist some bit masks *after* the header and *before* the pixel offset + // we're looking, but only if we have more than + // 8 bits per pixel, so we need to ajust for that + // + if (bih.biBitCount > 8) + { + // if bih.biCompression is RBG we should NOT offset more + + if (bih.biCompression == BI_BITFIELDS) + { + offset += 3 * rgbaSize; + } else if (bih.biCompression == 6 /* BI_ALPHABITFIELDS */) + { + // Not widely supported, but valid. + offset += 4 * rgbaSize; + } + } + } + + // + // biClrUsed Specifies the number of color indices in the color table that are actually used by the bitmap. + // If this value is zero, the bitmap uses the maximum number of colors + // corresponding to the value of the biBitCount member for the compression mode specified by biCompression. + // If biClrUsed is nonzero and the biBitCount member is less than 16 + // the biClrUsed member specifies the actual number of colors + // + if (bih.biClrUsed > 0) { + offset += bih.biClrUsed * rgbaSize; + } else { + if (bih.biBitCount < 16) + { + offset = offset + (rgbaSize << bih.biBitCount); + } + } + + return bih.biSize + offset; +} +#endif // WIN32_CLIPBOARD_IMPLEMENTATION +// EOF + diff --git a/src/minshell.html b/src/minshell.html index 4068ca36c..ec7158841 100644 --- a/src/minshell.html +++ b/src/minshell.html @@ -34,12 +34,8 @@