Merge branch 'raysan5:master' into master
This commit is contained in:
commit
1cc9a9c738
4
.github/workflows/linux.yml
vendored
4
.github/workflows/linux.yml
vendored
|
|
@ -55,7 +55,7 @@ jobs:
|
||||||
- name: Build Library
|
- name: Build Library
|
||||||
run: |
|
run: |
|
||||||
cd src
|
cd src
|
||||||
make PLATFORM=PLATFORM_DESKTOP CC=gcc RAYLIB_LIBTYPE=STATIC RAYLIB_RELEASE_PATH="../build/${{ env.RELEASE_NAME }}/lib" CFLAGS="-m32"
|
make PLATFORM=PLATFORM_DESKTOP CC=gcc RAYLIB_LIBTYPE=STATIC RAYLIB_RELEASE_PATH="../build/${{ env.RELEASE_NAME }}/lib" CFLAGS="-m32" -B
|
||||||
# make PLATFORM=PLATFORM_DESKTOP CC=gcc RAYLIB_LIBTYPE=SHARED RAYLIB_RELEASE_PATH="../build/${{ env.RELEASE_NAME }}/lib" -B
|
# make PLATFORM=PLATFORM_DESKTOP CC=gcc RAYLIB_LIBTYPE=SHARED RAYLIB_RELEASE_PATH="../build/${{ env.RELEASE_NAME }}/lib" -B
|
||||||
cd ..
|
cd ..
|
||||||
if: matrix.bits == 32
|
if: matrix.bits == 32
|
||||||
|
|
@ -63,7 +63,7 @@ jobs:
|
||||||
- name: Build Library
|
- name: Build Library
|
||||||
run: |
|
run: |
|
||||||
cd src
|
cd src
|
||||||
make PLATFORM=PLATFORM_DESKTOP CC=gcc RAYLIB_LIBTYPE=STATIC RAYLIB_RELEASE_PATH="../build/${{ env.RELEASE_NAME }}/lib"
|
make PLATFORM=PLATFORM_DESKTOP CC=gcc RAYLIB_LIBTYPE=STATIC RAYLIB_RELEASE_PATH="../build/${{ env.RELEASE_NAME }}/lib" -B
|
||||||
make PLATFORM=PLATFORM_DESKTOP CC=gcc RAYLIB_LIBTYPE=SHARED RAYLIB_RELEASE_PATH="../build/${{ env.RELEASE_NAME }}/lib" -B
|
make PLATFORM=PLATFORM_DESKTOP CC=gcc RAYLIB_LIBTYPE=SHARED RAYLIB_RELEASE_PATH="../build/${{ env.RELEASE_NAME }}/lib" -B
|
||||||
cd ..
|
cd ..
|
||||||
if: matrix.bits == 64
|
if: matrix.bits == 64
|
||||||
|
|
|
||||||
4
.github/workflows/macos.yml
vendored
4
.github/workflows/macos.yml
vendored
|
|
@ -40,12 +40,12 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
cd src
|
cd src
|
||||||
clang --version
|
clang --version
|
||||||
make PLATFORM=PLATFORM_DESKTOP RAYLIB_LIBTYPE=STATIC RAYLIB_RELEASE_PATH="../build/${{ env.RELEASE_NAME }}/lib" CFLAGS="-target x86_64-apple-macos10.12 -DGL_SILENCE_DEPRECATION"
|
make PLATFORM=PLATFORM_DESKTOP RAYLIB_LIBTYPE=STATIC RAYLIB_RELEASE_PATH="../build/${{ env.RELEASE_NAME }}/lib" CFLAGS="-target x86_64-apple-macos10.12 -DGL_SILENCE_DEPRECATION" -B
|
||||||
# make PLATFORM=PLATFORM_DESKTOP RAYLIB_LIBTYPE=STATIC RAYLIB_LIB_NAME=raylib_x86_64 CFLAGS="-target x86_64-apple-macos10.12 -DGL_SILENCE_DEPRECATION"
|
# make PLATFORM=PLATFORM_DESKTOP RAYLIB_LIBTYPE=STATIC RAYLIB_LIB_NAME=raylib_x86_64 CFLAGS="-target x86_64-apple-macos10.12 -DGL_SILENCE_DEPRECATION"
|
||||||
# make PLATFORM=PLATFORM_DESKTOP RAYLIB_LIBTYPE=STATIC RAYLIB_LIB_NAME=raylib_arm64 CFLAGS="-target arm64-apple-macos11 -DGL_SILENCE_DEPRECATION" -B
|
# make PLATFORM=PLATFORM_DESKTOP RAYLIB_LIBTYPE=STATIC RAYLIB_LIB_NAME=raylib_arm64 CFLAGS="-target arm64-apple-macos11 -DGL_SILENCE_DEPRECATION" -B
|
||||||
# lipo -create -output ../build/${{ env.RELEASE_NAME }}/lib/libraylib.a libraylib_x86_64.a libraylib_arm64.a
|
# lipo -create -output ../build/${{ env.RELEASE_NAME }}/lib/libraylib.a libraylib_x86_64.a libraylib_arm64.a
|
||||||
make clean
|
make clean
|
||||||
make PLATFORM=PLATFORM_DESKTOP RAYLIB_LIBTYPE=SHARED RAYLIB_RELEASE_PATH="../build/${{ env.RELEASE_NAME }}/lib" CFLAGS="-target x86_64-apple-macos10.12 -DGL_SILENCE_DEPRECATION"
|
make PLATFORM=PLATFORM_DESKTOP RAYLIB_LIBTYPE=SHARED RAYLIB_RELEASE_PATH="../build/${{ env.RELEASE_NAME }}/lib" CFLAGS="-target x86_64-apple-macos10.12 -DGL_SILENCE_DEPRECATION" -B
|
||||||
# make PLATFORM=PLATFORM_DESKTOP RAYLIB_LIBTYPE=SHARED RAYLIB_LIB_NAME=raylib_x86_64 CFLAGS="-target x86_64-apple-macos10.12 -DGL_SILENCE_DEPRECATION" -B
|
# make PLATFORM=PLATFORM_DESKTOP RAYLIB_LIBTYPE=SHARED RAYLIB_LIB_NAME=raylib_x86_64 CFLAGS="-target x86_64-apple-macos10.12 -DGL_SILENCE_DEPRECATION" -B
|
||||||
# make PLATFORM=PLATFORM_DESKTOP RAYLIB_LIBTYPE=SHARED RAYLIB_LIB_NAME=raylib_arm64 CFLAGS="-target i686-apple-macos -DGL_SILENCE_DEPRECATION" -B
|
# make PLATFORM=PLATFORM_DESKTOP RAYLIB_LIBTYPE=SHARED RAYLIB_LIB_NAME=raylib_arm64 CFLAGS="-target i686-apple-macos -DGL_SILENCE_DEPRECATION" -B
|
||||||
# lipo -create -output ../build/${{ env.RELEASE_NAME }}/lib/libraylib.3.1.0.dylib libraylib_x86_64.3.1.0.dylib libraylib_arm64.3.1.0.dylib
|
# lipo -create -output ../build/${{ env.RELEASE_NAME }}/lib/libraylib.3.1.0.dylib libraylib_x86_64.3.1.0.dylib libraylib_arm64.3.1.0.dylib
|
||||||
|
|
|
||||||
2
.github/workflows/webassembly.yml
vendored
2
.github/workflows/webassembly.yml
vendored
|
|
@ -43,7 +43,7 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
cd src
|
cd src
|
||||||
emcc -v
|
emcc -v
|
||||||
make PLATFORM=PLATFORM_WEB EMSDK_PATH="D:/a/raylib/raylib/emsdk-cache/emsdk-master" RAYLIB_RELEASE_PATH="../build/${{ env.RELEASE_NAME }}/lib"
|
make PLATFORM=PLATFORM_WEB EMSDK_PATH="D:/a/raylib/raylib/emsdk-cache/emsdk-master" RAYLIB_RELEASE_PATH="../build/${{ env.RELEASE_NAME }}/lib" -B
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
- name: Generate Artifacts
|
- name: Generate Artifacts
|
||||||
|
|
|
||||||
7
.gitignore
vendored
7
.gitignore
vendored
|
|
@ -93,3 +93,10 @@ build
|
||||||
GPATH
|
GPATH
|
||||||
GRTAGS
|
GRTAGS
|
||||||
GTAGS
|
GTAGS
|
||||||
|
|
||||||
|
# Zig programming language
|
||||||
|
zig-cache/
|
||||||
|
zig-out/
|
||||||
|
build/
|
||||||
|
build-*/
|
||||||
|
docgen_tmp/
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ Some people ported raylib to other languages in form of bindings or wrappers to
|
||||||
| raylib-ruby-ffi | 2.0 | [Ruby](https://www.ruby-lang.org/en/) | https://github.com/D3nX/raylib-ruby-ffi |
|
| raylib-ruby-ffi | 2.0 | [Ruby](https://www.ruby-lang.org/en/) | https://github.com/D3nX/raylib-ruby-ffi |
|
||||||
| raylib-ruby | 2.6 | [Ruby](https://www.ruby-lang.org/en/) | https://github.com/a0/raylib-ruby |
|
| raylib-ruby | 2.6 | [Ruby](https://www.ruby-lang.org/en/) | https://github.com/a0/raylib-ruby |
|
||||||
| raylib-mruby | 2.5-dev | [mruby](https://github.com/mruby/mruby) | https://github.com/lihaochen910/raylib-mruby |
|
| raylib-mruby | 2.5-dev | [mruby](https://github.com/mruby/mruby) | https://github.com/lihaochen910/raylib-mruby |
|
||||||
|
| pyraylib | 3.7 | [Python](https://www.python.org/) | https://github.com/Ho011/pyraylib |
|
||||||
| raylib-py | 2.0 | [Python](https://www.python.org/) | https://github.com/overdev/raylib-py |
|
| raylib-py | 2.0 | [Python](https://www.python.org/) | https://github.com/overdev/raylib-py |
|
||||||
| raylib-python-cffi | 3.7 | [Python](https://www.python.org/) | https://github.com/electronstudio/raylib-python-cffi |
|
| raylib-python-cffi | 3.7 | [Python](https://www.python.org/) | https://github.com/electronstudio/raylib-python-cffi |
|
||||||
| raylib-py-ctbg | 2.6 | [Python](https://www.python.org/) | https://github.com/overdev/raylib-py-ctbg |
|
| raylib-py-ctbg | 2.6 | [Python](https://www.python.org/) | https://github.com/overdev/raylib-py-ctbg |
|
||||||
|
|
@ -93,12 +94,13 @@ Some people ported raylib to other languages in form of bindings or wrappers to
|
||||||
| raylib-smallBasic | 3.1-dev | [SmallBASIC](https://github.com/smallbasic/SmallBASIC) | https://github.com/smallbasic/smallbasic.plugins/tree/master/raylib |
|
| raylib-smallBasic | 3.1-dev | [SmallBASIC](https://github.com/smallbasic/SmallBASIC) | https://github.com/smallbasic/smallbasic.plugins/tree/master/raylib |
|
||||||
| raylib-ats2 | 3.0 | [ATS2](http://www.ats-lang.org/) | https://github.com/mephistopheles-8/raylib-ats2 |
|
| raylib-ats2 | 3.0 | [ATS2](http://www.ats-lang.org/) | https://github.com/mephistopheles-8/raylib-ats2 |
|
||||||
| raylib-beef | 3.0 | [Beef](https://www.beeflang.org/) | https://github.com/M0n7y5/raylib-beef |
|
| raylib-beef | 3.0 | [Beef](https://www.beeflang.org/) | https://github.com/M0n7y5/raylib-beef |
|
||||||
| raylib-swift | 3.5 | [Swift](https://swift.org/) | https://github.com/conifer-dev/raylib-swift |
|
| raylib-swift | 3.7 | [Swift](https://swift.org/) | https://github.com/STREGAsGate/Raylib |
|
||||||
| raylib-never | 3.0 | [Never](https://github.com/never-lang/never) | https://github.com/never-lang/raylib-never |
|
| raylib-never | 3.0 | [Never](https://github.com/never-lang/never) | https://github.com/never-lang/raylib-never |
|
||||||
| hb-raylib | 3.5 | [Harbour](https://harbour.github.io) | https://github.com/MarcosLeonardoMendezGerencir/hb-raylib |
|
| hb-raylib | 3.5 | [Harbour](https://harbour.github.io) | https://github.com/MarcosLeonardoMendezGerencir/hb-raylib |
|
||||||
| Relib | 3.5 | [ReCT](https://github.com/RedCubeDev-ByteSpace/ReCT) | https://github.com/RedCubeDev-ByteSpace/Relib |
|
| Relib | 3.5 | [ReCT](https://github.com/RedCubeDev-ByteSpace/ReCT) | https://github.com/RedCubeDev-ByteSpace/Relib |
|
||||||
| rayex | 3.7 | [elixir](https://elixir-lang.org/) | https://github.com/shiryel/rayex |
|
| rayex | 3.7 | [elixir](https://elixir-lang.org/) | https://github.com/shiryel/rayex |
|
||||||
| raylib.cbl | 2.0 | [COBOL](https://en.wikipedia.org/wiki/COBOL) | *[code examples](https://github.com/Martinfx/Cobol/tree/master/OpenCobol/Games/raylib)* |
|
| raylib.cbl | 2.0 | [COBOL](https://en.wikipedia.org/wiki/COBOL) | *[code examples](https://github.com/Martinfx/Cobol/tree/master/OpenCobol/Games/raylib)* |
|
||||||
|
| kaylib | 3.7 | [Kotlin/native](https://kotlinlang.org) | https://github.com/electronstudio/kaylib |
|
||||||
|
|
||||||
### Utility Wrapers
|
### Utility Wrapers
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,9 @@ endif()
|
||||||
option(INCLUDE_EVERYTHING "Include everything disabled by default (for CI usage" OFF)
|
option(INCLUDE_EVERYTHING "Include everything disabled by default (for CI usage" OFF)
|
||||||
set(OFF ${INCLUDE_EVERYTHING} CACHE INTERNAL "Replace any OFF by default with \${OFF} to have it covered by this option")
|
set(OFF ${INCLUDE_EVERYTHING} CACHE INTERNAL "Replace any OFF by default with \${OFF} to have it covered by this option")
|
||||||
|
|
||||||
# core.c
|
# rcore.c
|
||||||
cmake_dependent_option(SUPPORT_CAMERA_SYSTEM "Provide camera module (camera.h) with multiple predefined cameras: free, 1st/3rd person, orbital" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_CAMERA_SYSTEM "Provide camera module (rcamera.h) with multiple predefined cameras: free, 1st/3rd person, orbital" ON CUSTOMIZE_BUILD ON)
|
||||||
cmake_dependent_option(SUPPORT_GESTURES_SYSTEM "Gestures module is included (gestures.h) to support gestures detection: tap, hold, swipe, drag" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_GESTURES_SYSTEM "Gestures module is included (rgestures.h) to support gestures detection: tap, hold, swipe, drag" ON CUSTOMIZE_BUILD ON)
|
||||||
cmake_dependent_option(SUPPORT_MOUSE_GESTURES "Mouse gestures are directly mapped like touches and processed by gestures system" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_MOUSE_GESTURES "Mouse gestures are directly mapped like touches and processed by gestures system" ON CUSTOMIZE_BUILD ON)
|
||||||
cmake_dependent_option(SUPPORT_SSH_KEYBOARD_RPI "Reconfigure standard input to receive key inputs, works with SSH connection" OFF CUSTOMIZE_BUILD OFF)
|
cmake_dependent_option(SUPPORT_SSH_KEYBOARD_RPI "Reconfigure standard input to receive key inputs, works with SSH connection" OFF CUSTOMIZE_BUILD OFF)
|
||||||
cmake_dependent_option(SUPPORT_DEFAULT_FONT "Default font is loaded on window initialization to be available for the user to render simple text. If enabled, uses external module functions to load default raylib font (module: text)" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_DEFAULT_FONT "Default font is loaded on window initialization to be available for the user to render simple text. If enabled, uses external module functions to load default raylib font (module: text)" ON CUSTOMIZE_BUILD ON)
|
||||||
|
|
@ -41,10 +41,10 @@ cmake_dependent_option(SUPPORT_WINMM_HIGHRES_TIMER "Setting a higher resolution
|
||||||
cmake_dependent_option(SUPPORT_DATA_STORAGE "Support for persistent data storage" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_DATA_STORAGE "Support for persistent data storage" ON CUSTOMIZE_BUILD ON)
|
||||||
cmake_dependent_option(SUPPORT_COMPRESSION_API "Support for compression API" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_COMPRESSION_API "Support for compression API" ON CUSTOMIZE_BUILD ON)
|
||||||
|
|
||||||
# shapes.c
|
# rshapes.c
|
||||||
cmake_dependent_option(SUPPORT_QUADS_DRAW_MODE "Use QUADS instead of TRIANGLES for drawing when possible. Some lines-based shapes could still use lines" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_QUADS_DRAW_MODE "Use QUADS instead of TRIANGLES for drawing when possible. Some lines-based shapes could still use lines" ON CUSTOMIZE_BUILD ON)
|
||||||
|
|
||||||
# textures.c
|
# rtextures.c
|
||||||
cmake_dependent_option(SUPPORT_IMAGE_EXPORT "Support image exporting to file" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_IMAGE_EXPORT "Support image exporting to file" ON CUSTOMIZE_BUILD ON)
|
||||||
cmake_dependent_option(SUPPORT_IMAGE_GENERATION "Support procedural image generation functionality (gradient, spot, perlin-noise, cellular)" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_IMAGE_GENERATION "Support procedural image generation functionality (gradient, spot, perlin-noise, cellular)" ON CUSTOMIZE_BUILD ON)
|
||||||
cmake_dependent_option(SUPPORT_IMAGE_MANIPULATION "Support multiple image editing functions to scale, adjust colors, flip, draw on images, crop... If not defined only three image editing functions supported: ImageFormat(), ImageAlphaMask(), ImageToPOT()" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_IMAGE_MANIPULATION "Support multiple image editing functions to scale, adjust colors, flip, draw on images, crop... If not defined only three image editing functions supported: ImageFormat(), ImageAlphaMask(), ImageToPOT()" ON CUSTOMIZE_BUILD ON)
|
||||||
|
|
@ -61,12 +61,12 @@ cmake_dependent_option(SUPPORT_FILEFORMAT_PSD "Support loading PSD as textures"
|
||||||
cmake_dependent_option(SUPPORT_FILEFORMAT_PKM "Support loading PKM as textures" ${OFF} CUSTOMIZE_BUILD OFF)
|
cmake_dependent_option(SUPPORT_FILEFORMAT_PKM "Support loading PKM as textures" ${OFF} CUSTOMIZE_BUILD OFF)
|
||||||
cmake_dependent_option(SUPPORT_FILEFORMAT_PVR "Support loading PVR as textures" ${OFF} CUSTOMIZE_BUILD OFF)
|
cmake_dependent_option(SUPPORT_FILEFORMAT_PVR "Support loading PVR as textures" ${OFF} CUSTOMIZE_BUILD OFF)
|
||||||
|
|
||||||
# text.c
|
# rtext.c
|
||||||
cmake_dependent_option(SUPPORT_FILEFORMAT_FNT "Support loading fonts in FNT format" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_FILEFORMAT_FNT "Support loading fonts in FNT format" ON CUSTOMIZE_BUILD ON)
|
||||||
cmake_dependent_option(SUPPORT_FILEFORMAT_TTF "Support loading font in TTF/OTF format" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_FILEFORMAT_TTF "Support loading font in TTF/OTF format" ON CUSTOMIZE_BUILD ON)
|
||||||
cmake_dependent_option(SUPPORT_TEXT_MANIPULATION "Support text manipulation functions" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_TEXT_MANIPULATION "Support text manipulation functions" ON CUSTOMIZE_BUILD ON)
|
||||||
|
|
||||||
# models.c
|
# rmodels.c
|
||||||
cmake_dependent_option(SUPPORT_MESH_GENERATION "Support procedural mesh generation functions, uses external par_shapes.h library. NOTE: Some generated meshes DO NOT include generated texture coordinates" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_MESH_GENERATION "Support procedural mesh generation functions, uses external par_shapes.h library. NOTE: Some generated meshes DO NOT include generated texture coordinates" ON CUSTOMIZE_BUILD ON)
|
||||||
cmake_dependent_option(SUPPORT_FILEFORMAT_OBJ "Support loading OBJ file format" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_FILEFORMAT_OBJ "Support loading OBJ file format" ON CUSTOMIZE_BUILD ON)
|
||||||
cmake_dependent_option(SUPPORT_FILEFORMAT_MTL "Support loading MTL file format" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_FILEFORMAT_MTL "Support loading MTL file format" ON CUSTOMIZE_BUILD ON)
|
||||||
|
|
|
||||||
10
HISTORY.md
10
HISTORY.md
|
|
@ -33,7 +33,7 @@ Lots of code changes and lot of testing have concluded in this amazing new rayli
|
||||||
notes on raylib 1.2
|
notes on raylib 1.2
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
On September 2014, after 5 month of raylib 1.1 release, it comes raylib 1.2. Again, this version presents a complete internal redesign of [core](https://github.com/raysan5/raylib/blob/master/src/core.c) module to support two new platforms: [Android](http://www.android.com/) and [Raspberry Pi](http://www.raspberrypi.org/).
|
On September 2014, after 5 month of raylib 1.1 release, it comes raylib 1.2. Again, this version presents a complete internal redesign of [core](https://github.com/raysan5/raylib/blob/master/src/rcore.c) module to support two new platforms: [Android](http://www.android.com/) and [Raspberry Pi](http://www.raspberrypi.org/).
|
||||||
|
|
||||||
It's been some month of really hard work to accomodate raylib to those new platforms while keeping it easy for the users. On Android, raylib manages internally the activity cicle, as well as the inputs; on Raspberry Pi, a complete raw input system has been written from scratch.
|
It's been some month of really hard work to accomodate raylib to those new platforms while keeping it easy for the users. On Android, raylib manages internally the activity cicle, as well as the inputs; on Raspberry Pi, a complete raw input system has been written from scratch.
|
||||||
|
|
||||||
|
|
@ -54,9 +54,9 @@ On September 2015, after 1 year of raylib 1.2 release, arrives raylib 1.3. This
|
||||||
|
|
||||||
- Textures module has grown to support most of the internal texture formats available in OpenGL (RGB565, RGB888, RGBA5551, RGBA4444, etc.), including compressed texture formats (DXT, ETC1, ETC2, ASTC, PVRT); raylib 1.3 can load .dds, .pkm, .ktx, .astc and .pvr files.
|
- Textures module has grown to support most of the internal texture formats available in OpenGL (RGB565, RGB888, RGBA5551, RGBA4444, etc.), including compressed texture formats (DXT, ETC1, ETC2, ASTC, PVRT); raylib 1.3 can load .dds, .pkm, .ktx, .astc and .pvr files.
|
||||||
|
|
||||||
- A brand new [camera](https://github.com/raysan5/raylib/blob/master/src/camera.c) module offers to the user multiple preconfigured ready-to-use camera systems (free camera, 1st person, 3rd person). Camera modes are very easy to use, just check examples: [core_3d_camera_free.c](https://github.com/raysan5/raylib/blob/master/examples/core_3d_camera_free.c) and [core_3d_camera_first_person.c](https://github.com/raysan5/raylib/blob/master/examples/core_3d_camera_first_person.c).
|
- A brand new [camera](https://github.com/raysan5/raylib/blob/master/src/rcamera.c) module offers to the user multiple preconfigured ready-to-use camera systems (free camera, 1st person, 3rd person). Camera modes are very easy to use, just check examples: [core_3d_camera_free.c](https://github.com/raysan5/raylib/blob/master/examples/core_3d_camera_free.c) and [core_3d_camera_first_person.c](https://github.com/raysan5/raylib/blob/master/examples/core_3d_camera_first_person.c).
|
||||||
|
|
||||||
- New [gestures](https://github.com/raysan5/raylib/blob/master/src/gestures.h) module simplifies gestures detection on Android and HTML5 programs.
|
- New [gestures](https://github.com/raysan5/raylib/blob/master/src/rgestures.h) module simplifies gestures detection on Android and HTML5 programs.
|
||||||
|
|
||||||
- [raygui](https://github.com/raysan5/raylib/blob/master/src/raygui.h), the new immediate-mode GUI module offers a set of functions to create simple user interfaces, primary intended for tools development. It's still in experimental state but already fully functional.
|
- [raygui](https://github.com/raysan5/raylib/blob/master/src/raygui.h), the new immediate-mode GUI module offers a set of functions to create simple user interfaces, primary intended for tools development. It's still in experimental state but already fully functional.
|
||||||
|
|
||||||
|
|
@ -77,7 +77,7 @@ On February 2016, after 4 months of raylib 1.3 release, it comes raylib 1.4. For
|
||||||
|
|
||||||
- [raymath](https://github.com/raysan5/raylib/blob/master/src/raymath.h) module has been reviewed; some bugs have been solved and the module has been converted to a header-only file for easier portability, optionally, functions can also be used as inline.
|
- [raymath](https://github.com/raysan5/raylib/blob/master/src/raymath.h) module has been reviewed; some bugs have been solved and the module has been converted to a header-only file for easier portability, optionally, functions can also be used as inline.
|
||||||
|
|
||||||
- [gestures](https://github.com/raysan5/raylib/blob/master/src/gestures.c) module has redesigned and simplified, now it can process touch events from any source, including mouse. This way, gestures system can be used on any platform providing an unified way to work with inputs and allowing the user to create multiplatform games with only one source code.
|
- [gestures](https://github.com/raysan5/raylib/blob/master/src/rgestures.c) module has redesigned and simplified, now it can process touch events from any source, including mouse. This way, gestures system can be used on any platform providing an unified way to work with inputs and allowing the user to create multiplatform games with only one source code.
|
||||||
|
|
||||||
- Raspberry Pi input system has been redesigned to better read raw inputs using generic Linux event handlers (keyboard:`stdin`, mouse:`/dev/input/mouse0`, gamepad:`/dev/input/js0`). Gamepad support has also been added (experimental).
|
- Raspberry Pi input system has been redesigned to better read raw inputs using generic Linux event handlers (keyboard:`stdin`, mouse:`/dev/input/mouse0`, gamepad:`/dev/input/js0`). Gamepad support has also been added (experimental).
|
||||||
|
|
||||||
|
|
@ -106,7 +106,7 @@ On July 2016, after 5 months of raylib 1.4 release, arrives raylib 1.5. This new
|
||||||
|
|
||||||
- Audio chiptunese support and mixing channels: Added support for module audio music (.xm, .mod) loading and playing. Multiple mixing channels are now also supported. All this features thanks to the amazing work of @kd7tck.
|
- Audio chiptunese support and mixing channels: Added support for module audio music (.xm, .mod) loading and playing. Multiple mixing channels are now also supported. All this features thanks to the amazing work of @kd7tck.
|
||||||
|
|
||||||
Other additions include a [2D camera system](https://github.com/raysan5/raylib/blob/master/examples/core_2d_camera.c), render textures for offline render (and most comprehensive [postprocessing](https://github.com/raysan5/raylib/blob/master/examples/shaders_postprocessing.c)) or support for legacy OpenGL 2.1 on desktop platforms.
|
Other additions include a [2D camera system](https://github.com/raysan5/raylib/blob/master/examples/core_2d_rcamera.c), render textures for offline render (and most comprehensive [postprocessing](https://github.com/raysan5/raylib/blob/master/examples/shaders_postprocessing.c)) or support for legacy OpenGL 2.1 on desktop platforms.
|
||||||
|
|
||||||
This new version is so massive that is difficult to list all the improvements, most of raylib modules have been reviewed and [rlgl](https://github.com/raysan5/raylib/blob/master/src/rlgl.c) module has been completely redesigned to accomodate to new material-lighting systems and stereo rendering. You can check [CHANGELOG](https://github.com/raysan5/raylib/blob/master/CHANGELOG) file for a more detailed list of changes.
|
This new version is so massive that is difficult to list all the improvements, most of raylib modules have been reviewed and [rlgl](https://github.com/raysan5/raylib/blob/master/src/rlgl.c) module has been completely redesigned to accomodate to new material-lighting systems and stereo rendering. You can check [CHANGELOG](https://github.com/raysan5/raylib/blob/master/CHANGELOG) file for a more detailed list of changes.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,8 @@ if (${PLATFORM} MATCHES "Desktop")
|
||||||
endif ()
|
endif ()
|
||||||
elseif (WIN32)
|
elseif (WIN32)
|
||||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||||
set(LIBS_PRIVATE ${LIBS_PRIVATE} winmm)
|
find_package(OpenGL QUIET)
|
||||||
|
set(LIBS_PRIVATE ${OPENGL_LIBRARIES} winmm)
|
||||||
else ()
|
else ()
|
||||||
find_library(pthread NAMES pthread)
|
find_library(pthread NAMES pthread)
|
||||||
find_package(OpenGL QUIET)
|
find_package(OpenGL QUIET)
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,8 @@ if (${PLATFORM} MATCHES "Android")
|
||||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_obj_viewer.c)
|
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_obj_viewer.c)
|
||||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_animation.c)
|
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_animation.c)
|
||||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_first_person_maze.c)
|
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_first_person_maze.c)
|
||||||
|
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_magicavoxel_loading.c)
|
||||||
|
|
||||||
|
|
||||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/shaders/shaders_custom_uniform.c)
|
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/shaders/shaders_custom_uniform.c)
|
||||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/shaders/shaders_model_shader.c)
|
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/shaders/shaders_model_shader.c)
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
# Define required raylib variables
|
# Define required raylib variables
|
||||||
PROJECT_NAME ?= raylib_examples
|
PROJECT_NAME ?= raylib_examples
|
||||||
RAYLIB_VERSION ?= 3.8.0
|
RAYLIB_VERSION ?= 4.0.0
|
||||||
RAYLIB_PATH ?= ..
|
RAYLIB_PATH ?= ..
|
||||||
|
|
||||||
# Define default options
|
# Define default options
|
||||||
|
|
@ -185,6 +185,12 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
|
||||||
MAKE = mingw32-make
|
MAKE = mingw32-make
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
ifeq ($(PLATFORM),PLATFORM_ANDROID)
|
||||||
|
MAKE = mingw32-make
|
||||||
|
endif
|
||||||
|
ifeq ($(PLATFORM),PLATFORM_WEB)
|
||||||
|
MAKE = mingw32-make
|
||||||
|
endif
|
||||||
|
|
||||||
# Define compiler flags:
|
# Define compiler flags:
|
||||||
# -O1 defines optimization level
|
# -O1 defines optimization level
|
||||||
|
|
@ -229,32 +235,6 @@ endif
|
||||||
ifeq ($(PLATFORM),PLATFORM_DRM)
|
ifeq ($(PLATFORM),PLATFORM_DRM)
|
||||||
CFLAGS += -std=gnu99 -DEGL_NO_X11
|
CFLAGS += -std=gnu99 -DEGL_NO_X11
|
||||||
endif
|
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 ASYNCIFY # lets synchronous C/C++ code interact with asynchronous JS
|
|
||||||
# -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)
|
|
||||||
# --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
|
|
||||||
CFLAGS += -s USE_GLFW=3 -s ASYNCIFY -s TOTAL_MEMORY=67108864 -s FORCE_FILESYSTEM=1 --preload-file $(dir $<)resources@resources
|
|
||||||
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
# Define a custom shell .html and output extension
|
|
||||||
CFLAGS += --shell-file $(RAYLIB_PATH)/src/shell.html
|
|
||||||
EXT = .html
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Define include paths for required headers
|
# Define include paths for required headers
|
||||||
# NOTE: Some external/extras libraries could be required (stb, physac, easings...)
|
# NOTE: Some external/extras libraries could be required (stb, physac, easings...)
|
||||||
|
|
@ -303,7 +283,32 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
|
||||||
LDFLAGS = -L. -L$(RAYLIB_INSTALL_PATH) -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)
|
LDFLAGS = -L. -L$(RAYLIB_INSTALL_PATH) -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)
|
||||||
endif
|
endif
|
||||||
endif
|
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) (67108864 = 64MB)
|
||||||
|
# -s USE_PTHREADS=1 # multithreading support
|
||||||
|
# -s WASM=0 # disable Web Assembly, emitted by default
|
||||||
|
# -s ASYNCIFY # lets synchronous C/C++ code interact with asynchronous JS
|
||||||
|
# -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)
|
||||||
|
# --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 += -s USE_GLFW=3 -s ASYNCIFY -s TOTAL_MEMORY=67108864 -s FORCE_FILESYSTEM=1 --preload-file $(dir $<)resources@resources
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
# Define a custom shell .html and output extension
|
||||||
|
LDFLAGS += --shell-file $(RAYLIB_PATH)/src/shell.html
|
||||||
|
EXT = .html
|
||||||
|
endif
|
||||||
ifeq ($(PLATFORM),PLATFORM_RPI)
|
ifeq ($(PLATFORM),PLATFORM_RPI)
|
||||||
LDFLAGS += -L/opt/vc/lib
|
LDFLAGS += -L/opt/vc/lib
|
||||||
endif
|
endif
|
||||||
|
|
@ -466,7 +471,8 @@ MODELS = \
|
||||||
models/models_skybox \
|
models/models_skybox \
|
||||||
models/models_yaw_pitch_roll \
|
models/models_yaw_pitch_roll \
|
||||||
models/models_heightmap \
|
models/models_heightmap \
|
||||||
models/models_waving_cubes
|
models/models_waving_cubes \
|
||||||
|
models/models_magicavoxel_loading
|
||||||
|
|
||||||
SHADERS = \
|
SHADERS = \
|
||||||
shaders/shaders_model_shader \
|
shaders/shaders_model_shader \
|
||||||
|
|
|
||||||
151
examples/models/models_magicavoxel_loading.c
Normal file
151
examples/models/models_magicavoxel_loading.c
Normal file
|
|
@ -0,0 +1,151 @@
|
||||||
|
/*******************************************************************************************
|
||||||
|
*
|
||||||
|
* raylib [models] example - magicavoxel loader and viewer
|
||||||
|
*
|
||||||
|
* This example has been created using raylib 3.8 (www.raylib.com)
|
||||||
|
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||||
|
*
|
||||||
|
* Example contributed by Johann Nadalutti
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021 Johann Nadalutti
|
||||||
|
*
|
||||||
|
********************************************************************************************/
|
||||||
|
|
||||||
|
#include "raylib.h"
|
||||||
|
#include "raymath.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
// VOX Files to load and view
|
||||||
|
|
||||||
|
#define NUM_VOX_FILES 3
|
||||||
|
|
||||||
|
const char* szVoxFiles[] = {
|
||||||
|
"resources/vox/chr_knight.vox",
|
||||||
|
"resources/vox/chr_sword.vox",
|
||||||
|
"resources/vox/monu9.vox"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
// Initialization
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
const int screenWidth = 800;
|
||||||
|
const int screenHeight = 450;
|
||||||
|
|
||||||
|
InitWindow(screenWidth, screenHeight, "raylib [models] example - magicavoxel loading");
|
||||||
|
|
||||||
|
// Load MagicaVoxel files
|
||||||
|
Model models[NUM_VOX_FILES] = { 0 };
|
||||||
|
|
||||||
|
for (int i = 0; i < NUM_VOX_FILES; i++)
|
||||||
|
{
|
||||||
|
// Load MagicaVoxel File and build model
|
||||||
|
double t0, t1;
|
||||||
|
t0 = GetTime() * 1000.0;
|
||||||
|
|
||||||
|
models[i] = LoadModel(szVoxFiles[i]);
|
||||||
|
|
||||||
|
t1 = GetTime() * 1000.0;
|
||||||
|
TraceLog(LOG_INFO, TextFormat("Vox <%s> loaded in %f ms", GetFileName(szVoxFiles[i]), t1 - t0));
|
||||||
|
|
||||||
|
//Compute model's center matrix
|
||||||
|
BoundingBox bb = GetModelBoundingBox(models[i]);
|
||||||
|
Vector3 center;
|
||||||
|
center.x = bb.min.x + (((bb.max.x - bb.min.x) / 2));
|
||||||
|
center.z = bb.min.z + (((bb.max.z - bb.min.z) / 2));
|
||||||
|
|
||||||
|
Matrix matP = MatrixTranslate(-center.x, 0, -center.z);
|
||||||
|
models[i].transform = matP;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Define the camera to look into our 3d world
|
||||||
|
Camera camera = { { 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 };
|
||||||
|
|
||||||
|
// Model drawing position
|
||||||
|
Vector3 position = { 0.0f, 0.0f, 0.0f };
|
||||||
|
|
||||||
|
int currentModel = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SetCameraMode(camera, CAMERA_ORBITAL); // Set a orbital camera mode
|
||||||
|
|
||||||
|
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
// Main game loop
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||||
|
{
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
// Update
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
UpdateCamera(&camera); // Update internal camera and our camera
|
||||||
|
|
||||||
|
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT))
|
||||||
|
{
|
||||||
|
currentModel = (currentModel + 1) % NUM_VOX_FILES; // Cycle between models
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsKeyPressed(KEY_RIGHT))
|
||||||
|
{
|
||||||
|
currentModel++;
|
||||||
|
if (currentModel >= NUM_VOX_FILES) currentModel = 0;
|
||||||
|
}
|
||||||
|
else if (IsKeyPressed(KEY_LEFT))
|
||||||
|
{
|
||||||
|
currentModel--;
|
||||||
|
if (currentModel < 0) currentModel = NUM_VOX_FILES - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Draw
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
BeginDrawing();
|
||||||
|
|
||||||
|
ClearBackground(RAYWHITE);
|
||||||
|
|
||||||
|
//Display model
|
||||||
|
BeginMode3D(camera);
|
||||||
|
|
||||||
|
Vector3 rotAxis = { 1,0,0 };
|
||||||
|
Vector3 scale = { 1,1,1 };
|
||||||
|
|
||||||
|
|
||||||
|
DrawModelEx(models[currentModel], position, rotAxis, 0, scale, WHITE);
|
||||||
|
//DrawModelWiresEx(models[currentModel], position, rotAxis, -90.0f, scale, BLACK);
|
||||||
|
|
||||||
|
DrawGrid(10, 1.0);
|
||||||
|
|
||||||
|
EndMode3D();
|
||||||
|
|
||||||
|
//Display debug infos
|
||||||
|
DrawRectangle(30, 400, 310, 30, Fade(SKYBLUE, 0.5f));
|
||||||
|
DrawRectangleLines(30, 400, 310, 30, Fade(DARKBLUE, 0.5f));
|
||||||
|
DrawText("MOUSE LEFT BUTTON to CYCLE VOX MODELS", 40, 410, 10, BLUE);
|
||||||
|
|
||||||
|
DrawText(GetFileName(szVoxFiles[currentModel]), 100, 10, 20, DARKBLUE);
|
||||||
|
|
||||||
|
EndDrawing();
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
}
|
||||||
|
|
||||||
|
// De-Initialization
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Unload models data (GPU VRAM)
|
||||||
|
for (int i = 0; i < NUM_VOX_FILES; i++) UnloadModel(models[i]);
|
||||||
|
|
||||||
|
CloseWindow(); // Close window and OpenGL context
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BIN
examples/models/resources/vox/chr_knight.vox
Normal file
BIN
examples/models/resources/vox/chr_knight.vox
Normal file
Binary file not shown.
BIN
examples/models/resources/vox/chr_sword.vox
Normal file
BIN
examples/models/resources/vox/chr_sword.vox
Normal file
Binary file not shown.
BIN
examples/models/resources/vox/monu9.vox
Normal file
BIN
examples/models/resources/vox/monu9.vox
Normal file
Binary file not shown.
|
|
@ -454,16 +454,16 @@ void DrawTextCodepoint3D(Font font, int codepoint, Vector3 position, float fontS
|
||||||
|
|
||||||
// Character destination rectangle on screen
|
// Character destination rectangle on screen
|
||||||
// NOTE: We consider charsPadding on drawing
|
// NOTE: We consider charsPadding on drawing
|
||||||
position.x += (float)(font.chars[index].offsetX - font.charsPadding)/(float)font.baseSize*scale;
|
position.x += (float)(font.glyphs[index].offsetX - font.glyphPadding)/(float)font.baseSize*scale;
|
||||||
position.z += (float)(font.chars[index].offsetY - font.charsPadding)/(float)font.baseSize*scale;
|
position.z += (float)(font.glyphs[index].offsetY - font.glyphPadding)/(float)font.baseSize*scale;
|
||||||
|
|
||||||
// Character source rectangle from font texture atlas
|
// Character source rectangle from font texture atlas
|
||||||
// NOTE: We consider chars padding when drawing, it could be required for outline/glow shader effects
|
// NOTE: We consider chars padding when drawing, it could be required for outline/glow shader effects
|
||||||
Rectangle srcRec = { font.recs[index].x - (float)font.charsPadding, font.recs[index].y - (float)font.charsPadding,
|
Rectangle srcRec = { font.recs[index].x - (float)font.glyphPadding, font.recs[index].y - (float)font.glyphPadding,
|
||||||
font.recs[index].width + 2.0f*font.charsPadding, font.recs[index].height + 2.0f*font.charsPadding };
|
font.recs[index].width + 2.0f*font.glyphPadding, font.recs[index].height + 2.0f*font.glyphPadding };
|
||||||
|
|
||||||
float width = (float)(font.recs[index].width + 2.0f*font.charsPadding)/(float)font.baseSize*scale;
|
float width = (float)(font.recs[index].width + 2.0f*font.glyphPadding)/(float)font.baseSize*scale;
|
||||||
float height = (float)(font.recs[index].height + 2.0f*font.charsPadding)/(float)font.baseSize*scale;
|
float height = (float)(font.recs[index].height + 2.0f*font.glyphPadding)/(float)font.baseSize*scale;
|
||||||
|
|
||||||
if (font.texture.id > 0)
|
if (font.texture.id > 0)
|
||||||
{
|
{
|
||||||
|
|
@ -477,16 +477,11 @@ void DrawTextCodepoint3D(Font font, int codepoint, Vector3 position, float fontS
|
||||||
const float tw = (srcRec.x+srcRec.width)/font.texture.width;
|
const float tw = (srcRec.x+srcRec.width)/font.texture.width;
|
||||||
const float th = (srcRec.y+srcRec.height)/font.texture.height;
|
const float th = (srcRec.y+srcRec.height)/font.texture.height;
|
||||||
|
|
||||||
if (SHOW_LETTER_BOUNDRY)
|
if (SHOW_LETTER_BOUNDRY) DrawCubeWiresV((Vector3){ position.x + width/2, position.y, position.z + height/2}, (Vector3){ width, LETTER_BOUNDRY_SIZE, height }, LETTER_BOUNDRY_COLOR);
|
||||||
DrawCubeWiresV((Vector3){ position.x + width/2, position.y, position.z + height/2}, (Vector3){ width, LETTER_BOUNDRY_SIZE, height }, LETTER_BOUNDRY_COLOR);
|
|
||||||
|
|
||||||
#if defined(RAYLIB_NEW_RLGL)
|
|
||||||
rlCheckRenderBatchLimit(4 + 4*backface);
|
rlCheckRenderBatchLimit(4 + 4*backface);
|
||||||
rlSetTexture(font.texture.id);
|
rlSetTexture(font.texture.id);
|
||||||
#else
|
|
||||||
if (rlCheckBufferLimit(4 + 4*backface)) rlglDraw();
|
|
||||||
rlEnableTexture(font.texture.id);
|
|
||||||
#endif
|
|
||||||
rlPushMatrix();
|
rlPushMatrix();
|
||||||
rlTranslatef(position.x, position.y, position.z);
|
rlTranslatef(position.x, position.y, position.z);
|
||||||
|
|
||||||
|
|
@ -512,11 +507,7 @@ void DrawTextCodepoint3D(Font font, int codepoint, Vector3 position, float fontS
|
||||||
rlEnd();
|
rlEnd();
|
||||||
rlPopMatrix();
|
rlPopMatrix();
|
||||||
|
|
||||||
#if defined(RAYLIB_NEW_RLGL)
|
|
||||||
rlSetTexture(0);
|
rlSetTexture(0);
|
||||||
#else
|
|
||||||
rlDisableTexture();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -554,8 +545,8 @@ void DrawText3D(Font font, const char *text, Vector3 position, float fontSize, f
|
||||||
DrawTextCodepoint3D(font, codepoint, (Vector3){ position.x + textOffsetX, position.y, position.z + textOffsetY }, fontSize, backface, tint);
|
DrawTextCodepoint3D(font, codepoint, (Vector3){ position.x + textOffsetX, position.y, position.z + textOffsetY }, fontSize, backface, tint);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (font.chars[index].advanceX == 0) textOffsetX += (float)(font.recs[index].width + fontSpacing)/(float)font.baseSize*scale;
|
if (font.glyphs[index].advanceX == 0) textOffsetX += (float)(font.recs[index].width + fontSpacing)/(float)font.baseSize*scale;
|
||||||
else textOffsetX += (float)(font.chars[index].advanceX + fontSpacing)/(float)font.baseSize*scale;
|
else textOffsetX += (float)(font.glyphs[index].advanceX + fontSpacing)/(float)font.baseSize*scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
i += codepointByteCount; // Move text bytes counter to next codepoint
|
i += codepointByteCount; // Move text bytes counter to next codepoint
|
||||||
|
|
@ -592,8 +583,8 @@ Vector3 MeasureText3D(Font font, const char* text, float fontSize, float fontSpa
|
||||||
|
|
||||||
if (letter != '\n')
|
if (letter != '\n')
|
||||||
{
|
{
|
||||||
if (font.chars[index].advanceX != 0) textWidth += (font.chars[index].advanceX+fontSpacing)/(float)font.baseSize*scale;
|
if (font.glyphs[index].advanceX != 0) textWidth += (font.glyphs[index].advanceX+fontSpacing)/(float)font.baseSize*scale;
|
||||||
else textWidth += (font.recs[index].width + font.chars[index].offsetX)/(float)font.baseSize*scale;
|
else textWidth += (font.recs[index].width + font.glyphs[index].offsetX)/(float)font.baseSize*scale;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -670,8 +661,8 @@ void DrawTextWave3D(Font font, const char *text, Vector3 position, float fontSiz
|
||||||
DrawTextCodepoint3D(font, codepoint, (Vector3){ pos.x + textOffsetX, pos.y, pos.z + textOffsetY }, fontSize, backface, tint);
|
DrawTextCodepoint3D(font, codepoint, (Vector3){ pos.x + textOffsetX, pos.y, pos.z + textOffsetY }, fontSize, backface, tint);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (font.chars[index].advanceX == 0) textOffsetX += (float)(font.recs[index].width + fontSpacing)/(float)font.baseSize*scale;
|
if (font.glyphs[index].advanceX == 0) textOffsetX += (float)(font.recs[index].width + fontSpacing)/(float)font.baseSize*scale;
|
||||||
else textOffsetX += (float)(font.chars[index].advanceX + fontSpacing)/(float)font.baseSize*scale;
|
else textOffsetX += (float)(font.glyphs[index].advanceX + fontSpacing)/(float)font.baseSize*scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
i += codepointByteCount; // Move text bytes counter to next codepoint
|
i += codepointByteCount; // Move text bytes counter to next codepoint
|
||||||
|
|
@ -714,8 +705,8 @@ Vector3 MeasureTextWave3D(Font font, const char* text, float fontSize, float fon
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (font.chars[index].advanceX != 0) textWidth += (font.chars[index].advanceX+fontSpacing)/(float)font.baseSize*scale;
|
if (font.glyphs[index].advanceX != 0) textWidth += (font.glyphs[index].advanceX+fontSpacing)/(float)font.baseSize*scale;
|
||||||
else textWidth += (font.recs[index].width + font.chars[index].offsetX)/(float)font.baseSize*scale;
|
else textWidth += (font.recs[index].width + font.glyphs[index].offsetX)/(float)font.baseSize*scale;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -39,24 +39,24 @@ int main(void)
|
||||||
// Default font generation from TTF font
|
// Default font generation from TTF font
|
||||||
Font fontDefault = { 0 };
|
Font fontDefault = { 0 };
|
||||||
fontDefault.baseSize = 16;
|
fontDefault.baseSize = 16;
|
||||||
fontDefault.charsCount = 95;
|
fontDefault.glyphCount = 95;
|
||||||
|
|
||||||
// Loading font data from memory data
|
// Loading font data from memory data
|
||||||
// Parameters > font size: 16, no chars array provided (0), chars count: 95 (autogenerate chars array)
|
// Parameters > font size: 16, no glyphs array provided (0), glyphs count: 95 (autogenerate chars array)
|
||||||
fontDefault.chars = LoadFontData(fileData, fileSize, 16, 0, 95, FONT_DEFAULT);
|
fontDefault.glyphs = LoadFontData(fileData, fileSize, 16, 0, 95, FONT_DEFAULT);
|
||||||
// Parameters > chars count: 95, font size: 16, chars padding in image: 4 px, pack method: 0 (default)
|
// Parameters > glyphs count: 95, font size: 16, glyphs padding in image: 4 px, pack method: 0 (default)
|
||||||
Image atlas = GenImageFontAtlas(fontDefault.chars, &fontDefault.recs, 95, 16, 4, 0);
|
Image atlas = GenImageFontAtlas(fontDefault.glyphs, &fontDefault.recs, 95, 16, 4, 0);
|
||||||
fontDefault.texture = LoadTextureFromImage(atlas);
|
fontDefault.texture = LoadTextureFromImage(atlas);
|
||||||
UnloadImage(atlas);
|
UnloadImage(atlas);
|
||||||
|
|
||||||
// SDF font generation from TTF font
|
// SDF font generation from TTF font
|
||||||
Font fontSDF = { 0 };
|
Font fontSDF = { 0 };
|
||||||
fontSDF.baseSize = 16;
|
fontSDF.baseSize = 16;
|
||||||
fontSDF.charsCount = 95;
|
fontSDF.glyphCount = 95;
|
||||||
// Parameters > font size: 16, no chars array provided (0), chars count: 0 (defaults to 95)
|
// Parameters > font size: 16, no glyphs array provided (0), glyphs count: 0 (defaults to 95)
|
||||||
fontSDF.chars = LoadFontData(fileData, fileSize, 16, 0, 0, FONT_SDF);
|
fontSDF.glyphs = LoadFontData(fileData, fileSize, 16, 0, 0, FONT_SDF);
|
||||||
// Parameters > chars count: 95, font size: 16, chars padding in image: 0 px, pack method: 1 (Skyline algorythm)
|
// Parameters > glyphs count: 95, font size: 16, glyphs padding in image: 0 px, pack method: 1 (Skyline algorythm)
|
||||||
atlas = GenImageFontAtlas(fontSDF.chars, &fontSDF.recs, 95, 16, 0, 1);
|
atlas = GenImageFontAtlas(fontSDF.glyphs, &fontSDF.recs, 95, 16, 0, 1);
|
||||||
fontSDF.texture = LoadTextureFromImage(atlas);
|
fontSDF.texture = LoadTextureFromImage(atlas);
|
||||||
UnloadImage(atlas);
|
UnloadImage(atlas);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -166,7 +166,7 @@ static void DrawTextBoxedSelectable(Font font, const char *text, Rectangle rec,
|
||||||
float glyphWidth = 0;
|
float glyphWidth = 0;
|
||||||
if (codepoint != '\n')
|
if (codepoint != '\n')
|
||||||
{
|
{
|
||||||
glyphWidth = (font.chars[index].advanceX == 0) ? font.recs[index].width*scaleFactor : font.chars[index].advanceX*scaleFactor;
|
glyphWidth = (font.glyphs[index].advanceX == 0) ? font.recs[index].width*scaleFactor : font.glyphs[index].advanceX*scaleFactor;
|
||||||
|
|
||||||
if (i + 1 < length) glyphWidth = glyphWidth + spacing;
|
if (i + 1 < length) glyphWidth = glyphWidth + spacing;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -277,8 +277,8 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
// Draw the info text below the main message
|
// Draw the info text below the main message
|
||||||
int size = (int)strlen(messages[message].text);
|
int size = (int)strlen(messages[message].text);
|
||||||
int len = GetCodepointsCount(messages[message].text);
|
int length = GetCodepointCount(messages[message].text);
|
||||||
const char *info = TextFormat("%s %u characters %i bytes", messages[message].language, len, size);
|
const char *info = TextFormat("%s %u characters %i bytes", messages[message].language, length, size);
|
||||||
sz = MeasureTextEx(GetFontDefault(), info, 10, 1.0f);
|
sz = MeasureTextEx(GetFontDefault(), info, 10, 1.0f);
|
||||||
Vector2 pos = { textRect.x + textRect.width - sz.x, msgRect.y + msgRect.height - sz.y - 2 };
|
Vector2 pos = { textRect.x + textRect.width - sz.x, msgRect.y + msgRect.height - sz.y - 2 };
|
||||||
DrawText(info, (int)pos.x, (int)pos.y, 10, RAYWHITE);
|
DrawText(info, (int)pos.x, (int)pos.y, 10, RAYWHITE);
|
||||||
|
|
@ -367,7 +367,7 @@ static void DrawTextBoxedSelectable(Font font, const char *text, Rectangle rec,
|
||||||
float glyphWidth = 0;
|
float glyphWidth = 0;
|
||||||
if (codepoint != '\n')
|
if (codepoint != '\n')
|
||||||
{
|
{
|
||||||
glyphWidth = (font.chars[index].advanceX == 0) ? font.recs[index].width*scaleFactor : font.chars[index].advanceX*scaleFactor;
|
glyphWidth = (font.glyphs[index].advanceX == 0) ? font.recs[index].width*scaleFactor : font.glyphs[index].advanceX*scaleFactor;
|
||||||
|
|
||||||
if (i + 1 < length) glyphWidth = glyphWidth + spacing;
|
if (i + 1 < length) glyphWidth = glyphWidth + spacing;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,8 @@ int main(void)
|
||||||
|
|
||||||
Image image = LoadImage("resources/raylib_logo.png"); // Loaded in CPU memory (RAM)
|
Image image = LoadImage("resources/raylib_logo.png"); // Loaded in CPU memory (RAM)
|
||||||
Texture2D texture = LoadTextureFromImage(image); // Image converted to texture, GPU memory (VRAM)
|
Texture2D texture = LoadTextureFromImage(image); // Image converted to texture, GPU memory (VRAM)
|
||||||
|
|
||||||
UnloadImage(image); // Once image has been converted to texture and uploaded to VRAM, it can be unloaded from RAM
|
UnloadImage(image); // Once image has been converted to texture and uploaded to VRAM, it can be unloaded from RAM
|
||||||
|
|
||||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||||
//---------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,11 +18,11 @@ cmd /c del /F libraylib.a
|
||||||
:: > Compile raylib modules
|
:: > Compile raylib modules
|
||||||
:: ------------------------------
|
:: ------------------------------
|
||||||
gcc -O2 -c rglfw.c -Wall -I. -Iexternal/glfw/include
|
gcc -O2 -c rglfw.c -Wall -I. -Iexternal/glfw/include
|
||||||
gcc -O2 -c core.c -std=c99 -Wall -Iexternal/glfw/include -DPLATFORM_DESKTOP -D%GRAPHICS_API%
|
gcc -O2 -c rcore.c -std=c99 -Wall -Iexternal/glfw/include -DPLATFORM_DESKTOP -D%GRAPHICS_API%
|
||||||
gcc -O2 -c shapes.c -std=c99 -Wall -DPLATFORM_DESKTOP
|
gcc -O2 -c rshapes.c -std=c99 -Wall -DPLATFORM_DESKTOP
|
||||||
gcc -O2 -c textures.c -std=c99 -Wall -DPLATFORM_DESKTOP
|
gcc -O2 -c rtextures.c -std=c99 -Wall -DPLATFORM_DESKTOP
|
||||||
gcc -O2 -c text.c -std=c99 -Wall -DPLATFORM_DESKTOP
|
gcc -O2 -c rtext.c -std=c99 -Wall -DPLATFORM_DESKTOP
|
||||||
gcc -O2 -c models.c -std=c99 -Wall -DPLATFORM_DESKTOP
|
gcc -O2 -c rmodels.c -std=c99 -Wall -DPLATFORM_DESKTOP
|
||||||
gcc -O2 -c raudio.c -std=c99 -Wall -DPLATFORM_DESKTOP
|
gcc -O2 -c raudio.c -std=c99 -Wall -DPLATFORM_DESKTOP
|
||||||
gcc -O2 -c utils.c -std=c99 -Wall -DPLATFORM_DESKTOP
|
gcc -O2 -c utils.c -std=c99 -Wall -DPLATFORM_DESKTOP
|
||||||
|
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
387
projects/VS2019/examples/models_mesh_magicavoxel_loading.vcxproj
Normal file
387
projects/VS2019/examples/models_mesh_magicavoxel_loading.vcxproj
Normal file
|
|
@ -0,0 +1,387 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug.DLL|Win32">
|
||||||
|
<Configuration>Debug.DLL</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug.DLL|x64">
|
||||||
|
<Configuration>Debug.DLL</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release.DLL|Win32">
|
||||||
|
<Configuration>Release.DLL</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release.DLL|x64">
|
||||||
|
<Configuration>Release.DLL</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{2F1B955B-275E-4D8E-8864-06FEC44D7912}</ProjectGuid>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<RootNamespace>models_mesh_magicavoxel_loading</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||||
|
<ProjectName>models_mesh_magicavoxel_loading</ProjectName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'">
|
||||||
|
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\models</LocalDebuggerWorkingDirectory>
|
||||||
|
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|x64'">
|
||||||
|
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\models</LocalDebuggerWorkingDirectory>
|
||||||
|
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\models</LocalDebuggerWorkingDirectory>
|
||||||
|
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\models</LocalDebuggerWorkingDirectory>
|
||||||
|
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'">
|
||||||
|
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\models</LocalDebuggerWorkingDirectory>
|
||||||
|
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\models</LocalDebuggerWorkingDirectory>
|
||||||
|
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\models</LocalDebuggerWorkingDirectory>
|
||||||
|
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|x64'">
|
||||||
|
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\models</LocalDebuggerWorkingDirectory>
|
||||||
|
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<CompileAs>CompileAsC</CompileAs>
|
||||||
|
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
||||||
|
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<CompileAs>CompileAsC</CompileAs>
|
||||||
|
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
||||||
|
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<CompileAs>CompileAsC</CompileAs>
|
||||||
|
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
||||||
|
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Command>xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"</Command>
|
||||||
|
<Message>Copy Debug DLL to output directory</Message>
|
||||||
|
</PostBuildEvent>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<CompileAs>CompileAsC</CompileAs>
|
||||||
|
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
||||||
|
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Command>xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"</Command>
|
||||||
|
<Message>Copy Debug DLL to output directory</Message>
|
||||||
|
</PostBuildEvent>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<CompileAs>CompileAsC</CompileAs>
|
||||||
|
<RemoveUnreferencedCodeData>true</RemoveUnreferencedCodeData>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<CompileAs>CompileAsC</CompileAs>
|
||||||
|
<RemoveUnreferencedCodeData>true</RemoveUnreferencedCodeData>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<CompileAs>CompileAsC</CompileAs>
|
||||||
|
<RemoveUnreferencedCodeData>true</RemoveUnreferencedCodeData>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
||||||
|
</Link>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Command>xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"</Command>
|
||||||
|
</PostBuildEvent>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Message>Copy Release DLL to output directory</Message>
|
||||||
|
</PostBuildEvent>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<CompileAs>CompileAsC</CompileAs>
|
||||||
|
<RemoveUnreferencedCodeData>true</RemoveUnreferencedCodeData>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
||||||
|
</Link>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Command>xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"</Command>
|
||||||
|
</PostBuildEvent>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Message>Copy Release DLL to output directory</Message>
|
||||||
|
</PostBuildEvent>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\raylib\raylib.vcxproj">
|
||||||
|
<Project>{e89d61ac-55de-4482-afd4-df7242ebc859}</Project>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\..\..\examples\models\models_magicavoxel_loading.c" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
||||||
|
|
@ -275,6 +275,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rlgl_standalone", "examples
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_split_screen", "examples\core_split_screen.vcxproj", "{946A1700-C7AA-46F0-AEF2-67C98B5722AC}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_split_screen", "examples\core_split_screen.vcxproj", "{946A1700-C7AA-46F0-AEF2-67C98B5722AC}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models_mesh_magicavoxel_loading", "examples\models_mesh_magicavoxel_loading.vcxproj", "{2F1B955B-275E-4D8E-8864-06FEC44D7912}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug.DLL|x64 = Debug.DLL|x64
|
Debug.DLL|x64 = Debug.DLL|x64
|
||||||
|
|
@ -2283,6 +2285,22 @@ Global
|
||||||
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Release|x64.Build.0 = Release|x64
|
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Release|x64.Build.0 = Release|x64
|
||||||
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Release|x86.ActiveCfg = Release|Win32
|
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Release|x86.ActiveCfg = Release|Win32
|
||||||
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Release|x86.Build.0 = Release|Win32
|
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Release|x86.Build.0 = Release|Win32
|
||||||
|
{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64
|
||||||
|
{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Debug.DLL|x64.Build.0 = Debug.DLL|x64
|
||||||
|
{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
|
||||||
|
{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32
|
||||||
|
{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Release.DLL|x64.ActiveCfg = Release.DLL|x64
|
||||||
|
{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Release.DLL|x64.Build.0 = Release.DLL|x64
|
||||||
|
{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32
|
||||||
|
{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Release.DLL|x86.Build.0 = Release.DLL|Win32
|
||||||
|
{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Release|x64.Build.0 = Release|x64
|
||||||
|
{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Release|x86.Build.0 = Release|Win32
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
@ -2422,6 +2440,7 @@ Global
|
||||||
{6237BEDE-BAAA-4A06-9C5E-8089BAA14C8B} = {E9D708A5-9C1F-4B84-A795-C5F191801762}
|
{6237BEDE-BAAA-4A06-9C5E-8089BAA14C8B} = {E9D708A5-9C1F-4B84-A795-C5F191801762}
|
||||||
{C8765523-58F8-4C8E-9914-693396F6F0FF} = {E9D708A5-9C1F-4B84-A795-C5F191801762}
|
{C8765523-58F8-4C8E-9914-693396F6F0FF} = {E9D708A5-9C1F-4B84-A795-C5F191801762}
|
||||||
{946A1700-C7AA-46F0-AEF2-67C98B5722AC} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
|
{946A1700-C7AA-46F0-AEF2-67C98B5722AC} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
|
||||||
|
{2F1B955B-275E-4D8E-8864-06FEC44D7912} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29}
|
SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29}
|
||||||
|
|
|
||||||
|
|
@ -303,16 +303,16 @@
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\..\src\raudio.c" />
|
<ClCompile Include="..\..\..\src\raudio.c" />
|
||||||
<ClCompile Include="..\..\..\src\core.c" />
|
<ClCompile Include="..\..\..\src\rcore.c" />
|
||||||
<ClCompile Include="..\..\..\src\models.c" />
|
<ClCompile Include="..\..\..\src\rmodels.c" />
|
||||||
<ClCompile Include="..\..\..\src\rglfw.c" />
|
<ClCompile Include="..\..\..\src\rglfw.c" />
|
||||||
<ClCompile Include="..\..\..\src\shapes.c" />
|
<ClCompile Include="..\..\..\src\rshapes.c" />
|
||||||
<ClCompile Include="..\..\..\src\text.c" />
|
<ClCompile Include="..\..\..\src\rtext.c" />
|
||||||
<ClCompile Include="..\..\..\src\textures.c" />
|
<ClCompile Include="..\..\..\src\rtextures.c" />
|
||||||
<ClCompile Include="..\..\..\src\utils.c" />
|
<ClCompile Include="..\..\..\src\utils.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\..\src\camera.h" />
|
<ClInclude Include="..\..\..\src\rcamera.h" />
|
||||||
<ClInclude Include="..\..\..\src\config.h" />
|
<ClInclude Include="..\..\..\src\config.h" />
|
||||||
<ClInclude Include="..\..\..\src\external\glad.h" />
|
<ClInclude Include="..\..\..\src\external\glad.h" />
|
||||||
<ClInclude Include="..\..\..\src\external\jar_mod.h" />
|
<ClInclude Include="..\..\..\src\external\jar_mod.h" />
|
||||||
|
|
@ -324,7 +324,7 @@
|
||||||
<ClInclude Include="..\..\..\src\external\stb_rect_pack.h" />
|
<ClInclude Include="..\..\..\src\external\stb_rect_pack.h" />
|
||||||
<ClInclude Include="..\..\..\src\external\stb_truetype.h" />
|
<ClInclude Include="..\..\..\src\external\stb_truetype.h" />
|
||||||
<ClInclude Include="..\..\..\src\external\stb_vorbis.h" />
|
<ClInclude Include="..\..\..\src\external\stb_vorbis.h" />
|
||||||
<ClInclude Include="..\..\..\src\gestures.h" />
|
<ClInclude Include="..\..\..\src\rgestures.h" />
|
||||||
<ClInclude Include="..\..\..\src\raylib.h" />
|
<ClInclude Include="..\..\..\src\raylib.h" />
|
||||||
<ClInclude Include="..\..\..\src\raymath.h" />
|
<ClInclude Include="..\..\..\src\raymath.h" />
|
||||||
<ClInclude Include="..\..\..\src\rlgl.h" />
|
<ClInclude Include="..\..\..\src\rlgl.h" />
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ if [ ! -d "$TEMP_DIR" ]; then
|
||||||
mkdir -p $TEMP_DIR
|
mkdir -p $TEMP_DIR
|
||||||
cd $TEMP_DIR
|
cd $TEMP_DIR
|
||||||
RAYLIB_DEFINES="-D_DEFAULT_SOURCE -DPLATFORM_DESKTOP -DGRAPHICS_API_OPENGL_33"
|
RAYLIB_DEFINES="-D_DEFAULT_SOURCE -DPLATFORM_DESKTOP -DGRAPHICS_API_OPENGL_33"
|
||||||
RAYLIB_C_FILES="$RAYLIB_SRC/core.c $RAYLIB_SRC/shapes.c $RAYLIB_SRC/textures.c $RAYLIB_SRC/text.c $RAYLIB_SRC/models.c $RAYLIB_SRC/utils.c $RAYLIB_SRC/raudio.c $RAYLIB_SRC/rglfw.c"
|
RAYLIB_C_FILES="$RAYLIB_SRC/rcore.c $RAYLIB_SRC/rshapes.c $RAYLIB_SRC/rtextures.c $RAYLIB_SRC/rtext.c $RAYLIB_SRC/rmodels.c $RAYLIB_SRC/utils.c $RAYLIB_SRC/raudio.c $RAYLIB_SRC/rglfw.c"
|
||||||
RAYLIB_INCLUDE_FLAGS="-I$RAYLIB_SRC -I$RAYLIB_SRC/external/glfw/include"
|
RAYLIB_INCLUDE_FLAGS="-I$RAYLIB_SRC -I$RAYLIB_SRC/external/glfw/include"
|
||||||
|
|
||||||
if [ -n "$REALLY_QUIET" ]; then
|
if [ -n "$REALLY_QUIET" ]; then
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ if [ ! -d "$TEMP_DIR" ]; then
|
||||||
mkdir -p $TEMP_DIR
|
mkdir -p $TEMP_DIR
|
||||||
cd $TEMP_DIR
|
cd $TEMP_DIR
|
||||||
RAYLIB_DEFINES="-D_DEFAULT_SOURCE -DPLATFORM_DESKTOP -DGRAPHICS_API_OPENGL_33"
|
RAYLIB_DEFINES="-D_DEFAULT_SOURCE -DPLATFORM_DESKTOP -DGRAPHICS_API_OPENGL_33"
|
||||||
RAYLIB_C_FILES="$RAYLIB_SRC/core.c $RAYLIB_SRC/shapes.c $RAYLIB_SRC/textures.c $RAYLIB_SRC/text.c $RAYLIB_SRC/models.c $RAYLIB_SRC/utils.c $RAYLIB_SRC/raudio.c"
|
RAYLIB_C_FILES="$RAYLIB_SRC/rcore.c $RAYLIB_SRC/rshapes.c $RAYLIB_SRC/rtextures.c $RAYLIB_SRC/rtext.c $RAYLIB_SRC/rmodels.c $RAYLIB_SRC/utils.c $RAYLIB_SRC/raudio.c"
|
||||||
RAYLIB_INCLUDE_FLAGS="-I$RAYLIB_SRC -I$RAYLIB_SRC/external/glfw/include"
|
RAYLIB_INCLUDE_FLAGS="-I$RAYLIB_SRC -I$RAYLIB_SRC/external/glfw/include"
|
||||||
|
|
||||||
if [ -n "$REALLY_QUIET" ]; then
|
if [ -n "$REALLY_QUIET" ]; then
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ if [ ! -d "$TEMP_DIR" ]; then
|
||||||
mkdir -p $TEMP_DIR
|
mkdir -p $TEMP_DIR
|
||||||
cd $TEMP_DIR
|
cd $TEMP_DIR
|
||||||
RAYLIB_DEFINES="-D_DEFAULT_SOURCE -DPLATFORM_RPI -DGRAPHICS_API_OPENGL_ES2"
|
RAYLIB_DEFINES="-D_DEFAULT_SOURCE -DPLATFORM_RPI -DGRAPHICS_API_OPENGL_ES2"
|
||||||
RAYLIB_C_FILES="$RAYLIB_SRC/core.c $RAYLIB_SRC/shapes.c $RAYLIB_SRC/textures.c $RAYLIB_SRC/text.c $RAYLIB_SRC/models.c $RAYLIB_SRC/utils.c $RAYLIB_SRC/raudio.c"
|
RAYLIB_C_FILES="$RAYLIB_SRC/rcore.c $RAYLIB_SRC/rshapes.c $RAYLIB_SRC/rtextures.c $RAYLIB_SRC/rtext.c $RAYLIB_SRC/rmodels.c $RAYLIB_SRC/utils.c $RAYLIB_SRC/raudio.c"
|
||||||
RAYLIB_INCLUDE_FLAGS="-I$RAYLIB_SRC -I/opt/vc/include"
|
RAYLIB_INCLUDE_FLAGS="-I$RAYLIB_SRC -I/opt/vc/include"
|
||||||
|
|
||||||
if [ -n "$REALLY_QUIET" ]; then
|
if [ -n "$REALLY_QUIET" ]; then
|
||||||
|
|
|
||||||
|
|
@ -167,7 +167,7 @@ IF NOT EXIST !TEMP_DIR!\ (
|
||||||
cd !TEMP_DIR!
|
cd !TEMP_DIR!
|
||||||
REM Raylib's src folder
|
REM Raylib's src folder
|
||||||
set "RAYLIB_DEFINES=/D_DEFAULT_SOURCE /DPLATFORM_DESKTOP /DGRAPHICS_API_OPENGL_33"
|
set "RAYLIB_DEFINES=/D_DEFAULT_SOURCE /DPLATFORM_DESKTOP /DGRAPHICS_API_OPENGL_33"
|
||||||
set RAYLIB_C_FILES="!RAYLIB_SRC!\core.c" "!RAYLIB_SRC!\shapes.c" "!RAYLIB_SRC!\textures.c" "!RAYLIB_SRC!\text.c" "!RAYLIB_SRC!\models.c" "!RAYLIB_SRC!\utils.c" "!RAYLIB_SRC!\raudio.c" "!RAYLIB_SRC!\rglfw.c"
|
set RAYLIB_C_FILES="!RAYLIB_SRC!\rcore.c" "!RAYLIB_SRC!\rshapes.c" "!RAYLIB_SRC!\rtextures.c" "!RAYLIB_SRC!\rtext.c" "!RAYLIB_SRC!\rmodels.c" "!RAYLIB_SRC!\utils.c" "!RAYLIB_SRC!\raudio.c" "!RAYLIB_SRC!\rglfw.c"
|
||||||
set RAYLIB_INCLUDE_FLAGS=/I"!RAYLIB_SRC!" /I"!RAYLIB_SRC!\external\glfw\include"
|
set RAYLIB_INCLUDE_FLAGS=/I"!RAYLIB_SRC!" /I"!RAYLIB_SRC!\external\glfw\include"
|
||||||
|
|
||||||
IF DEFINED REALLY_QUIET (
|
IF DEFINED REALLY_QUIET (
|
||||||
|
|
|
||||||
|
|
@ -30,11 +30,11 @@ set(raylib_public_headers
|
||||||
|
|
||||||
# Sources to be compiled
|
# Sources to be compiled
|
||||||
set(raylib_sources
|
set(raylib_sources
|
||||||
core.c
|
rcore.c
|
||||||
models.c
|
rmodels.c
|
||||||
shapes.c
|
rshapes.c
|
||||||
text.c
|
rtext.c
|
||||||
textures.c
|
rtextures.c
|
||||||
utils.c
|
utils.c
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
58
src/Makefile
58
src/Makefile
|
|
@ -80,7 +80,6 @@ RAYLIB_MODULE_RAYGUI_PATH ?= $(RAYLIB_SRC_PATH)/../../raygui/src
|
||||||
RAYLIB_MODULE_PHYSAC_PATH ?= $(RAYLIB_SRC_PATH)/extras
|
RAYLIB_MODULE_PHYSAC_PATH ?= $(RAYLIB_SRC_PATH)/extras
|
||||||
|
|
||||||
# Use external GLFW library instead of rglfw module
|
# Use external GLFW library instead of rglfw module
|
||||||
# TODO: Review usage of examples on Linux.
|
|
||||||
USE_EXTERNAL_GLFW ?= FALSE
|
USE_EXTERNAL_GLFW ?= FALSE
|
||||||
|
|
||||||
# Use Wayland display server protocol on Linux desktop
|
# Use Wayland display server protocol on Linux desktop
|
||||||
|
|
@ -186,16 +185,16 @@ ifeq ($(PLATFORM),PLATFORM_ANDROID)
|
||||||
ANDROID_SYSROOT ?= $(ANDROID_TOOLCHAIN)/sysroot
|
ANDROID_SYSROOT ?= $(ANDROID_TOOLCHAIN)/sysroot
|
||||||
|
|
||||||
ifeq ($(ANDROID_ARCH),arm)
|
ifeq ($(ANDROID_ARCH),arm)
|
||||||
ANDROID_ARCH_NAME = armeabi-v7a
|
ANDROID_COMPILER_ARCH = armv7a
|
||||||
endif
|
endif
|
||||||
ifeq ($(ANDROID_ARCH),arm64)
|
ifeq ($(ANDROID_ARCH),arm64)
|
||||||
ANDROID_ARCH_NAME = arm64-v8a
|
ANDROID_COMPILER_ARCH = aarch64
|
||||||
endif
|
endif
|
||||||
ifeq ($(ANDROID_ARCH),x86)
|
ifeq ($(ANDROID_ARCH),x86)
|
||||||
ANDROID_ARCH_NAME = i686
|
ANDROID_COMPILER_ARCH = i686
|
||||||
endif
|
endif
|
||||||
ifeq ($(ANDROID_ARCH),x86_64)
|
ifeq ($(ANDROID_ARCH),x86_64)
|
||||||
ANDROID_ARCH_NAME = x86_64
|
ANDROID_COMPILER_ARCH = x86_64
|
||||||
endif
|
endif
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
@ -255,21 +254,13 @@ endif
|
||||||
ifeq ($(PLATFORM),PLATFORM_ANDROID)
|
ifeq ($(PLATFORM),PLATFORM_ANDROID)
|
||||||
# Android toolchain (must be provided for desired architecture and compiler)
|
# Android toolchain (must be provided for desired architecture and compiler)
|
||||||
ifeq ($(ANDROID_ARCH),arm)
|
ifeq ($(ANDROID_ARCH),arm)
|
||||||
CC = $(ANDROID_TOOLCHAIN)/bin/armv7a-linux-androideabi$(ANDROID_API_VERSION)-clang
|
CC = $(ANDROID_TOOLCHAIN)/bin/$(ANDROID_COMPILER_ARCH)-linux-androideabi$(ANDROID_API_VERSION)-clang
|
||||||
AR = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-ar
|
|
||||||
endif
|
endif
|
||||||
ifeq ($(ANDROID_ARCH),arm64)
|
ifeq ($(ANDROID_ARCH),arm64)
|
||||||
CC = $(ANDROID_TOOLCHAIN)/bin/aarch64-linux-android$(ANDROID_API_VERSION)-clang
|
CC = $(ANDROID_TOOLCHAIN)/bin/$(ANDROID_COMPILER_ARCH)-linux-android$(ANDROID_API_VERSION)-clang
|
||||||
AR = $(ANDROID_TOOLCHAIN)/bin/aarch64-linux-android-ar
|
|
||||||
endif
|
|
||||||
ifeq ($(ANDROID_ARCH),x86)
|
|
||||||
CC = $(ANDROID_TOOLCHAIN)/bin/i686-linux-android$(ANDROID_API_VERSION)-clang
|
|
||||||
AR = $(ANDROID_TOOLCHAIN)/bin/i686-linux-android-ar
|
|
||||||
endif
|
|
||||||
ifeq ($(ANDROID_ARCH),x86_64)
|
|
||||||
CC = $(ANDROID_TOOLCHAIN)/bin/x86_64-linux-android$(ANDROID_API_VERSION)-clang
|
|
||||||
AR = $(ANDROID_TOOLCHAIN)/bin/x86_64-linux-android-ar
|
|
||||||
endif
|
endif
|
||||||
|
# It seems from Android NDK r22 onwards we need to use llvm-ar
|
||||||
|
AR = $(ANDROID_TOOLCHAIN)/bin/llvm-ar
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Define compiler flags:
|
# Define compiler flags:
|
||||||
|
|
@ -322,7 +313,7 @@ endif
|
||||||
ifeq ($(PLATFORM),PLATFORM_WEB)
|
ifeq ($(PLATFORM),PLATFORM_WEB)
|
||||||
# -Os # size optimization
|
# -Os # size optimization
|
||||||
# -O2 # optimization level 2, if used, also set --memory-init-file 0
|
# -O2 # optimization level 2, if used, also set --memory-init-file 0
|
||||||
# -s USE_GLFW=3 # Use glfw3 library (context/input management)
|
# -s USE_GLFW=3 # Use glfw3 library (context/input management) -> Only for linker!
|
||||||
# -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL!
|
# -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 TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB)
|
||||||
# -s USE_PTHREADS=1 # multithreading support
|
# -s USE_PTHREADS=1 # multithreading support
|
||||||
|
|
@ -331,7 +322,6 @@ ifeq ($(PLATFORM),PLATFORM_WEB)
|
||||||
# --profiling # include information for code profiling
|
# --profiling # include information for code profiling
|
||||||
# --memory-init-file 0 # to avoid an external memory initialization code file (.mem)
|
# --memory-init-file 0 # to avoid an external memory initialization code file (.mem)
|
||||||
# --preload-file resources # specify a resources folder for data compilation
|
# --preload-file resources # specify a resources folder for data compilation
|
||||||
CFLAGS += -s USE_GLFW=3
|
|
||||||
ifeq ($(RAYLIB_BUILD_MODE),DEBUG)
|
ifeq ($(RAYLIB_BUILD_MODE),DEBUG)
|
||||||
CFLAGS += -s ASSERTIONS=1 --profiling
|
CFLAGS += -s ASSERTIONS=1 --profiling
|
||||||
endif
|
endif
|
||||||
|
|
@ -344,10 +334,10 @@ ifeq ($(PLATFORM),PLATFORM_ANDROID)
|
||||||
ifeq ($(ANDROID_ARCH),arm64)
|
ifeq ($(ANDROID_ARCH),arm64)
|
||||||
CFLAGS += -target aarch64 -mfix-cortex-a53-835769
|
CFLAGS += -target aarch64 -mfix-cortex-a53-835769
|
||||||
endif
|
endif
|
||||||
ifeq ($(ANDROID_ARCH), x86)
|
ifeq ($(ANDROID_ARCH),x86)
|
||||||
CFLAGS += -march=i686
|
CFLAGS += -march=i686
|
||||||
endif
|
endif
|
||||||
ifeq ($(ANDROID_ARCH), x86_64)
|
ifeq ($(ANDROID_ARCH),x86_64)
|
||||||
CFLAGS += -march=x86-64
|
CFLAGS += -march=x86-64
|
||||||
endif
|
endif
|
||||||
# Compilation functions attributes options
|
# Compilation functions attributes options
|
||||||
|
|
@ -452,10 +442,10 @@ endif
|
||||||
# OBJS = $(patsubst %.c, %.o, $(wildcard *.c))
|
# OBJS = $(patsubst %.c, %.o, $(wildcard *.c))
|
||||||
|
|
||||||
# Define object required on compilation
|
# Define object required on compilation
|
||||||
OBJS = core.o \
|
OBJS = rcore.o \
|
||||||
shapes.o \
|
rshapes.o \
|
||||||
textures.o \
|
rtextures.o \
|
||||||
text.o \
|
rtext.o \
|
||||||
utils.o
|
utils.o
|
||||||
|
|
||||||
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
|
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
|
||||||
|
|
@ -464,7 +454,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
ifeq ($(RAYLIB_MODULE_MODELS),TRUE)
|
ifeq ($(RAYLIB_MODULE_MODELS),TRUE)
|
||||||
OBJS += models.o
|
OBJS += rmodels.o
|
||||||
endif
|
endif
|
||||||
ifeq ($(RAYLIB_MODULE_AUDIO),TRUE)
|
ifeq ($(RAYLIB_MODULE_AUDIO),TRUE)
|
||||||
OBJS += raudio.o
|
OBJS += raudio.o
|
||||||
|
|
@ -509,7 +499,7 @@ else
|
||||||
endif
|
endif
|
||||||
ifeq ($(PLATFORM_OS),OSX)
|
ifeq ($(PLATFORM_OS),OSX)
|
||||||
$(CC) -dynamiclib -o $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).$(RAYLIB_VERSION).dylib $(OBJS) $(LDFLAGS) -compatibility_version $(RAYLIB_API_VERSION) -current_version $(RAYLIB_VERSION) -framework OpenGL -framework Cocoa -framework IOKit -framework CoreAudio -framework CoreVideo
|
$(CC) -dynamiclib -o $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).$(RAYLIB_VERSION).dylib $(OBJS) $(LDFLAGS) -compatibility_version $(RAYLIB_API_VERSION) -current_version $(RAYLIB_VERSION) -framework OpenGL -framework Cocoa -framework IOKit -framework CoreAudio -framework CoreVideo
|
||||||
install_name_tool -id "lib$(RAYLIB_LIB_NAME).$(VERSION).dylib" $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).$(RAYLIB_VERSION).dylib
|
install_name_tool -id "@rpath/lib$(RAYLIB_LIB_NAME).$(RAYLIB_API_VERSION).dylib" $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).$(RAYLIB_VERSION).dylib
|
||||||
@echo "raylib shared library generated (lib$(RAYLIB_LIB_NAME).$(RAYLIB_VERSION).dylib)!"
|
@echo "raylib shared library generated (lib$(RAYLIB_LIB_NAME).$(RAYLIB_VERSION).dylib)!"
|
||||||
cd $(RAYLIB_RELEASE_PATH) && ln -fs lib$(RAYLIB_LIB_NAME).$(RAYLIB_VERSION).dylib lib$(RAYLIB_LIB_NAME).$(RAYLIB_API_VERSION).dylib
|
cd $(RAYLIB_RELEASE_PATH) && ln -fs lib$(RAYLIB_LIB_NAME).$(RAYLIB_VERSION).dylib lib$(RAYLIB_LIB_NAME).$(RAYLIB_API_VERSION).dylib
|
||||||
cd $(RAYLIB_RELEASE_PATH) && ln -fs lib$(RAYLIB_LIB_NAME).$(RAYLIB_VERSION).dylib lib$(RAYLIB_LIB_NAME).dylib
|
cd $(RAYLIB_RELEASE_PATH) && ln -fs lib$(RAYLIB_LIB_NAME).$(RAYLIB_VERSION).dylib lib$(RAYLIB_LIB_NAME).dylib
|
||||||
|
|
@ -558,7 +548,7 @@ endif
|
||||||
# Compile all modules with their prerequisites
|
# Compile all modules with their prerequisites
|
||||||
|
|
||||||
# Compile core module
|
# Compile core module
|
||||||
core.o : core.c raylib.h rlgl.h utils.h raymath.h camera.h gestures.h
|
rcore.o : rcore.c raylib.h rlgl.h utils.h raymath.h rcamera.h rgestures.h
|
||||||
$(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS) -D$(PLATFORM) -D$(GRAPHICS)
|
$(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS) -D$(PLATFORM) -D$(GRAPHICS)
|
||||||
|
|
||||||
# Compile rglfw module
|
# Compile rglfw module
|
||||||
|
|
@ -566,15 +556,15 @@ rglfw.o : rglfw.c
|
||||||
$(CC) $(GLFW_OSX) -c $< $(CFLAGS) $(INCLUDE_PATHS) -D$(PLATFORM) -D$(GRAPHICS)
|
$(CC) $(GLFW_OSX) -c $< $(CFLAGS) $(INCLUDE_PATHS) -D$(PLATFORM) -D$(GRAPHICS)
|
||||||
|
|
||||||
# Compile shapes module
|
# Compile shapes module
|
||||||
shapes.o : shapes.c raylib.h rlgl.h
|
rshapes.o : rshapes.c raylib.h rlgl.h
|
||||||
$(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS) -D$(PLATFORM) -D$(GRAPHICS)
|
$(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS) -D$(PLATFORM) -D$(GRAPHICS)
|
||||||
|
|
||||||
# Compile textures module
|
# Compile textures module
|
||||||
textures.o : textures.c raylib.h rlgl.h utils.h
|
rtextures.o : rtextures.c raylib.h rlgl.h utils.h
|
||||||
$(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS) -D$(PLATFORM) -D$(GRAPHICS)
|
$(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS) -D$(PLATFORM) -D$(GRAPHICS)
|
||||||
|
|
||||||
# Compile text module
|
# Compile text module
|
||||||
text.o : text.c raylib.h utils.h
|
rtext.o : rtext.c raylib.h utils.h
|
||||||
$(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS) -D$(PLATFORM) -D$(GRAPHICS)
|
$(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS) -D$(PLATFORM) -D$(GRAPHICS)
|
||||||
|
|
||||||
# Compile utils module
|
# Compile utils module
|
||||||
|
|
@ -582,7 +572,7 @@ utils.o : utils.c utils.h
|
||||||
$(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS) -D$(PLATFORM)
|
$(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS) -D$(PLATFORM)
|
||||||
|
|
||||||
# Compile models module
|
# Compile models module
|
||||||
models.o : models.c raylib.h rlgl.h raymath.h
|
rmodels.o : rmodels.c raylib.h rlgl.h raymath.h
|
||||||
$(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS) -D$(PLATFORM) -D$(GRAPHICS)
|
$(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS) -D$(PLATFORM) -D$(GRAPHICS)
|
||||||
|
|
||||||
# Compile audio module
|
# Compile audio module
|
||||||
|
|
@ -617,7 +607,7 @@ android_native_app_glue.o : $(NATIVE_APP_GLUE)/android_native_app_glue.c
|
||||||
# for our -L and -I specification to simplify management of the raylib source package.
|
# for our -L and -I specification to simplify management of the raylib source package.
|
||||||
# Customize these locations if you like but don't forget to pass them to make
|
# Customize these locations if you like but don't forget to pass them to make
|
||||||
# for compilation and enable runtime linking with -rpath, LD_LIBRARY_PATH, or ldconfig.
|
# for compilation and enable runtime linking with -rpath, LD_LIBRARY_PATH, or ldconfig.
|
||||||
# Hint: add -L$(RAYLIB_INSTALL_PATH) -I$(RAYLIB_H_INSTALL_PATH) to your own makefiles.
|
# HINT: Add -L$(RAYLIB_INSTALL_PATH) -I$(RAYLIB_H_INSTALL_PATH) to your own makefiles.
|
||||||
# See below and ../examples/Makefile for more information.
|
# See below and ../examples/Makefile for more information.
|
||||||
# TODO: Add other platforms. Remove sudo requirement, i.e. add USER mode.
|
# TODO: Add other platforms. Remove sudo requirement, i.e. add USER mode.
|
||||||
|
|
||||||
|
|
@ -661,7 +651,7 @@ else
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Remove raylib dev files installed on the system
|
# Remove raylib dev files installed on the system
|
||||||
# TODO: see 'install' target.
|
# NOTE: see 'install' target.
|
||||||
uninstall :
|
uninstall :
|
||||||
ifeq ($(ROOT),root)
|
ifeq ($(ROOT),root)
|
||||||
# WARNING: You are root, about to delete items from $(RAYLIB_INSTALL_PATH).
|
# WARNING: You are root, about to delete items from $(RAYLIB_INSTALL_PATH).
|
||||||
|
|
|
||||||
58
src/build.zig
Normal file
58
src/build.zig
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub fn build(b: *std.build.Builder) void {
|
||||||
|
// Standard target options allows the person running `zig build` to choose
|
||||||
|
// what target to build for. Here we do not override the defaults, which
|
||||||
|
// means any target is allowed, and the default is native. Other options
|
||||||
|
// for restricting supported target set are available.
|
||||||
|
const target = b.standardTargetOptions(.{});
|
||||||
|
|
||||||
|
// Standard release options allow the person running `zig build` to select
|
||||||
|
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
|
||||||
|
const mode = b.standardReleaseOptions();
|
||||||
|
|
||||||
|
const raylib_flags = &[_][]const u8{
|
||||||
|
"-std=gnu99",
|
||||||
|
"-DPLATFORM_DESKTOP",
|
||||||
|
"-DGL_SILENCE_DEPRECATION",
|
||||||
|
"-fno-sanitize=undefined", // https://github.com/raysan5/raylib/issues/1891
|
||||||
|
};
|
||||||
|
|
||||||
|
const raylib = b.addStaticLibrary("raylib", "raylib.h");
|
||||||
|
raylib.setTarget(target);
|
||||||
|
raylib.setBuildMode(mode);
|
||||||
|
raylib.linkLibC();
|
||||||
|
|
||||||
|
raylib.addIncludeDir("external/glfw/include");
|
||||||
|
|
||||||
|
raylib.addCSourceFile("rcore.c", raylib_flags);
|
||||||
|
raylib.addCSourceFile("rmodels.c", raylib_flags);
|
||||||
|
raylib.addCSourceFile("raudio.c", raylib_flags);
|
||||||
|
raylib.addCSourceFile("rshapes.c", raylib_flags);
|
||||||
|
raylib.addCSourceFile("rtext.c", raylib_flags);
|
||||||
|
raylib.addCSourceFile("rtextures.c", raylib_flags);
|
||||||
|
raylib.addCSourceFile("utils.c", raylib_flags);
|
||||||
|
raylib.addCSourceFile("rglfw.c", raylib_flags);
|
||||||
|
|
||||||
|
switch (raylib.target.toTarget().os.tag) {
|
||||||
|
.windows => {
|
||||||
|
raylib.linkSystemLibrary("winmm");
|
||||||
|
raylib.linkSystemLibrary("gdi32");
|
||||||
|
raylib.linkSystemLibrary("opengl32");
|
||||||
|
raylib.addIncludeDir("external/glfw/deps/mingw");
|
||||||
|
},
|
||||||
|
.linux => {
|
||||||
|
raylib.linkSystemLibrary("GL");
|
||||||
|
raylib.linkSystemLibrary("rt");
|
||||||
|
raylib.linkSystemLibrary("dl");
|
||||||
|
raylib.linkSystemLibrary("m");
|
||||||
|
raylib.linkSystemLibrary("X11");
|
||||||
|
},
|
||||||
|
else => {
|
||||||
|
@panic("Unsupported OS");
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
raylib.setOutputDir("./");
|
||||||
|
raylib.install();
|
||||||
|
}
|
||||||
|
|
@ -28,9 +28,9 @@
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Module: core - Configuration Flags
|
// Module: core - Configuration Flags
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Camera module is included (camera.h) and multiple predefined cameras are available: free, 1st/3rd person, orbital
|
// Camera module is included (rcamera.h) and multiple predefined cameras are available: free, 1st/3rd person, orbital
|
||||||
#define SUPPORT_CAMERA_SYSTEM 1
|
#define SUPPORT_CAMERA_SYSTEM 1
|
||||||
// Gestures module is included (gestures.h) to support gestures detection: tap, hold, swipe, drag
|
// Gestures module is included (rgestures.h) to support gestures detection: tap, hold, swipe, drag
|
||||||
#define SUPPORT_GESTURES_SYSTEM 1
|
#define SUPPORT_GESTURES_SYSTEM 1
|
||||||
// Mouse gestures are directly mapped like touches and processed by gestures system
|
// Mouse gestures are directly mapped like touches and processed by gestures system
|
||||||
#define SUPPORT_MOUSE_GESTURES 1
|
#define SUPPORT_MOUSE_GESTURES 1
|
||||||
|
|
@ -73,7 +73,7 @@
|
||||||
#define MAX_GAMEPADS 4 // Max number of gamepads supported
|
#define MAX_GAMEPADS 4 // Max number of gamepads supported
|
||||||
#define MAX_GAMEPAD_AXIS 8 // Max number of axis supported (per gamepad)
|
#define MAX_GAMEPAD_AXIS 8 // Max number of axis supported (per gamepad)
|
||||||
#define MAX_GAMEPAD_BUTTONS 32 // Max bumber of buttons supported (per gamepad)
|
#define MAX_GAMEPAD_BUTTONS 32 // Max bumber of buttons supported (per gamepad)
|
||||||
#define MAX_TOUCH_POINTS 10 // Maximum number of touch points supported
|
#define MAX_TOUCH_POINTS 8 // Maximum number of touch points supported
|
||||||
#define MAX_KEY_PRESSED_QUEUE 16 // Max number of characters in the key input queue
|
#define MAX_KEY_PRESSED_QUEUE 16 // Max number of characters in the key input queue
|
||||||
|
|
||||||
#define STORAGE_DATA_FILE "storage.data" // Automatic storage filename
|
#define STORAGE_DATA_FILE "storage.data" // Automatic storage filename
|
||||||
|
|
@ -182,6 +182,7 @@
|
||||||
#define SUPPORT_FILEFORMAT_MTL 1
|
#define SUPPORT_FILEFORMAT_MTL 1
|
||||||
#define SUPPORT_FILEFORMAT_IQM 1
|
#define SUPPORT_FILEFORMAT_IQM 1
|
||||||
#define SUPPORT_FILEFORMAT_GLTF 1
|
#define SUPPORT_FILEFORMAT_GLTF 1
|
||||||
|
#define SUPPORT_FILEFORMAT_VOX 1
|
||||||
// Support procedural mesh generation functions, uses external par_shapes.h library
|
// Support procedural mesh generation functions, uses external par_shapes.h library
|
||||||
// NOTE: Some generated meshes DO NOT include generated texture coordinates
|
// NOTE: Some generated meshes DO NOT include generated texture coordinates
|
||||||
#define SUPPORT_MESH_GENERATION 1
|
#define SUPPORT_MESH_GENERATION 1
|
||||||
|
|
|
||||||
1272
src/external/glfw/src/mappings.h
vendored
1272
src/external/glfw/src/mappings.h
vendored
File diff suppressed because it is too large
Load Diff
744
src/external/vox_loader.h
vendored
Normal file
744
src/external/vox_loader.h
vendored
Normal file
|
|
@ -0,0 +1,744 @@
|
||||||
|
/*
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2021 Johann Nadalutti.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
|
vox_loader - v1.01
|
||||||
|
no warranty implied; use at your own risk
|
||||||
|
|
||||||
|
Do this:
|
||||||
|
#define VOX_LOADER_INCLUDE__H
|
||||||
|
before you include this file in* one* C or C++ file to create the implementation.
|
||||||
|
|
||||||
|
// i.e. it should look like this:
|
||||||
|
#include ...
|
||||||
|
#include ...
|
||||||
|
#include ...
|
||||||
|
#define VOX_LOADER_INCLUDE__H
|
||||||
|
#include "vox_loader.h"
|
||||||
|
|
||||||
|
revision history:
|
||||||
|
1.00 (2021-09-03) first released version
|
||||||
|
1.01 (2021-09-07) Support custom memory allocators
|
||||||
|
Removed Raylib dependencies
|
||||||
|
Changed Vox_LoadFileName to Vox_LoadFromMemory
|
||||||
|
1.02 (2021-09-10) @raysan5: Reviewed some formating
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VOX_LOADER_H
|
||||||
|
#define VOX_LOADER_H
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// Allow custom memory allocators
|
||||||
|
#ifndef VOX_MALLOC
|
||||||
|
#define VOX_MALLOC RL_MALLOC
|
||||||
|
#endif
|
||||||
|
#ifndef VOX_CALLOC
|
||||||
|
#define VOX_CALLOC RL_CALLOC
|
||||||
|
#endif
|
||||||
|
#ifndef VOX_REALLOC
|
||||||
|
#define VOX_REALLOC RL_REALLOC
|
||||||
|
#endif
|
||||||
|
#ifndef VOX_FREE
|
||||||
|
#define VOX_FREE RL_FREE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define VOX_SUCCESS (0)
|
||||||
|
#define VOX_ERROR_FILE_NOT_FOUND (-1)
|
||||||
|
#define VOX_ERROR_INVALID_FORMAT (-2)
|
||||||
|
#define VOX_ERROR_FILE_VERSION_TOO_OLD (-3)
|
||||||
|
|
||||||
|
// VoxColor, 4 components, R8G8B8A8 (32bit)
|
||||||
|
typedef struct {
|
||||||
|
unsigned char r, g, b, a;
|
||||||
|
} VoxColor;
|
||||||
|
|
||||||
|
// VoxVector3, 3 components
|
||||||
|
typedef struct {
|
||||||
|
float x, y, z;
|
||||||
|
} VoxVector3;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int* array;
|
||||||
|
int used, size;
|
||||||
|
} ArrayInt;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
VoxVector3* array;
|
||||||
|
int used, size;
|
||||||
|
} ArrayVector3;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
VoxColor* array;
|
||||||
|
int used, size;
|
||||||
|
} ArrayColor;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned short* array;
|
||||||
|
int used, size;
|
||||||
|
} ArrayUShort;
|
||||||
|
|
||||||
|
// A chunk that contain voxels
|
||||||
|
typedef struct {
|
||||||
|
unsigned char* m_array; //If Sparse != null
|
||||||
|
int arraySize; //Size for m_array in bytes (DEBUG ONLY)
|
||||||
|
} CubeChunk3D;
|
||||||
|
|
||||||
|
// Array for voxels
|
||||||
|
// Array is divised into chunks of CHUNKSIZE*CHUNKSIZE*CHUNKSIZE voxels size
|
||||||
|
typedef struct {
|
||||||
|
// Array size in voxels
|
||||||
|
int sizeX;
|
||||||
|
int sizeY;
|
||||||
|
int sizeZ;
|
||||||
|
|
||||||
|
// Chunks size into array (array is divised into chunks)
|
||||||
|
int chunksSizeX;
|
||||||
|
int chunksSizeY;
|
||||||
|
int chunksSizeZ;
|
||||||
|
|
||||||
|
// Chunks array
|
||||||
|
CubeChunk3D* m_arrayChunks;
|
||||||
|
int arrayChunksSize; // Size for m_arrayChunks in bytes (DEBUG ONLY)
|
||||||
|
|
||||||
|
int ChunkFlattenOffset;
|
||||||
|
int chunksAllocated;
|
||||||
|
int chunksTotal;
|
||||||
|
|
||||||
|
// Arrays for mesh build
|
||||||
|
ArrayVector3 vertices;
|
||||||
|
ArrayUShort indices;
|
||||||
|
ArrayColor colors;
|
||||||
|
|
||||||
|
//Palette for voxels
|
||||||
|
VoxColor palette[256];
|
||||||
|
|
||||||
|
} VoxArray3D;
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" { // Prevents name mangling of functions
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Functions
|
||||||
|
int Vox_LoadFromMemory(const unsigned char* pvoxData, unsigned int voxDataSize, VoxArray3D* pvoxarray);
|
||||||
|
void Vox_FreeArrays(VoxArray3D* voxarray);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // VOX_LOADER_H
|
||||||
|
//// end header file /////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Implementation
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifdef VOX_LOADER_IMPLEMENTATION
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// ArrayInt helper
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static void initArrayInt(ArrayInt* a, int initialSize)
|
||||||
|
{
|
||||||
|
a->array = VOX_MALLOC(initialSize * sizeof(int));
|
||||||
|
a->used = 0;
|
||||||
|
a->size = initialSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void insertArrayInt(ArrayInt* a, int element)
|
||||||
|
{
|
||||||
|
if (a->used == a->size)
|
||||||
|
{
|
||||||
|
a->size *= 2;
|
||||||
|
a->array = VOX_REALLOC(a->array, a->size * sizeof(int));
|
||||||
|
}
|
||||||
|
|
||||||
|
a->array[a->used++] = element;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void freeArrayInt(ArrayInt* a)
|
||||||
|
{
|
||||||
|
VOX_FREE(a->array);
|
||||||
|
a->array = NULL;
|
||||||
|
a->used = a->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// ArrayUShort helper
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static void initArrayUShort(ArrayUShort* a, int initialSize)
|
||||||
|
{
|
||||||
|
a->array = VOX_MALLOC(initialSize * sizeof(unsigned short));
|
||||||
|
a->used = 0;
|
||||||
|
a->size = initialSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void insertArrayUShort(ArrayUShort* a, unsigned short element)
|
||||||
|
{
|
||||||
|
if (a->used == a->size)
|
||||||
|
{
|
||||||
|
a->size *= 2;
|
||||||
|
a->array = VOX_REALLOC(a->array, a->size * sizeof(unsigned short));
|
||||||
|
}
|
||||||
|
a->array[a->used++] = element;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void freeArrayUShort(ArrayUShort* a)
|
||||||
|
{
|
||||||
|
VOX_FREE(a->array);
|
||||||
|
a->array = NULL;
|
||||||
|
a->used = a->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// ArrayVector3 helper
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static void initArrayVector3(ArrayVector3* a, int initialSize)
|
||||||
|
{
|
||||||
|
a->array = VOX_MALLOC(initialSize * sizeof(VoxVector3));
|
||||||
|
a->used = 0;
|
||||||
|
a->size = initialSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void insertArrayVector3(ArrayVector3* a, VoxVector3 element)
|
||||||
|
{
|
||||||
|
if (a->used == a->size)
|
||||||
|
{
|
||||||
|
a->size *= 2;
|
||||||
|
a->array = VOX_REALLOC(a->array, a->size * sizeof(VoxVector3));
|
||||||
|
}
|
||||||
|
a->array[a->used++] = element;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void freeArrayVector3(ArrayVector3* a)
|
||||||
|
{
|
||||||
|
VOX_FREE(a->array);
|
||||||
|
a->array = NULL;
|
||||||
|
a->used = a->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// ArrayColor helper
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static void initArrayColor(ArrayColor* a, int initialSize)
|
||||||
|
{
|
||||||
|
a->array = VOX_MALLOC(initialSize * sizeof(VoxColor));
|
||||||
|
a->used = 0;
|
||||||
|
a->size = initialSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void insertArrayColor(ArrayColor* a, VoxColor element)
|
||||||
|
{
|
||||||
|
if (a->used == a->size)
|
||||||
|
{
|
||||||
|
a->size *= 2;
|
||||||
|
a->array = VOX_REALLOC(a->array, a->size * sizeof(VoxColor));
|
||||||
|
}
|
||||||
|
a->array[a->used++] = element;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void freeArrayColor(ArrayColor* a)
|
||||||
|
{
|
||||||
|
VOX_FREE(a->array);
|
||||||
|
a->array = NULL;
|
||||||
|
a->used = a->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Vox Loader
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#define CHUNKSIZE 16 // chunk size (CHUNKSIZE*CHUNKSIZE*CHUNKSIZE) in voxels
|
||||||
|
#define CHUNKSIZE_OPSHIFT 4 // 1<<4=16 -> Warning depend of CHUNKSIZE
|
||||||
|
#define CHUNK_FLATTENOFFSET_OPSHIFT 8 // Warning depend of CHUNKSIZE
|
||||||
|
|
||||||
|
//
|
||||||
|
// used right handed system and CCW face
|
||||||
|
//
|
||||||
|
// indexes for voxelcoords, per face orientation
|
||||||
|
//
|
||||||
|
|
||||||
|
//# Y
|
||||||
|
//# |
|
||||||
|
//# o----X
|
||||||
|
//# /
|
||||||
|
//# Z 2------------3
|
||||||
|
//# /| /|
|
||||||
|
//# 6------------7 |
|
||||||
|
//# | | | |
|
||||||
|
//# |0 ----------|- 1
|
||||||
|
//# |/ |/
|
||||||
|
//# 4------------5
|
||||||
|
|
||||||
|
//
|
||||||
|
// CCW
|
||||||
|
const int fv[6][4] = {
|
||||||
|
{0, 2, 6, 4 }, //-X
|
||||||
|
{5, 7, 3, 1 }, //+X
|
||||||
|
{0, 4, 5, 1 }, //-y
|
||||||
|
{6, 2, 3, 7 }, //+y
|
||||||
|
{1, 3, 2, 0 }, //-Z
|
||||||
|
{4, 6, 7, 5 } //+Z
|
||||||
|
};
|
||||||
|
|
||||||
|
const VoxVector3 SolidVertex[] = {
|
||||||
|
{0, 0, 0}, //0
|
||||||
|
{1, 0, 0}, //1
|
||||||
|
{0, 1, 0}, //2
|
||||||
|
{1, 1, 0}, //3
|
||||||
|
{0, 0, 1}, //4
|
||||||
|
{1, 0, 1}, //5
|
||||||
|
{0, 1, 1}, //6
|
||||||
|
{1, 1, 1} //7
|
||||||
|
};
|
||||||
|
|
||||||
|
// Allocated VoxArray3D size
|
||||||
|
static void Vox_AllocArray(VoxArray3D* pvoxarray, int _sx, int _sy, int _sz)
|
||||||
|
{
|
||||||
|
int sx = _sx + ((CHUNKSIZE - (_sx % CHUNKSIZE)) % CHUNKSIZE);
|
||||||
|
int sy = _sy + ((CHUNKSIZE - (_sy % CHUNKSIZE)) % CHUNKSIZE);
|
||||||
|
int sz = _sz + ((CHUNKSIZE - (_sz % CHUNKSIZE)) % CHUNKSIZE);
|
||||||
|
|
||||||
|
int chx = sx >> CHUNKSIZE_OPSHIFT; //Chunks Count in X
|
||||||
|
int chy = sy >> CHUNKSIZE_OPSHIFT; //Chunks Count in Y
|
||||||
|
int chz = sz >> CHUNKSIZE_OPSHIFT; //Chunks Count in Z
|
||||||
|
|
||||||
|
//VoxArray3D* parray = (VoxArray3D*)VOX_MALLOC(sizeof(VoxArray3D));
|
||||||
|
pvoxarray->sizeX = sx;
|
||||||
|
pvoxarray->sizeY = sy;
|
||||||
|
pvoxarray->sizeZ = sz;
|
||||||
|
|
||||||
|
pvoxarray->chunksSizeX = chx;
|
||||||
|
pvoxarray->chunksSizeY = chy;
|
||||||
|
pvoxarray->chunksSizeZ = chz;
|
||||||
|
|
||||||
|
pvoxarray->ChunkFlattenOffset = (chy * chz); //m_arrayChunks[(x * (sy*sz)) + (z * sy) + y]
|
||||||
|
|
||||||
|
// Alloc chunks array
|
||||||
|
int size = sizeof(CubeChunk3D) * chx * chy * chz;
|
||||||
|
pvoxarray->m_arrayChunks = VOX_MALLOC(size);
|
||||||
|
pvoxarray->arrayChunksSize = size;
|
||||||
|
|
||||||
|
// Init chunks array
|
||||||
|
size = chx * chy * chz;
|
||||||
|
pvoxarray->chunksTotal = size;
|
||||||
|
pvoxarray->chunksAllocated = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
pvoxarray->m_arrayChunks[i].m_array = 0;
|
||||||
|
pvoxarray->m_arrayChunks[i].arraySize = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set voxel ID from its position into VoxArray3D
|
||||||
|
static void Vox_SetVoxel(VoxArray3D* pvoxarray, int x, int y, int z, unsigned char id)
|
||||||
|
{
|
||||||
|
// Get chunk from array pos
|
||||||
|
int chX = x >> CHUNKSIZE_OPSHIFT; //x / CHUNKSIZE;
|
||||||
|
int chY = y >> CHUNKSIZE_OPSHIFT; //y / CHUNKSIZE;
|
||||||
|
int chZ = z >> CHUNKSIZE_OPSHIFT; //z / CHUNKSIZE;
|
||||||
|
int offset = (chX * pvoxarray->ChunkFlattenOffset) + (chZ * pvoxarray->chunksSizeY) + chY;
|
||||||
|
|
||||||
|
//if (offset > voxarray->arrayChunksSize)
|
||||||
|
//{
|
||||||
|
// TraceLog(LOG_ERROR, "Out of array");
|
||||||
|
//}
|
||||||
|
|
||||||
|
CubeChunk3D* chunk = &pvoxarray->m_arrayChunks[offset];
|
||||||
|
|
||||||
|
// Set Chunk
|
||||||
|
chX = x - (chX << CHUNKSIZE_OPSHIFT); //x - (bx * CHUNKSIZE);
|
||||||
|
chY = y - (chY << CHUNKSIZE_OPSHIFT); //y - (by * CHUNKSIZE);
|
||||||
|
chZ = z - (chZ << CHUNKSIZE_OPSHIFT); //z - (bz * CHUNKSIZE);
|
||||||
|
|
||||||
|
if (chunk->m_array == 0)
|
||||||
|
{
|
||||||
|
int size = CHUNKSIZE * CHUNKSIZE * CHUNKSIZE;
|
||||||
|
chunk->m_array = VOX_MALLOC(size);
|
||||||
|
chunk->arraySize = size;
|
||||||
|
memset(chunk->m_array, 0, size);
|
||||||
|
|
||||||
|
pvoxarray->chunksAllocated++;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = (chX << CHUNK_FLATTENOFFSET_OPSHIFT) + (chZ << CHUNKSIZE_OPSHIFT) + chY;
|
||||||
|
|
||||||
|
//if (offset > chunk->arraySize)
|
||||||
|
//{
|
||||||
|
// TraceLog(LOG_ERROR, "Out of array");
|
||||||
|
//}
|
||||||
|
|
||||||
|
chunk->m_array[offset] = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get voxel ID from its position into VoxArray3D
|
||||||
|
static unsigned char Vox_GetVoxel(VoxArray3D* pvoxarray, int x, int y, int z)
|
||||||
|
{
|
||||||
|
if (x < 0 || y < 0 || z < 0) return 0;
|
||||||
|
|
||||||
|
if (x >= pvoxarray->sizeX || y >= pvoxarray->sizeY || z >= pvoxarray->sizeZ) return 0;
|
||||||
|
|
||||||
|
// Get chunk from array pos
|
||||||
|
int chX = x >> CHUNKSIZE_OPSHIFT; //x / CHUNKSIZE;
|
||||||
|
int chY = y >> CHUNKSIZE_OPSHIFT; //y / CHUNKSIZE;
|
||||||
|
int chZ = z >> CHUNKSIZE_OPSHIFT; //z / CHUNKSIZE;
|
||||||
|
int offset = (chX * pvoxarray->ChunkFlattenOffset) + (chZ * pvoxarray->chunksSizeY) + chY;
|
||||||
|
|
||||||
|
//if (offset > voxarray->arrayChunksSize)
|
||||||
|
//{
|
||||||
|
// TraceLog(LOG_ERROR, "Out of array");
|
||||||
|
//}
|
||||||
|
|
||||||
|
CubeChunk3D* chunk = &pvoxarray->m_arrayChunks[offset];
|
||||||
|
|
||||||
|
// Set Chunk
|
||||||
|
chX = x - (chX << CHUNKSIZE_OPSHIFT); //x - (bx * CHUNKSIZE);
|
||||||
|
chY = y - (chY << CHUNKSIZE_OPSHIFT); //y - (by * CHUNKSIZE);
|
||||||
|
chZ = z - (chZ << CHUNKSIZE_OPSHIFT); //z - (bz * CHUNKSIZE);
|
||||||
|
|
||||||
|
if (chunk->m_array == 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = (chX << CHUNK_FLATTENOFFSET_OPSHIFT) + (chZ << CHUNKSIZE_OPSHIFT) + chY;
|
||||||
|
|
||||||
|
//if (offset > chunk->arraySize)
|
||||||
|
//{
|
||||||
|
// TraceLog(LOG_ERROR, "Out of array");
|
||||||
|
//}
|
||||||
|
return chunk->m_array[offset];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calc visibles faces from a voxel position
|
||||||
|
static unsigned char Vox_CalcFacesVisible(VoxArray3D* pvoxArray, int cx, int cy, int cz)
|
||||||
|
{
|
||||||
|
unsigned char idXm1 = Vox_GetVoxel(pvoxArray, cx - 1, cy, cz);
|
||||||
|
unsigned char idXp1 = Vox_GetVoxel(pvoxArray, cx + 1, cy, cz);
|
||||||
|
|
||||||
|
unsigned char idYm1 = Vox_GetVoxel(pvoxArray, cx, cy - 1, cz);
|
||||||
|
unsigned char idYp1 = Vox_GetVoxel(pvoxArray, cx, cy + 1, cz);
|
||||||
|
|
||||||
|
unsigned char idZm1 = Vox_GetVoxel(pvoxArray, cx, cy, cz - 1);
|
||||||
|
unsigned char idZp1 = Vox_GetVoxel(pvoxArray, cx, cy, cz + 1);
|
||||||
|
|
||||||
|
unsigned char byVFMask = 0;
|
||||||
|
|
||||||
|
//#-x
|
||||||
|
if (idXm1 == 0) byVFMask |= (1 << 0);
|
||||||
|
|
||||||
|
//#+x
|
||||||
|
if (idXp1 == 0) byVFMask |= (1 << 1);
|
||||||
|
|
||||||
|
//#-y
|
||||||
|
if (idYm1 == 0) byVFMask |= (1 << 2);
|
||||||
|
|
||||||
|
//#+y
|
||||||
|
if (idYp1 == 0) byVFMask |= (1 << 3);
|
||||||
|
|
||||||
|
//#-z
|
||||||
|
if (idZm1 == 0) byVFMask |= (1 << 4);
|
||||||
|
|
||||||
|
//#+z
|
||||||
|
if (idZp1 == 0) byVFMask |= (1 << 5);
|
||||||
|
|
||||||
|
return byVFMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a vertex position from a voxel's corner
|
||||||
|
static VoxVector3 Vox_GetVertexPosition(int _wcx, int _wcy, int _wcz, int _nNumVertex)
|
||||||
|
{
|
||||||
|
float scale = 0.25;
|
||||||
|
|
||||||
|
VoxVector3 vtx = SolidVertex[_nNumVertex];
|
||||||
|
vtx.x = (vtx.x + _wcx) * scale;
|
||||||
|
vtx.y = (vtx.y + _wcy) * scale;
|
||||||
|
vtx.z = (vtx.z + _wcz) * scale;
|
||||||
|
|
||||||
|
return vtx;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build a voxel vertices/colors/indices
|
||||||
|
static void Vox_Build_Voxel(VoxArray3D* pvoxArray, int x, int y, int z, int matID)
|
||||||
|
{
|
||||||
|
unsigned char byVFMask = Vox_CalcFacesVisible(pvoxArray, x, y, z);
|
||||||
|
|
||||||
|
if (byVFMask == 0) return;
|
||||||
|
|
||||||
|
int i, j;
|
||||||
|
VoxVector3 vertComputed[8];
|
||||||
|
int bVertexComputed[8];
|
||||||
|
memset(vertComputed, 0, sizeof(vertComputed));
|
||||||
|
memset(bVertexComputed, 0, sizeof(bVertexComputed));
|
||||||
|
|
||||||
|
//For each Cube's faces
|
||||||
|
for (i = 0; i < 6; i++) // 6 faces
|
||||||
|
{
|
||||||
|
if ((byVFMask & (1 << i)) != 0) //If face is visible
|
||||||
|
{
|
||||||
|
for (j = 0; j < 4; j++) // 4 corners
|
||||||
|
{
|
||||||
|
int nNumVertex = fv[i][j]; //Face,Corner
|
||||||
|
if (bVertexComputed[nNumVertex] == 0) //if never calc
|
||||||
|
{
|
||||||
|
bVertexComputed[nNumVertex] = 1;
|
||||||
|
vertComputed[nNumVertex] = Vox_GetVertexPosition(x, y, z, nNumVertex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add face
|
||||||
|
for (i = 0; i < 6; i++)// 6 faces
|
||||||
|
{
|
||||||
|
if ((byVFMask & (1 << i)) == 0)
|
||||||
|
continue; //Face invisible
|
||||||
|
|
||||||
|
int v0 = fv[i][0]; //Face, Corner
|
||||||
|
int v1 = fv[i][1]; //Face, Corner
|
||||||
|
int v2 = fv[i][2]; //Face, Corner
|
||||||
|
int v3 = fv[i][3]; //Face, Corner
|
||||||
|
|
||||||
|
//Arrays
|
||||||
|
int idx = pvoxArray->vertices.used;
|
||||||
|
insertArrayVector3(&pvoxArray->vertices, vertComputed[v0]);
|
||||||
|
insertArrayVector3(&pvoxArray->vertices, vertComputed[v1]);
|
||||||
|
insertArrayVector3(&pvoxArray->vertices, vertComputed[v2]);
|
||||||
|
insertArrayVector3(&pvoxArray->vertices, vertComputed[v3]);
|
||||||
|
|
||||||
|
VoxColor col = pvoxArray->palette[matID];
|
||||||
|
|
||||||
|
insertArrayColor(&pvoxArray->colors, col);
|
||||||
|
insertArrayColor(&pvoxArray->colors, col);
|
||||||
|
insertArrayColor(&pvoxArray->colors, col);
|
||||||
|
insertArrayColor(&pvoxArray->colors, col);
|
||||||
|
|
||||||
|
|
||||||
|
//v0 - v1 - v2, v0 - v2 - v3
|
||||||
|
insertArrayUShort(&pvoxArray->indices, idx + 0);
|
||||||
|
insertArrayUShort(&pvoxArray->indices, idx + 2);
|
||||||
|
insertArrayUShort(&pvoxArray->indices, idx + 1);
|
||||||
|
|
||||||
|
insertArrayUShort(&pvoxArray->indices, idx + 0);
|
||||||
|
insertArrayUShort(&pvoxArray->indices, idx + 3);
|
||||||
|
insertArrayUShort(&pvoxArray->indices, idx + 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MagicaVoxel *.vox file format Loader
|
||||||
|
int Vox_LoadFromMemory(const unsigned char* pvoxData, unsigned int voxDataSize, VoxArray3D* pvoxarray)
|
||||||
|
{
|
||||||
|
//////////////////////////////////////////////////
|
||||||
|
//Read VOX file
|
||||||
|
//4 bytes: magic number ('V' 'O' 'X' 'space' )
|
||||||
|
//4 bytes: version number (current version is 150 )
|
||||||
|
|
||||||
|
unsigned long signature;
|
||||||
|
|
||||||
|
unsigned char* fileData = pvoxData;
|
||||||
|
|
||||||
|
unsigned char* fileDataPtr = fileData;
|
||||||
|
unsigned char* endfileDataPtr = fileData + voxDataSize;
|
||||||
|
|
||||||
|
signature = *((unsigned long *)fileDataPtr);
|
||||||
|
fileDataPtr += sizeof(unsigned long);
|
||||||
|
|
||||||
|
if (signature != 0x20584F56) //56 4F 58 20
|
||||||
|
{
|
||||||
|
return VOX_ERROR_INVALID_FORMAT; //"Not an MagicaVoxel File format"
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long version;
|
||||||
|
|
||||||
|
version = *((unsigned long*)fileDataPtr);
|
||||||
|
fileDataPtr += sizeof(unsigned long);
|
||||||
|
|
||||||
|
if (version < 150)
|
||||||
|
{
|
||||||
|
return VOX_ERROR_FILE_VERSION_TOO_OLD; //"MagicaVoxel version too old"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// header
|
||||||
|
//4 bytes: chunk id
|
||||||
|
//4 bytes: size of chunk contents (n)
|
||||||
|
//4 bytes: total size of children chunks(m)
|
||||||
|
|
||||||
|
//// chunk content
|
||||||
|
//n bytes: chunk contents
|
||||||
|
|
||||||
|
//// children chunks : m bytes
|
||||||
|
//{ child chunk 0 }
|
||||||
|
//{ child chunk 1 }
|
||||||
|
unsigned long sizeX, sizeY, sizeZ;
|
||||||
|
sizeX = sizeY = sizeZ = 0;
|
||||||
|
unsigned long numVoxels = 0;
|
||||||
|
int offsetX, offsetY, offsetZ;
|
||||||
|
offsetX = offsetY = offsetZ = 0;
|
||||||
|
|
||||||
|
while (fileDataPtr < endfileDataPtr)
|
||||||
|
{
|
||||||
|
char szChunkName[5];
|
||||||
|
memcpy(szChunkName, fileDataPtr, 4);
|
||||||
|
szChunkName[4] = 0;
|
||||||
|
fileDataPtr += 4;
|
||||||
|
|
||||||
|
unsigned long chunkSize = *((unsigned long*)fileDataPtr);
|
||||||
|
fileDataPtr += sizeof(unsigned long);
|
||||||
|
|
||||||
|
unsigned long chunkTotalChildSize = *((unsigned long*)fileDataPtr);
|
||||||
|
fileDataPtr += sizeof(unsigned long);
|
||||||
|
|
||||||
|
if (strcmp(szChunkName, "SIZE") == 0)
|
||||||
|
{
|
||||||
|
//(4 bytes x 3 : x, y, z )
|
||||||
|
sizeX = *((unsigned long*)fileDataPtr);
|
||||||
|
fileDataPtr += sizeof(unsigned long);
|
||||||
|
|
||||||
|
sizeY = *((unsigned long*)fileDataPtr);
|
||||||
|
fileDataPtr += sizeof(unsigned long);
|
||||||
|
|
||||||
|
sizeZ = *((unsigned long*)fileDataPtr);
|
||||||
|
fileDataPtr += sizeof(unsigned long);
|
||||||
|
|
||||||
|
//Alloc vox array
|
||||||
|
Vox_AllocArray(pvoxarray, sizeX, sizeZ, sizeY); //Reverse Y<>Z for left to right handed system
|
||||||
|
}
|
||||||
|
else if (strcmp(szChunkName, "XYZI") == 0)
|
||||||
|
{
|
||||||
|
unsigned char vx, vy, vz, vi;
|
||||||
|
|
||||||
|
//(numVoxels : 4 bytes )
|
||||||
|
//(each voxel: 1 byte x 4 : x, y, z, colorIndex ) x numVoxels
|
||||||
|
numVoxels = *((unsigned long*)fileDataPtr);
|
||||||
|
fileDataPtr += sizeof(unsigned long);
|
||||||
|
|
||||||
|
while (numVoxels > 0)
|
||||||
|
{
|
||||||
|
vx = *((unsigned char*)fileDataPtr++);
|
||||||
|
vy = *((unsigned char*)fileDataPtr++);
|
||||||
|
vz = *((unsigned char*)fileDataPtr++);
|
||||||
|
vi = *((unsigned char*)fileDataPtr++);
|
||||||
|
|
||||||
|
Vox_SetVoxel(pvoxarray, vx, vz, pvoxarray->sizeZ-vy-1, vi); //Reverse Y<>Z for left to right handed system
|
||||||
|
|
||||||
|
numVoxels--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strcmp(szChunkName, "RGBA") == 0)
|
||||||
|
{
|
||||||
|
VoxColor col;
|
||||||
|
|
||||||
|
//(each pixel: 1 byte x 4 : r, g, b, a ) x 256
|
||||||
|
for (int i = 0; i < 256 - 1; i++)
|
||||||
|
{
|
||||||
|
col.r = *((unsigned char*)fileDataPtr++);
|
||||||
|
col.g = *((unsigned char*)fileDataPtr++);
|
||||||
|
col.b = *((unsigned char*)fileDataPtr++);
|
||||||
|
col.a = *((unsigned char*)fileDataPtr++);
|
||||||
|
|
||||||
|
pvoxarray->palette[i + 1] = col;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fileDataPtr += chunkSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////
|
||||||
|
// Building Mesh
|
||||||
|
// TODO compute globals indices array
|
||||||
|
|
||||||
|
// Init Arrays
|
||||||
|
initArrayVector3(&pvoxarray->vertices, 3 * 1024);
|
||||||
|
initArrayUShort(&pvoxarray->indices, 3 * 1024);
|
||||||
|
initArrayColor(&pvoxarray->colors, 3 * 1024);
|
||||||
|
|
||||||
|
// Create vertices and indices buffers
|
||||||
|
int x, y, z;
|
||||||
|
|
||||||
|
for (x = 0; x <= pvoxarray->sizeX; x++)
|
||||||
|
{
|
||||||
|
for (z = 0; z <= pvoxarray->sizeZ; z++)
|
||||||
|
{
|
||||||
|
for (y = 0; y <= pvoxarray->sizeY; y++)
|
||||||
|
{
|
||||||
|
unsigned char matID = Vox_GetVoxel(pvoxarray, x, y, z);
|
||||||
|
if (matID != 0)
|
||||||
|
Vox_Build_Voxel(pvoxarray, x, y, z, matID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return VOX_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vox_FreeArrays(VoxArray3D* voxarray)
|
||||||
|
{
|
||||||
|
// Free chunks
|
||||||
|
if (voxarray->m_arrayChunks != 0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < voxarray->chunksTotal; i++)
|
||||||
|
{
|
||||||
|
CubeChunk3D* chunk = &voxarray->m_arrayChunks[i];
|
||||||
|
if (chunk->m_array != 0)
|
||||||
|
{
|
||||||
|
chunk->arraySize = 0;
|
||||||
|
VOX_FREE(chunk->m_array);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOX_FREE(voxarray->m_arrayChunks);
|
||||||
|
voxarray->m_arrayChunks = 0;
|
||||||
|
voxarray->arrayChunksSize = 0;
|
||||||
|
|
||||||
|
voxarray->chunksSizeX = voxarray->chunksSizeY = voxarray->chunksSizeZ = 0;
|
||||||
|
voxarray->chunksTotal = 0;
|
||||||
|
voxarray->chunksAllocated = 0;
|
||||||
|
voxarray->ChunkFlattenOffset = 0;
|
||||||
|
voxarray->sizeX = voxarray->sizeY = voxarray->sizeZ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free arrays
|
||||||
|
freeArrayVector3(&voxarray->vertices);
|
||||||
|
freeArrayUShort(&voxarray->indices);
|
||||||
|
freeArrayColor(&voxarray->colors);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //VOX_LOADER_IMPLEMENTATION
|
||||||
|
|
@ -220,14 +220,20 @@
|
||||||
int format; // Data format (PixelFormat type)
|
int format; // Data format (PixelFormat type)
|
||||||
} Texture2D;
|
} Texture2D;
|
||||||
|
|
||||||
// Font character info
|
// GlyphInfo, font characters glyphs info
|
||||||
typedef struct GlyphInfo GlyphInfo;
|
typedef struct GlyphInfo {
|
||||||
|
int value; // Character value (Unicode)
|
||||||
|
int offsetX; // Character offset X when drawing
|
||||||
|
int offsetY; // Character offset Y when drawing
|
||||||
|
int advanceX; // Character advance position X
|
||||||
|
Image image; // Character image data
|
||||||
|
} GlyphInfo;
|
||||||
|
|
||||||
// TODO: Font type is very coupled to raylib, mostly required by GuiLoadStyle()
|
// TODO: Font type is very coupled to raylib, mostly required by GuiLoadStyle()
|
||||||
// It should be redesigned to be provided by user
|
// It should be redesigned to be provided by user
|
||||||
typedef struct Font {
|
typedef struct Font {
|
||||||
int baseSize; // Base size (default chars height)
|
int baseSize; // Base size (default chars height)
|
||||||
int charsCount; // Number of characters
|
int glyphCount; // Number of characters
|
||||||
Texture2D texture; // Characters texture atlas
|
Texture2D texture; // Characters texture atlas
|
||||||
Rectangle *recs; // Characters rectangles in texture
|
Rectangle *recs; // Characters rectangles in texture
|
||||||
GlyphInfo *chars; // Characters info data
|
GlyphInfo *chars; // Characters info data
|
||||||
|
|
@ -406,7 +412,7 @@ typedef enum {
|
||||||
extern "C" { // Prevents name mangling of functions
|
extern "C" { // Prevents name mangling of functions
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// State modification functions
|
// Global gui state control functions
|
||||||
RAYGUIDEF void GuiEnable(void); // Enable gui controls (global state)
|
RAYGUIDEF void GuiEnable(void); // Enable gui controls (global state)
|
||||||
RAYGUIDEF void GuiDisable(void); // Disable gui controls (global state)
|
RAYGUIDEF void GuiDisable(void); // Disable gui controls (global state)
|
||||||
RAYGUIDEF void GuiLock(void); // Lock gui controls (global state)
|
RAYGUIDEF void GuiLock(void); // Lock gui controls (global state)
|
||||||
|
|
@ -1076,7 +1082,7 @@ static unsigned int guiIcons[RICON_MAX_ICONS*RICON_DATA_ELEMENTS] = {
|
||||||
|
|
||||||
// TODO: Avoid animations and time-based states
|
// TODO: Avoid animations and time-based states
|
||||||
// Functions using it: GuiTextBox(), GuiValueBox(), GuiTextBoxMulti()
|
// Functions using it: GuiTextBox(), GuiValueBox(), GuiTextBoxMulti()
|
||||||
#define TEXTEDIT_CURSOR_BLINK_FRAMES 20 // Text edit controls cursor blink timming
|
//#define TEXTEDIT_CURSOR_BLINK_FRAMES 20 // Text edit controls cursor blink timming
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Types and Structures Definition
|
// Types and Structures Definition
|
||||||
|
|
@ -1147,14 +1153,14 @@ static Font GetFontDefault(void); // -- GuiLoadStyleDe
|
||||||
static Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // -- GetTextWidth(), GuiTextBoxMulti()
|
static Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // -- GetTextWidth(), GuiTextBoxMulti()
|
||||||
static void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // -- GuiDrawText()
|
static void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // -- GuiDrawText()
|
||||||
|
|
||||||
static Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int charsCount); // -- GuiLoadStyle()
|
static Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int glyphCount); // -- GuiLoadStyle()
|
||||||
static char *LoadFileText(const char *fileName); // -- GuiLoadStyle()
|
static char *LoadFileText(const char *fileName); // -- GuiLoadStyle()
|
||||||
static const char *GetDirectoryPath(const char *filePath); // -- GuiLoadStyle()
|
static const char *GetDirectoryPath(const char *filePath); // -- GuiLoadStyle()
|
||||||
//-------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
// raylib functions already implemented in raygui
|
// raylib functions already implemented in raygui
|
||||||
//-------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------
|
||||||
static Color GetColor(unsigned int hexValue); // Returns a Color struct from hexadecimal value
|
static Color GetColor(int hexValue); // Returns a Color struct from hexadecimal value
|
||||||
static int ColorToInt(Color color); // Returns hexadecimal value for a Color
|
static int ColorToInt(Color color); // Returns hexadecimal value for a Color
|
||||||
static Color Fade(Color color, float alpha); // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f
|
static Color Fade(Color color, float alpha); // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f
|
||||||
static bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle
|
static bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle
|
||||||
|
|
@ -1594,7 +1600,7 @@ bool GuiImageButtonEx(Rectangle bounds, const char *text, Texture2D texture, Rec
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
GuiDrawRectangle(bounds, GuiGetStyle(BUTTON, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(BUTTON, BORDER + (state*3))), guiAlpha), Fade(GetColor(GuiGetStyle(BUTTON, BASE + (state*3))), guiAlpha));
|
GuiDrawRectangle(bounds, GuiGetStyle(BUTTON, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(BUTTON, BORDER + (state*3))), guiAlpha), Fade(GetColor(GuiGetStyle(BUTTON, BASE + (state*3))), guiAlpha));
|
||||||
|
|
||||||
if (text != NULL) GuiDrawText(text, GetTextBounds(BUTTON, bounds), GuiGetStyle(BUTTON, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(BUTTON, TEXT + (state*3))), guiAlpha));
|
GuiDrawText(text, GetTextBounds(BUTTON, bounds), GuiGetStyle(BUTTON, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(BUTTON, TEXT + (state*3))), guiAlpha));
|
||||||
if (texture.id > 0) DrawTextureRec(texture, texSource, RAYGUI_CLITERAL(Vector2){ bounds.x + bounds.width/2 - texSource.width/2, bounds.y + bounds.height/2 - texSource.height/2 }, Fade(GetColor(GuiGetStyle(BUTTON, TEXT + (state*3))), guiAlpha));
|
if (texture.id > 0) DrawTextureRec(texture, texSource, RAYGUI_CLITERAL(Vector2){ bounds.x + bounds.width/2 - texSource.width/2, bounds.y + bounds.height/2 - texSource.height/2 }, Fade(GetColor(GuiGetStyle(BUTTON, TEXT + (state*3))), guiAlpha));
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
@ -1654,12 +1660,12 @@ int GuiToggleGroup(Rectangle bounds, const char *text, int active)
|
||||||
|
|
||||||
// Get substrings items from text (items pointers)
|
// Get substrings items from text (items pointers)
|
||||||
int rows[TOGGLEGROUP_MAX_ELEMENTS] = { 0 };
|
int rows[TOGGLEGROUP_MAX_ELEMENTS] = { 0 };
|
||||||
int itemsCount = 0;
|
int itemCount = 0;
|
||||||
const char **items = GuiTextSplit(text, &itemsCount, rows);
|
const char **items = GuiTextSplit(text, &itemCount, rows);
|
||||||
|
|
||||||
int prevRow = rows[0];
|
int prevRow = rows[0];
|
||||||
|
|
||||||
for (int i = 0; i < itemsCount; i++)
|
for (int i = 0; i < itemCount; i++)
|
||||||
{
|
{
|
||||||
if (prevRow != rows[i])
|
if (prevRow != rows[i])
|
||||||
{
|
{
|
||||||
|
|
@ -1730,7 +1736,7 @@ bool GuiCheckBox(Rectangle bounds, const char *text, bool checked)
|
||||||
GuiDrawRectangle(check, 0, BLANK, Fade(GetColor(GuiGetStyle(CHECKBOX, TEXT + state*3)), guiAlpha));
|
GuiDrawRectangle(check, 0, BLANK, Fade(GetColor(GuiGetStyle(CHECKBOX, TEXT + state*3)), guiAlpha));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (text != NULL) GuiDrawText(text, textBounds, (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == GUI_TEXT_ALIGN_RIGHT)? GUI_TEXT_ALIGN_LEFT : GUI_TEXT_ALIGN_RIGHT, Fade(GetColor(GuiGetStyle(LABEL, TEXT + (state*3))), guiAlpha));
|
GuiDrawText(text, textBounds, (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == GUI_TEXT_ALIGN_RIGHT)? GUI_TEXT_ALIGN_LEFT : GUI_TEXT_ALIGN_RIGHT, Fade(GetColor(GuiGetStyle(LABEL, TEXT + (state*3))), guiAlpha));
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
return checked;
|
return checked;
|
||||||
|
|
@ -1747,15 +1753,15 @@ int GuiComboBox(Rectangle bounds, const char *text, int active)
|
||||||
(float)bounds.y, (float)GuiGetStyle(COMBOBOX, COMBO_BUTTON_WIDTH), (float)bounds.height };
|
(float)bounds.y, (float)GuiGetStyle(COMBOBOX, COMBO_BUTTON_WIDTH), (float)bounds.height };
|
||||||
|
|
||||||
// Get substrings items from text (items pointers, lengths and count)
|
// Get substrings items from text (items pointers, lengths and count)
|
||||||
int itemsCount = 0;
|
int itemCount = 0;
|
||||||
const char **items = GuiTextSplit(text, &itemsCount, NULL);
|
const char **items = GuiTextSplit(text, &itemCount, NULL);
|
||||||
|
|
||||||
if (active < 0) active = 0;
|
if (active < 0) active = 0;
|
||||||
else if (active > itemsCount - 1) active = itemsCount - 1;
|
else if (active > itemCount - 1) active = itemCount - 1;
|
||||||
|
|
||||||
// Update control
|
// Update control
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
if ((state != GUI_STATE_DISABLED) && !guiLocked && (itemsCount > 1))
|
if ((state != GUI_STATE_DISABLED) && !guiLocked && (itemCount > 1))
|
||||||
{
|
{
|
||||||
Vector2 mousePoint = GetMousePosition();
|
Vector2 mousePoint = GetMousePosition();
|
||||||
|
|
||||||
|
|
@ -1765,7 +1771,7 @@ int GuiComboBox(Rectangle bounds, const char *text, int active)
|
||||||
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
|
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
|
||||||
{
|
{
|
||||||
active += 1;
|
active += 1;
|
||||||
if (active >= itemsCount) active = 0;
|
if (active >= itemCount) active = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = GUI_STATE_PRESSED;
|
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = GUI_STATE_PRESSED;
|
||||||
|
|
@ -1787,7 +1793,7 @@ int GuiComboBox(Rectangle bounds, const char *text, int active)
|
||||||
GuiSetStyle(BUTTON, BORDER_WIDTH, 1);
|
GuiSetStyle(BUTTON, BORDER_WIDTH, 1);
|
||||||
GuiSetStyle(BUTTON, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER);
|
GuiSetStyle(BUTTON, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER);
|
||||||
|
|
||||||
GuiButton(selector, TextFormat("%i/%i", active + 1, itemsCount));
|
GuiButton(selector, TextFormat("%i/%i", active + 1, itemCount));
|
||||||
|
|
||||||
GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlign);
|
GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlign);
|
||||||
GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth);
|
GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth);
|
||||||
|
|
@ -1805,11 +1811,11 @@ bool GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMo
|
||||||
int itemFocused = -1;
|
int itemFocused = -1;
|
||||||
|
|
||||||
// Get substrings items from text (items pointers, lengths and count)
|
// Get substrings items from text (items pointers, lengths and count)
|
||||||
int itemsCount = 0;
|
int itemCount = 0;
|
||||||
const char **items = GuiTextSplit(text, &itemsCount, NULL);
|
const char **items = GuiTextSplit(text, &itemCount, NULL);
|
||||||
|
|
||||||
Rectangle boundsOpen = bounds;
|
Rectangle boundsOpen = bounds;
|
||||||
boundsOpen.height = (itemsCount + 1)*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_PADDING));
|
boundsOpen.height = (itemCount + 1)*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_PADDING));
|
||||||
|
|
||||||
Rectangle itemBounds = bounds;
|
Rectangle itemBounds = bounds;
|
||||||
|
|
||||||
|
|
@ -1817,7 +1823,7 @@ bool GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMo
|
||||||
|
|
||||||
// Update control
|
// Update control
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
if ((state != GUI_STATE_DISABLED) && !guiLocked && (itemsCount > 1))
|
if ((state != GUI_STATE_DISABLED) && !guiLocked && (itemCount > 1))
|
||||||
{
|
{
|
||||||
Vector2 mousePoint = GetMousePosition();
|
Vector2 mousePoint = GetMousePosition();
|
||||||
|
|
||||||
|
|
@ -1835,7 +1841,7 @@ bool GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMo
|
||||||
if (CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) pressed = true;
|
if (CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) pressed = true;
|
||||||
|
|
||||||
// Check focused and selected item
|
// Check focused and selected item
|
||||||
for (int i = 0; i < itemsCount; i++)
|
for (int i = 0; i < itemCount; i++)
|
||||||
{
|
{
|
||||||
// Update item rectangle y position for next item
|
// Update item rectangle y position for next item
|
||||||
itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_PADDING));
|
itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_PADDING));
|
||||||
|
|
@ -1879,7 +1885,7 @@ bool GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMo
|
||||||
if (editMode)
|
if (editMode)
|
||||||
{
|
{
|
||||||
// Draw visible items
|
// Draw visible items
|
||||||
for (int i = 0; i < itemsCount; i++)
|
for (int i = 0; i < itemCount; i++)
|
||||||
{
|
{
|
||||||
// Update item rectangle y position for next item
|
// Update item rectangle y position for next item
|
||||||
itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_PADDING));
|
itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_PADDING));
|
||||||
|
|
@ -1913,19 +1919,16 @@ bool GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMo
|
||||||
}
|
}
|
||||||
|
|
||||||
// Text Box control, updates input text
|
// Text Box control, updates input text
|
||||||
// NOTE 1: Requires static variables: framesCounter
|
|
||||||
// NOTE 2: Returns if KEY_ENTER pressed (useful for data validation)
|
// NOTE 2: Returns if KEY_ENTER pressed (useful for data validation)
|
||||||
bool GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode)
|
bool GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode)
|
||||||
{
|
{
|
||||||
static int framesCounter = 0; // Blinking cursor counter
|
|
||||||
|
|
||||||
GuiControlState state = guiState;
|
GuiControlState state = guiState;
|
||||||
bool pressed = false;
|
bool pressed = false;
|
||||||
|
|
||||||
Rectangle cursor = {
|
Rectangle cursor = {
|
||||||
bounds.x + GuiGetStyle(TEXTBOX, TEXT_PADDING) + GetTextWidth(text) + 2,
|
bounds.x + GuiGetStyle(TEXTBOX, TEXT_PADDING) + GetTextWidth(text) + 2,
|
||||||
bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE),
|
bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE),
|
||||||
1,
|
4,
|
||||||
(float)GuiGetStyle(DEFAULT, TEXT_SIZE)*2
|
(float)GuiGetStyle(DEFAULT, TEXT_SIZE)*2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1938,7 +1941,6 @@ bool GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode)
|
||||||
if (editMode)
|
if (editMode)
|
||||||
{
|
{
|
||||||
state = GUI_STATE_PRESSED;
|
state = GUI_STATE_PRESSED;
|
||||||
framesCounter++;
|
|
||||||
|
|
||||||
int key = GetCharPressed(); // Returns codepoint as Unicode
|
int key = GetCharPressed(); // Returns codepoint as Unicode
|
||||||
int keyCount = (int)strlen(text);
|
int keyCount = (int)strlen(text);
|
||||||
|
|
@ -1950,10 +1952,10 @@ bool GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode)
|
||||||
|
|
||||||
if ((GetTextWidth(text) < (maxWidth - GuiGetStyle(DEFAULT, TEXT_SIZE))) && (key >= 32))
|
if ((GetTextWidth(text) < (maxWidth - GuiGetStyle(DEFAULT, TEXT_SIZE))) && (key >= 32))
|
||||||
{
|
{
|
||||||
int byteLength = 0;
|
int byteSize = 0;
|
||||||
const char *textUTF8 = CodepointToUTF8(key, &byteLength);
|
const char *textUTF8 = CodepointToUTF8(key, &byteSize);
|
||||||
|
|
||||||
for (int i = 0; i < byteLength; i++)
|
for (int i = 0; i < byteSize; i++)
|
||||||
{
|
{
|
||||||
text[keyCount] = textUTF8[i];
|
text[keyCount] = textUTF8[i];
|
||||||
keyCount++;
|
keyCount++;
|
||||||
|
|
@ -1970,13 +1972,6 @@ bool GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode)
|
||||||
{
|
{
|
||||||
keyCount--;
|
keyCount--;
|
||||||
text[keyCount] = '\0';
|
text[keyCount] = '\0';
|
||||||
framesCounter = 0;
|
|
||||||
if (keyCount < 0) keyCount = 0;
|
|
||||||
}
|
|
||||||
else if (IsKeyDown(KEY_BACKSPACE))
|
|
||||||
{
|
|
||||||
if ((framesCounter > TEXTEDIT_CURSOR_BLINK_FRAMES) && (framesCounter%2) == 0) keyCount--;
|
|
||||||
text[keyCount] = '\0';
|
|
||||||
if (keyCount < 0) keyCount = 0;
|
if (keyCount < 0) keyCount = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1996,8 +1991,6 @@ bool GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode)
|
||||||
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) pressed = true;
|
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) pressed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pressed) framesCounter = 0;
|
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
@ -2006,9 +1999,6 @@ bool GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode)
|
||||||
if (state == GUI_STATE_PRESSED)
|
if (state == GUI_STATE_PRESSED)
|
||||||
{
|
{
|
||||||
GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), guiAlpha), Fade(GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_PRESSED)), guiAlpha));
|
GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), guiAlpha), Fade(GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_PRESSED)), guiAlpha));
|
||||||
|
|
||||||
// Draw blinking cursor
|
|
||||||
if (editMode && ((framesCounter/20)%2 == 0)) GuiDrawRectangle(cursor, 0, BLANK, Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_PRESSED)), guiAlpha));
|
|
||||||
}
|
}
|
||||||
else if (state == GUI_STATE_DISABLED)
|
else if (state == GUI_STATE_DISABLED)
|
||||||
{
|
{
|
||||||
|
|
@ -2017,6 +2007,9 @@ bool GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode)
|
||||||
else GuiDrawRectangle(bounds, 1, Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), guiAlpha), BLANK);
|
else GuiDrawRectangle(bounds, 1, Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), guiAlpha), BLANK);
|
||||||
|
|
||||||
GuiDrawText(text, GetTextBounds(TEXTBOX, bounds), GuiGetStyle(TEXTBOX, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(TEXTBOX, TEXT + (state*3))), guiAlpha));
|
GuiDrawText(text, GetTextBounds(TEXTBOX, bounds), GuiGetStyle(TEXTBOX, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(TEXTBOX, TEXT + (state*3))), guiAlpha));
|
||||||
|
|
||||||
|
// Draw cursor
|
||||||
|
if (editMode) GuiDrawRectangle(cursor, 0, BLANK, Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_PRESSED)), guiAlpha));
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
return pressed;
|
return pressed;
|
||||||
|
|
@ -2090,7 +2083,7 @@ bool GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, in
|
||||||
GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth);
|
GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth);
|
||||||
|
|
||||||
// Draw text label if provided
|
// Draw text label if provided
|
||||||
if (text != NULL) GuiDrawText(text, textBounds, (GuiGetStyle(SPINNER, TEXT_ALIGNMENT) == GUI_TEXT_ALIGN_RIGHT)? GUI_TEXT_ALIGN_LEFT : GUI_TEXT_ALIGN_RIGHT, Fade(GetColor(GuiGetStyle(LABEL, TEXT + (state*3))), guiAlpha));
|
GuiDrawText(text, textBounds, (GuiGetStyle(SPINNER, TEXT_ALIGNMENT) == GUI_TEXT_ALIGN_RIGHT)? GUI_TEXT_ALIGN_LEFT : GUI_TEXT_ALIGN_RIGHT, Fade(GetColor(GuiGetStyle(LABEL, TEXT + (state*3))), guiAlpha));
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
*value = tempValue;
|
*value = tempValue;
|
||||||
|
|
@ -2098,15 +2091,13 @@ bool GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, in
|
||||||
}
|
}
|
||||||
|
|
||||||
// Value Box control, updates input text with numbers
|
// Value Box control, updates input text with numbers
|
||||||
// NOTE: Requires static variables: framesCounter
|
// NOTE: Requires static variables: frameCounter
|
||||||
bool GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode)
|
bool GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode)
|
||||||
{
|
{
|
||||||
#if !defined(VALUEBOX_MAX_CHARS)
|
#if !defined(VALUEBOX_MAX_CHARS)
|
||||||
#define VALUEBOX_MAX_CHARS 32
|
#define VALUEBOX_MAX_CHARS 32
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int framesCounter = 0; // Blinking cursor counter
|
|
||||||
|
|
||||||
GuiControlState state = guiState;
|
GuiControlState state = guiState;
|
||||||
bool pressed = false;
|
bool pressed = false;
|
||||||
|
|
||||||
|
|
@ -2135,8 +2126,6 @@ bool GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, i
|
||||||
{
|
{
|
||||||
state = GUI_STATE_PRESSED;
|
state = GUI_STATE_PRESSED;
|
||||||
|
|
||||||
framesCounter++;
|
|
||||||
|
|
||||||
int keyCount = (int)strlen(textValue);
|
int keyCount = (int)strlen(textValue);
|
||||||
|
|
||||||
// Only allow keys in range [48..57]
|
// Only allow keys in range [48..57]
|
||||||
|
|
@ -2161,14 +2150,6 @@ bool GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, i
|
||||||
{
|
{
|
||||||
keyCount--;
|
keyCount--;
|
||||||
textValue[keyCount] = '\0';
|
textValue[keyCount] = '\0';
|
||||||
framesCounter = 0;
|
|
||||||
if (keyCount < 0) keyCount = 0;
|
|
||||||
valueHasChanged = true;
|
|
||||||
}
|
|
||||||
else if (IsKeyDown(KEY_BACKSPACE))
|
|
||||||
{
|
|
||||||
if ((framesCounter > TEXTEDIT_CURSOR_BLINK_FRAMES) && (framesCounter%2) == 0) keyCount--;
|
|
||||||
textValue[keyCount] = '\0';
|
|
||||||
if (keyCount < 0) keyCount = 0;
|
if (keyCount < 0) keyCount = 0;
|
||||||
valueHasChanged = true;
|
valueHasChanged = true;
|
||||||
}
|
}
|
||||||
|
|
@ -2189,8 +2170,6 @@ bool GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, i
|
||||||
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) pressed = true;
|
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) pressed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pressed) framesCounter = 0;
|
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
@ -2204,16 +2183,16 @@ bool GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, i
|
||||||
GuiDrawRectangle(bounds, GuiGetStyle(VALUEBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(VALUEBOX, BORDER + (state*3))), guiAlpha), baseColor);
|
GuiDrawRectangle(bounds, GuiGetStyle(VALUEBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(VALUEBOX, BORDER + (state*3))), guiAlpha), baseColor);
|
||||||
GuiDrawText(textValue, GetTextBounds(VALUEBOX, bounds), GUI_TEXT_ALIGN_CENTER, Fade(GetColor(GuiGetStyle(VALUEBOX, TEXT + (state*3))), guiAlpha));
|
GuiDrawText(textValue, GetTextBounds(VALUEBOX, bounds), GUI_TEXT_ALIGN_CENTER, Fade(GetColor(GuiGetStyle(VALUEBOX, TEXT + (state*3))), guiAlpha));
|
||||||
|
|
||||||
// Draw blinking cursor
|
// Draw cursor
|
||||||
if ((state == GUI_STATE_PRESSED) && (editMode && ((framesCounter/20)%2 == 0)))
|
if (editMode)
|
||||||
{
|
{
|
||||||
// NOTE: ValueBox internal text is always centered
|
// NOTE: ValueBox internal text is always centered
|
||||||
Rectangle cursor = { bounds.x + GetTextWidth(textValue)/2 + bounds.width/2 + 2, bounds.y + 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), 1, bounds.height - 4*GuiGetStyle(VALUEBOX, BORDER_WIDTH) };
|
Rectangle cursor = { bounds.x + GetTextWidth(textValue)/2 + bounds.width/2 + 2, bounds.y + 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), 4, bounds.height - 4*GuiGetStyle(VALUEBOX, BORDER_WIDTH) };
|
||||||
GuiDrawRectangle(cursor, 0, BLANK, Fade(GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED)), guiAlpha));
|
GuiDrawRectangle(cursor, 0, BLANK, Fade(GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED)), guiAlpha));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw text label if provided
|
// Draw text label if provided
|
||||||
if (text != NULL) GuiDrawText(text, textBounds, (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == GUI_TEXT_ALIGN_RIGHT)? GUI_TEXT_ALIGN_LEFT : GUI_TEXT_ALIGN_RIGHT, Fade(GetColor(GuiGetStyle(LABEL, TEXT + (state*3))), guiAlpha));
|
GuiDrawText(text, textBounds, (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == GUI_TEXT_ALIGN_RIGHT)? GUI_TEXT_ALIGN_LEFT : GUI_TEXT_ALIGN_RIGHT, Fade(GetColor(GuiGetStyle(LABEL, TEXT + (state*3))), guiAlpha));
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
return pressed;
|
return pressed;
|
||||||
|
|
@ -2222,8 +2201,6 @@ bool GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, i
|
||||||
// Text Box control with multiple lines
|
// Text Box control with multiple lines
|
||||||
bool GuiTextBoxMulti(Rectangle bounds, char *text, int textSize, bool editMode)
|
bool GuiTextBoxMulti(Rectangle bounds, char *text, int textSize, bool editMode)
|
||||||
{
|
{
|
||||||
static int framesCounter = 0; // Blinking cursor counter
|
|
||||||
|
|
||||||
GuiControlState state = guiState;
|
GuiControlState state = guiState;
|
||||||
bool pressed = false;
|
bool pressed = false;
|
||||||
|
|
||||||
|
|
@ -2235,10 +2212,9 @@ bool GuiTextBoxMulti(Rectangle bounds, char *text, int textSize, bool editMode)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Cursor position, [x, y] values should be updated
|
// Cursor position, [x, y] values should be updated
|
||||||
Rectangle cursor = { 0, 0, 1, (float)GuiGetStyle(DEFAULT, TEXT_SIZE) + 2 };
|
Rectangle cursor = { 0, -1, 4, (float)GuiGetStyle(DEFAULT, TEXT_SIZE) + 2 };
|
||||||
|
|
||||||
int textWidth = 0;
|
float scaleFactor = (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/(float)guiFont.baseSize; // Character rectangle scaling factor
|
||||||
int currentLine = 0;
|
|
||||||
|
|
||||||
// Update control
|
// Update control
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
|
@ -2249,76 +2225,51 @@ bool GuiTextBoxMulti(Rectangle bounds, char *text, int textSize, bool editMode)
|
||||||
if (editMode)
|
if (editMode)
|
||||||
{
|
{
|
||||||
state = GUI_STATE_PRESSED;
|
state = GUI_STATE_PRESSED;
|
||||||
framesCounter++;
|
|
||||||
|
|
||||||
int character = GetCharPressed();
|
// We get an Unicode codepoint
|
||||||
int keyCount = (int)strlen(text);
|
int codepoint = GetCharPressed();
|
||||||
|
int textLength = (int)strlen(text); // Length in bytes (UTF-8 string)
|
||||||
|
|
||||||
// Introduce characters
|
// Introduce characters
|
||||||
if (keyCount < (textSize - 1))
|
if (textLength < (textSize - 1))
|
||||||
{
|
|
||||||
Vector2 textSize = MeasureTextEx(guiFont, text, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
|
|
||||||
|
|
||||||
if (textSize.y < (textAreaBounds.height - GuiGetStyle(DEFAULT, TEXT_SIZE)))
|
|
||||||
{
|
{
|
||||||
if (IsKeyPressed(KEY_ENTER))
|
if (IsKeyPressed(KEY_ENTER))
|
||||||
{
|
{
|
||||||
text[keyCount] = '\n';
|
text[textLength] = '\n';
|
||||||
keyCount++;
|
textLength++;
|
||||||
}
|
}
|
||||||
else if (((character >= 32) && (character < 255))) // TODO: Support Unicode inputs
|
else if (codepoint >= 32)
|
||||||
{
|
{
|
||||||
text[keyCount] = (char)character;
|
// Supports Unicode inputs -> Encoded to UTF-8
|
||||||
keyCount++;
|
int charUTF8Length = 0;
|
||||||
}
|
const char *charEncoded = CodepointToUTF8(codepoint, &charUTF8Length);
|
||||||
|
memcpy(text + textLength, charEncoded, charUTF8Length);
|
||||||
|
textLength += charUTF8Length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete characters
|
// Delete characters
|
||||||
if (keyCount > 0)
|
if (textLength > 0)
|
||||||
{
|
{
|
||||||
if (IsKeyPressed(KEY_BACKSPACE))
|
if (IsKeyPressed(KEY_BACKSPACE))
|
||||||
{
|
{
|
||||||
keyCount--;
|
if ((unsigned char)text[textLength - 1] < 127)
|
||||||
text[keyCount] = '\0';
|
|
||||||
framesCounter = 0;
|
|
||||||
|
|
||||||
if (keyCount < 0) keyCount = 0;
|
|
||||||
}
|
|
||||||
else if (IsKeyDown(KEY_BACKSPACE))
|
|
||||||
{
|
{
|
||||||
if ((framesCounter > TEXTEDIT_CURSOR_BLINK_FRAMES) && (framesCounter%2) == 0) keyCount--;
|
// Remove ASCII equivalent character (1 byte)
|
||||||
text[keyCount] = '\0';
|
textLength--;
|
||||||
|
text[textLength] = '\0';
|
||||||
if (keyCount < 0) keyCount = 0;
|
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
|
||||||
// Calculate cursor position considering text
|
|
||||||
char oneCharText[2] = { 0 };
|
|
||||||
int lastBreakingPos = -1;
|
|
||||||
|
|
||||||
for (int i = 0; i < keyCount && currentLine < keyCount; i++)
|
|
||||||
{
|
{
|
||||||
oneCharText[0] = text[i];
|
// Remove latest UTF-8 unicode character introduced (n bytes)
|
||||||
textWidth += (GetTextWidth(oneCharText) + GuiGetStyle(DEFAULT, TEXT_SPACING));
|
int charUTF8Length = 0;
|
||||||
|
while (((unsigned char)text[textLength - 1 - charUTF8Length] & 0b01000000) == 0) charUTF8Length++;
|
||||||
|
|
||||||
if (text[i] == ' ' || text[i] == '\n') lastBreakingPos = i;
|
textLength -= (charUTF8Length + 1);
|
||||||
|
text[textLength] = '\0';
|
||||||
if ( text[i] == '\n' || textWidth >= textAreaBounds.width)
|
}
|
||||||
{
|
|
||||||
currentLine++;
|
|
||||||
textWidth = 0;
|
|
||||||
|
|
||||||
if (lastBreakingPos > 0) i = lastBreakingPos;
|
|
||||||
else textWidth += (GetTextWidth(oneCharText) + GuiGetStyle(DEFAULT, TEXT_SPACING));
|
|
||||||
|
|
||||||
lastBreakingPos = -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor.x = bounds.x + GuiGetStyle(TEXTBOX, BORDER_WIDTH) + GuiGetStyle(TEXTBOX, TEXT_INNER_PADDING) + textWidth - GuiGetStyle(DEFAULT, TEXT_SPACING);
|
|
||||||
cursor.y = bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH) + GuiGetStyle(TEXTBOX, TEXT_INNER_PADDING)/2 + ((GuiGetStyle(DEFAULT, TEXT_SIZE) + GuiGetStyle(TEXTBOX, TEXT_INNER_PADDING))*currentLine);
|
|
||||||
|
|
||||||
// Exit edit mode
|
// Exit edit mode
|
||||||
if (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) pressed = true;
|
if (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) pressed = true;
|
||||||
|
|
@ -2331,8 +2282,6 @@ bool GuiTextBoxMulti(Rectangle bounds, char *text, int textSize, bool editMode)
|
||||||
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) pressed = true;
|
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) pressed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pressed) framesCounter = 0; // Reset blinking cursor
|
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
@ -2341,9 +2290,6 @@ bool GuiTextBoxMulti(Rectangle bounds, char *text, int textSize, bool editMode)
|
||||||
if (state == GUI_STATE_PRESSED)
|
if (state == GUI_STATE_PRESSED)
|
||||||
{
|
{
|
||||||
GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), guiAlpha), Fade(GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_PRESSED)), guiAlpha));
|
GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), guiAlpha), Fade(GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_PRESSED)), guiAlpha));
|
||||||
|
|
||||||
// Draw blinking cursor
|
|
||||||
if (editMode && ((framesCounter/20)%2 == 0)) GuiDrawRectangle(cursor, 0, BLANK, Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_PRESSED)), guiAlpha));
|
|
||||||
}
|
}
|
||||||
else if (state == GUI_STATE_DISABLED)
|
else if (state == GUI_STATE_DISABLED)
|
||||||
{
|
{
|
||||||
|
|
@ -2351,9 +2297,76 @@ bool GuiTextBoxMulti(Rectangle bounds, char *text, int textSize, bool editMode)
|
||||||
}
|
}
|
||||||
else GuiDrawRectangle(bounds, 1, Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), guiAlpha), BLANK);
|
else GuiDrawRectangle(bounds, 1, Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), guiAlpha), BLANK);
|
||||||
|
|
||||||
// TODO: Review to support boxed text with word-wrap
|
int wrapMode = 1; // 0-No wrap, 1-Char wrap, 2-Word wrap
|
||||||
//DrawTextBoxed(guiFont, text, textAreaBounds, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), (float)GuiGetStyle(DEFAULT, TEXT_SPACING), true, Fade(GetColor(GuiGetStyle(TEXTBOX, TEXT + (state*3))), guiAlpha));
|
Vector2 cursorPos = { textAreaBounds.x, textAreaBounds.y };
|
||||||
DrawTextEx(guiFont, text, (Vector2){ textAreaBounds.x, textAreaBounds.y }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), (float)GuiGetStyle(DEFAULT, TEXT_SPACING), Fade(GetColor(GuiGetStyle(TEXTBOX, TEXT + (state*3))), guiAlpha));
|
|
||||||
|
//int lastSpacePos = 0;
|
||||||
|
//int lastSpaceWidth = 0;
|
||||||
|
//int lastSpaceCursorPos = 0;
|
||||||
|
|
||||||
|
for (int i = 0, codepointLength = 0; text[i] != '\0'; i += codepointLength)
|
||||||
|
{
|
||||||
|
int codepoint = GetCodepoint(text + i, &codepointLength);
|
||||||
|
int index = GetGlyphIndex(guiFont, codepoint); // If requested codepoint is not found, we get '?' (0x3f) -> TODO: review that case!
|
||||||
|
Rectangle atlasRec = guiFont.recs[index];
|
||||||
|
GlyphInfo glyphInfo = guiFont.glyphs[index]; // Glyph measures
|
||||||
|
|
||||||
|
if ((codepointLength == 1) && (codepoint == '\n'))
|
||||||
|
{
|
||||||
|
cursorPos.y += (guiFont.baseSize*scaleFactor + GuiGetStyle(TEXTBOX, TEXT_LINES_PADDING)); // Line feed
|
||||||
|
cursorPos.x = textAreaBounds.x; // Carriage return
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (wrapMode == 1)
|
||||||
|
{
|
||||||
|
int glyphWidth = 0;
|
||||||
|
if (glyphInfo.advanceX != 0) glyphWidth += glyphInfo.advanceX;
|
||||||
|
else glyphWidth += (atlasRec.width + glyphInfo.offsetX);
|
||||||
|
|
||||||
|
// Jump line if the end of the text box area has been reached
|
||||||
|
if ((cursorPos.x + (glyphWidth*scaleFactor)) > (textAreaBounds.x + textAreaBounds.width))
|
||||||
|
{
|
||||||
|
cursorPos.y += (guiFont.baseSize*scaleFactor + GuiGetStyle(TEXTBOX, TEXT_LINES_PADDING)); // Line feed
|
||||||
|
cursorPos.x = textAreaBounds.x; // Carriage return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (wrapMode == 2)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
if ((codepointLength == 1) && (codepoint == ' '))
|
||||||
|
{
|
||||||
|
lastSpacePos = i;
|
||||||
|
lastSpaceWidth = 0;
|
||||||
|
lastSpaceCursorPos = cursorPos.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jump line if last word reaches end of text box area
|
||||||
|
if ((lastSpaceCursorPos + lastSpaceWidth) > (textAreaBounds.x + textAreaBounds.width))
|
||||||
|
{
|
||||||
|
cursorPos.y += 12; // Line feed
|
||||||
|
cursorPos.x = textAreaBounds.x; // Carriage return
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw current character glyph
|
||||||
|
DrawTextCodepoint(guiFont, codepoint, cursorPos, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), Fade(GetColor(GuiGetStyle(TEXTBOX, TEXT + (state*3))), guiAlpha));
|
||||||
|
|
||||||
|
int glyphWidth = 0;
|
||||||
|
if (glyphInfo.advanceX != 0) glyphWidth += glyphInfo.advanceX;
|
||||||
|
else glyphWidth += (atlasRec.width + glyphInfo.offsetX);
|
||||||
|
|
||||||
|
cursorPos.x += (glyphWidth*scaleFactor + (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
|
||||||
|
//if (i > lastSpacePos) lastSpaceWidth += (atlasRec.width + (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor.x = cursorPos.x;
|
||||||
|
cursor.y = cursorPos.y;
|
||||||
|
|
||||||
|
// Draw cursor position considering text glyphs
|
||||||
|
if (editMode) GuiDrawRectangle(cursor, 0, BLANK, Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_PRESSED)), guiAlpha));
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
return pressed;
|
return pressed;
|
||||||
|
|
@ -2698,12 +2711,12 @@ int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue)
|
||||||
// List View control
|
// List View control
|
||||||
int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int active)
|
int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int active)
|
||||||
{
|
{
|
||||||
int itemsCount = 0;
|
int itemCount = 0;
|
||||||
const char **items = NULL;
|
const char **items = NULL;
|
||||||
|
|
||||||
if (text != NULL) items = GuiTextSplit(text, &itemsCount, NULL);
|
if (text != NULL) items = GuiTextSplit(text, &itemCount, NULL);
|
||||||
|
|
||||||
return GuiListViewEx(bounds, items, itemsCount, NULL, scrollIndex, active);
|
return GuiListViewEx(bounds, items, itemCount, NULL, scrollIndex, active);
|
||||||
}
|
}
|
||||||
|
|
||||||
// List View control with extended parameters
|
// List View control with extended parameters
|
||||||
|
|
@ -3096,12 +3109,12 @@ int GuiMessageBox(Rectangle bounds, const char *title, const char *message, cons
|
||||||
|
|
||||||
int clicked = -1; // Returns clicked button from buttons list, 0 refers to closed window button
|
int clicked = -1; // Returns clicked button from buttons list, 0 refers to closed window button
|
||||||
|
|
||||||
int buttonsCount = 0;
|
int buttonCount = 0;
|
||||||
const char **buttonsText = GuiTextSplit(buttons, &buttonsCount, NULL);
|
const char **buttonsText = GuiTextSplit(buttons, &buttonCount, NULL);
|
||||||
Rectangle buttonBounds = { 0 };
|
Rectangle buttonBounds = { 0 };
|
||||||
buttonBounds.x = bounds.x + MESSAGEBOX_BUTTON_PADDING;
|
buttonBounds.x = bounds.x + MESSAGEBOX_BUTTON_PADDING;
|
||||||
buttonBounds.y = bounds.y + bounds.height - MESSAGEBOX_BUTTON_HEIGHT - MESSAGEBOX_BUTTON_PADDING;
|
buttonBounds.y = bounds.y + bounds.height - MESSAGEBOX_BUTTON_HEIGHT - MESSAGEBOX_BUTTON_PADDING;
|
||||||
buttonBounds.width = (bounds.width - MESSAGEBOX_BUTTON_PADDING*(buttonsCount + 1))/buttonsCount;
|
buttonBounds.width = (bounds.width - MESSAGEBOX_BUTTON_PADDING*(buttonCount + 1))/buttonCount;
|
||||||
buttonBounds.height = MESSAGEBOX_BUTTON_HEIGHT;
|
buttonBounds.height = MESSAGEBOX_BUTTON_HEIGHT;
|
||||||
|
|
||||||
Vector2 textSize = MeasureTextEx(guiFont, message, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), 1);
|
Vector2 textSize = MeasureTextEx(guiFont, message, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), 1);
|
||||||
|
|
@ -3124,7 +3137,7 @@ int GuiMessageBox(Rectangle bounds, const char *title, const char *message, cons
|
||||||
prevTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
|
prevTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
|
||||||
GuiSetStyle(BUTTON, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER);
|
GuiSetStyle(BUTTON, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER);
|
||||||
|
|
||||||
for (int i = 0; i < buttonsCount; i++)
|
for (int i = 0; i < buttonCount; i++)
|
||||||
{
|
{
|
||||||
if (GuiButton(buttonBounds, buttonsText[i])) clicked = i + 1;
|
if (GuiButton(buttonBounds, buttonsText[i])) clicked = i + 1;
|
||||||
buttonBounds.x += (buttonBounds.width + MESSAGEBOX_BUTTON_PADDING);
|
buttonBounds.x += (buttonBounds.width + MESSAGEBOX_BUTTON_PADDING);
|
||||||
|
|
@ -3151,12 +3164,12 @@ int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, co
|
||||||
|
|
||||||
int btnIndex = -1;
|
int btnIndex = -1;
|
||||||
|
|
||||||
int buttonsCount = 0;
|
int buttonCount = 0;
|
||||||
const char **buttonsText = GuiTextSplit(buttons, &buttonsCount, NULL);
|
const char **buttonsText = GuiTextSplit(buttons, &buttonCount, NULL);
|
||||||
Rectangle buttonBounds = { 0 };
|
Rectangle buttonBounds = { 0 };
|
||||||
buttonBounds.x = bounds.x + TEXTINPUTBOX_BUTTON_PADDING;
|
buttonBounds.x = bounds.x + TEXTINPUTBOX_BUTTON_PADDING;
|
||||||
buttonBounds.y = bounds.y + bounds.height - TEXTINPUTBOX_BUTTON_HEIGHT - TEXTINPUTBOX_BUTTON_PADDING;
|
buttonBounds.y = bounds.y + bounds.height - TEXTINPUTBOX_BUTTON_HEIGHT - TEXTINPUTBOX_BUTTON_PADDING;
|
||||||
buttonBounds.width = (bounds.width - TEXTINPUTBOX_BUTTON_PADDING*(buttonsCount + 1))/buttonsCount;
|
buttonBounds.width = (bounds.width - TEXTINPUTBOX_BUTTON_PADDING*(buttonCount + 1))/buttonCount;
|
||||||
buttonBounds.height = TEXTINPUTBOX_BUTTON_HEIGHT;
|
buttonBounds.height = TEXTINPUTBOX_BUTTON_HEIGHT;
|
||||||
|
|
||||||
int messageInputHeight = (int)bounds.height - WINDOW_STATUSBAR_HEIGHT - GuiGetStyle(STATUSBAR, BORDER_WIDTH) - TEXTINPUTBOX_BUTTON_HEIGHT - 2*TEXTINPUTBOX_BUTTON_PADDING;
|
int messageInputHeight = (int)bounds.height - WINDOW_STATUSBAR_HEIGHT - GuiGetStyle(STATUSBAR, BORDER_WIDTH) - TEXTINPUTBOX_BUTTON_HEIGHT - 2*TEXTINPUTBOX_BUTTON_PADDING;
|
||||||
|
|
@ -3198,7 +3211,7 @@ int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, co
|
||||||
int prevBtnTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
|
int prevBtnTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
|
||||||
GuiSetStyle(BUTTON, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER);
|
GuiSetStyle(BUTTON, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER);
|
||||||
|
|
||||||
for (int i = 0; i < buttonsCount; i++)
|
for (int i = 0; i < buttonCount; i++)
|
||||||
{
|
{
|
||||||
if (GuiButton(buttonBounds, buttonsText[i])) btnIndex = i + 1;
|
if (GuiButton(buttonBounds, buttonsText[i])) btnIndex = i + 1;
|
||||||
buttonBounds.x += (buttonBounds.width + MESSAGEBOX_BUTTON_PADDING);
|
buttonBounds.x += (buttonBounds.width + MESSAGEBOX_BUTTON_PADDING);
|
||||||
|
|
@ -3322,20 +3335,20 @@ void GuiLoadStyle(const char *fileName)
|
||||||
char *charValues = LoadFileText(charmapFileName);
|
char *charValues = LoadFileText(charmapFileName);
|
||||||
if (charValues != NULL)
|
if (charValues != NULL)
|
||||||
{
|
{
|
||||||
int charsCount = 0;
|
int glyphCount = 0;
|
||||||
const char **chars = TextSplit(charValues, '\n', &charsCount);
|
const char **chars = TextSplit(charValues, '\n', &glyphCount);
|
||||||
|
|
||||||
int *values = (int *)RAYGUI_MALLOC(charsCount*sizeof(int));
|
int *values = (int *)RAYGUI_MALLOC(glyphCount*sizeof(int));
|
||||||
for (int i = 0; i < charsCount; i++) values[i] = TextToInteger(chars[i]);
|
for (int i = 0; i < glyphCount; i++) values[i] = TextToInteger(chars[i]);
|
||||||
|
|
||||||
font = LoadFontEx(TextFormat("%s/%s", GetDirectoryPath(fileName), fontFileName), fontSize, values, charsCount);
|
font = LoadFontEx(TextFormat("%s/%s", GetDirectoryPath(fileName), fontFileName), fontSize, values, glyphCount);
|
||||||
|
|
||||||
RAYGUI_FREE(values);
|
RAYGUI_FREE(values);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else font = LoadFontEx(TextFormat("%s/%s", GetDirectoryPath(fileName), fontFileName), fontSize, NULL, 0);
|
else font = LoadFontEx(TextFormat("%s/%s", GetDirectoryPath(fileName), fontFileName), fontSize, NULL, 0);
|
||||||
|
|
||||||
if ((font.texture.id > 0) && (font.charsCount > 0)) GuiSetFont(font);
|
if ((font.texture.id > 0) && (font.glyphCount > 0)) GuiSetFont(font);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
default: break;
|
default: break;
|
||||||
|
|
@ -3358,12 +3371,12 @@ void GuiLoadStyle(const char *fileName)
|
||||||
char signature[5] = "";
|
char signature[5] = "";
|
||||||
short version = 0;
|
short version = 0;
|
||||||
short reserved = 0;
|
short reserved = 0;
|
||||||
int propertiesCount = 0;
|
int propertyCount = 0;
|
||||||
|
|
||||||
fread(signature, 1, 4, rgsFile);
|
fread(signature, 1, 4, rgsFile);
|
||||||
fread(&version, 1, sizeof(short), rgsFile);
|
fread(&version, 1, sizeof(short), rgsFile);
|
||||||
fread(&reserved, 1, sizeof(short), rgsFile);
|
fread(&reserved, 1, sizeof(short), rgsFile);
|
||||||
fread(&propertiesCount, 1, sizeof(int), rgsFile);
|
fread(&propertyCount, 1, sizeof(int), rgsFile);
|
||||||
|
|
||||||
if ((signature[0] == 'r') &&
|
if ((signature[0] == 'r') &&
|
||||||
(signature[1] == 'G') &&
|
(signature[1] == 'G') &&
|
||||||
|
|
@ -3374,7 +3387,7 @@ void GuiLoadStyle(const char *fileName)
|
||||||
short propertyId = 0;
|
short propertyId = 0;
|
||||||
int propertyValue = 0;
|
int propertyValue = 0;
|
||||||
|
|
||||||
for (int i = 0; i < propertiesCount; i++)
|
for (int i = 0; i < propertyCount; i++)
|
||||||
{
|
{
|
||||||
fread(&controlId, 1, sizeof(short), rgsFile);
|
fread(&controlId, 1, sizeof(short), rgsFile);
|
||||||
fread(&propertyId, 1, sizeof(short), rgsFile);
|
fread(&propertyId, 1, sizeof(short), rgsFile);
|
||||||
|
|
@ -3405,7 +3418,7 @@ void GuiLoadStyle(const char *fileName)
|
||||||
Rectangle whiteRec = { 0 };
|
Rectangle whiteRec = { 0 };
|
||||||
|
|
||||||
fread(&font.baseSize, 1, sizeof(int), rgsFile);
|
fread(&font.baseSize, 1, sizeof(int), rgsFile);
|
||||||
fread(&font.charsCount, 1, sizeof(int), rgsFile);
|
fread(&font.glyphCount, 1, sizeof(int), rgsFile);
|
||||||
fread(&fontType, 1, sizeof(int), rgsFile);
|
fread(&fontType, 1, sizeof(int), rgsFile);
|
||||||
|
|
||||||
// Load font white rectangle
|
// Load font white rectangle
|
||||||
|
|
@ -3432,17 +3445,17 @@ void GuiLoadStyle(const char *fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load font recs data
|
// Load font recs data
|
||||||
font.recs = (Rectangle *)RAYGUI_CALLOC(font.charsCount, sizeof(Rectangle));
|
font.recs = (Rectangle *)RAYGUI_CALLOC(font.glyphCount, sizeof(Rectangle));
|
||||||
for (int i = 0; i < font.charsCount; i++) fread(&font.recs[i], 1, sizeof(Rectangle), rgsFile);
|
for (int i = 0; i < font.glyphCount; i++) fread(&font.recs[i], 1, sizeof(Rectangle), rgsFile);
|
||||||
|
|
||||||
// Load font chars info data
|
// Load font chars info data
|
||||||
font.chars = (GlyphInfo *)RAYGUI_CALLOC(font.charsCount, sizeof(GlyphInfo));
|
font.glyphs = (GlyphInfo *)RAYGUI_CALLOC(font.glyphCount, sizeof(GlyphInfo));
|
||||||
for (int i = 0; i < font.charsCount; i++)
|
for (int i = 0; i < font.glyphCount; i++)
|
||||||
{
|
{
|
||||||
fread(&font.chars[i].value, 1, sizeof(int), rgsFile);
|
fread(&font.glyphs[i].value, 1, sizeof(int), rgsFile);
|
||||||
fread(&font.chars[i].offsetX, 1, sizeof(int), rgsFile);
|
fread(&font.glyphs[i].offsetX, 1, sizeof(int), rgsFile);
|
||||||
fread(&font.chars[i].offsetY, 1, sizeof(int), rgsFile);
|
fread(&font.glyphs[i].offsetY, 1, sizeof(int), rgsFile);
|
||||||
fread(&font.chars[i].advanceX, 1, sizeof(int), rgsFile);
|
fread(&font.glyphs[i].advanceX, 1, sizeof(int), rgsFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
GuiSetFont(font);
|
GuiSetFont(font);
|
||||||
|
|
@ -3572,7 +3585,7 @@ unsigned int *GuiGetIcons(void) { return guiIcons; }
|
||||||
|
|
||||||
// Load raygui icons file (.rgi)
|
// Load raygui icons file (.rgi)
|
||||||
// NOTE: In case nameIds are required, they can be requested with loadIconsName,
|
// NOTE: In case nameIds are required, they can be requested with loadIconsName,
|
||||||
// they are returned as a guiIconsName[iconsCount][RICON_MAX_NAME_LENGTH],
|
// they are returned as a guiIconsName[iconCount][RICON_MAX_NAME_LENGTH],
|
||||||
// guiIconsName[]][] memory should be manually freed!
|
// guiIconsName[]][] memory should be manually freed!
|
||||||
char **GuiLoadIcons(const char *fileName, bool loadIconsName)
|
char **GuiLoadIcons(const char *fileName, bool loadIconsName)
|
||||||
{
|
{
|
||||||
|
|
@ -3609,14 +3622,14 @@ char **GuiLoadIcons(const char *fileName, bool loadIconsName)
|
||||||
char signature[5] = "";
|
char signature[5] = "";
|
||||||
short version = 0;
|
short version = 0;
|
||||||
short reserved = 0;
|
short reserved = 0;
|
||||||
short iconsCount = 0;
|
short iconCount = 0;
|
||||||
short iconsSize = 0;
|
short iconSize = 0;
|
||||||
|
|
||||||
fread(signature, 1, 4, rgiFile);
|
fread(signature, 1, 4, rgiFile);
|
||||||
fread(&version, 1, sizeof(short), rgiFile);
|
fread(&version, 1, sizeof(short), rgiFile);
|
||||||
fread(&reserved, 1, sizeof(short), rgiFile);
|
fread(&reserved, 1, sizeof(short), rgiFile);
|
||||||
fread(&iconsCount, 1, sizeof(short), rgiFile);
|
fread(&iconCount, 1, sizeof(short), rgiFile);
|
||||||
fread(&iconsSize, 1, sizeof(short), rgiFile);
|
fread(&iconSize, 1, sizeof(short), rgiFile);
|
||||||
|
|
||||||
if ((signature[0] == 'r') &&
|
if ((signature[0] == 'r') &&
|
||||||
(signature[1] == 'G') &&
|
(signature[1] == 'G') &&
|
||||||
|
|
@ -3625,17 +3638,17 @@ char **GuiLoadIcons(const char *fileName, bool loadIconsName)
|
||||||
{
|
{
|
||||||
if (loadIconsName)
|
if (loadIconsName)
|
||||||
{
|
{
|
||||||
guiIconsName = (char **)RAYGUI_MALLOC(iconsCount*sizeof(char **));
|
guiIconsName = (char **)RAYGUI_MALLOC(iconCount*sizeof(char **));
|
||||||
for (int i = 0; i < iconsCount; i++)
|
for (int i = 0; i < iconCount; i++)
|
||||||
{
|
{
|
||||||
guiIconsName[i] = (char *)RAYGUI_MALLOC(RICON_MAX_NAME_LENGTH);
|
guiIconsName[i] = (char *)RAYGUI_MALLOC(RICON_MAX_NAME_LENGTH);
|
||||||
fread(guiIconsName[i], RICON_MAX_NAME_LENGTH, 1, rgiFile);
|
fread(guiIconsName[i], RICON_MAX_NAME_LENGTH, 1, rgiFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else fseek(rgiFile, iconsCount*RICON_MAX_NAME_LENGTH, SEEK_CUR);
|
else fseek(rgiFile, iconCount*RICON_MAX_NAME_LENGTH, SEEK_CUR);
|
||||||
|
|
||||||
// Read icons data directly over guiIcons data array
|
// Read icons data directly over guiIcons data array
|
||||||
fread(guiIcons, iconsCount*(iconsSize*iconsSize/32), sizeof(unsigned int), rgiFile);
|
fread(guiIcons, iconCount*(iconSize*iconSize/32), sizeof(unsigned int), rgiFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(rgiFile);
|
fclose(rgiFile);
|
||||||
|
|
@ -4061,7 +4074,7 @@ static Vector3 ConvertHSVtoRGB(Vector3 hsv)
|
||||||
|
|
||||||
#if defined(RAYGUI_STANDALONE)
|
#if defined(RAYGUI_STANDALONE)
|
||||||
// Returns a Color struct from hexadecimal value
|
// Returns a Color struct from hexadecimal value
|
||||||
static Color GetColor(unsigned int hexValue)
|
static Color GetColor(int hexValue)
|
||||||
{
|
{
|
||||||
Color color;
|
Color color;
|
||||||
|
|
||||||
|
|
@ -4186,29 +4199,29 @@ static int TextToInteger(const char *text)
|
||||||
return value*sign;
|
return value*sign;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encode codepoint into UTF-8 text (char array length returned as parameter)
|
// Encode codepoint into UTF-8 text (char array size returned as parameter)
|
||||||
static const char *CodepointToUTF8(int codepoint, int *byteLength)
|
static const char *CodepointToUTF8(int codepoint, int *byteSize)
|
||||||
{
|
{
|
||||||
static char utf8[6] = { 0 };
|
static char utf8[6] = { 0 };
|
||||||
int length = 0;
|
int size = 0;
|
||||||
|
|
||||||
if (codepoint <= 0x7f)
|
if (codepoint <= 0x7f)
|
||||||
{
|
{
|
||||||
utf8[0] = (char)codepoint;
|
utf8[0] = (char)codepoint;
|
||||||
length = 1;
|
size = 1;
|
||||||
}
|
}
|
||||||
else if (codepoint <= 0x7ff)
|
else if (codepoint <= 0x7ff)
|
||||||
{
|
{
|
||||||
utf8[0] = (char)(((codepoint >> 6) & 0x1f) | 0xc0);
|
utf8[0] = (char)(((codepoint >> 6) & 0x1f) | 0xc0);
|
||||||
utf8[1] = (char)((codepoint & 0x3f) | 0x80);
|
utf8[1] = (char)((codepoint & 0x3f) | 0x80);
|
||||||
length = 2;
|
size = 2;
|
||||||
}
|
}
|
||||||
else if (codepoint <= 0xffff)
|
else if (codepoint <= 0xffff)
|
||||||
{
|
{
|
||||||
utf8[0] = (char)(((codepoint >> 12) & 0x0f) | 0xe0);
|
utf8[0] = (char)(((codepoint >> 12) & 0x0f) | 0xe0);
|
||||||
utf8[1] = (char)(((codepoint >> 6) & 0x3f) | 0x80);
|
utf8[1] = (char)(((codepoint >> 6) & 0x3f) | 0x80);
|
||||||
utf8[2] = (char)((codepoint & 0x3f) | 0x80);
|
utf8[2] = (char)((codepoint & 0x3f) | 0x80);
|
||||||
length = 3;
|
size = 3;
|
||||||
}
|
}
|
||||||
else if (codepoint <= 0x10ffff)
|
else if (codepoint <= 0x10ffff)
|
||||||
{
|
{
|
||||||
|
|
@ -4216,10 +4229,10 @@ static const char *CodepointToUTF8(int codepoint, int *byteLength)
|
||||||
utf8[1] = (char)(((codepoint >> 12) & 0x3f) | 0x80);
|
utf8[1] = (char)(((codepoint >> 12) & 0x3f) | 0x80);
|
||||||
utf8[2] = (char)(((codepoint >> 6) & 0x3f) | 0x80);
|
utf8[2] = (char)(((codepoint >> 6) & 0x3f) | 0x80);
|
||||||
utf8[3] = (char)((codepoint & 0x3f) | 0x80);
|
utf8[3] = (char)((codepoint & 0x3f) | 0x80);
|
||||||
length = 4;
|
size = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
*byteLength = length;
|
*byteSize = size;
|
||||||
|
|
||||||
return utf8;
|
return utf8;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -276,7 +276,10 @@ static void __InsertMemNode(MemPool *const mempool, AllocList *const list, MemNo
|
||||||
mempool->arena.offs += iter->size;
|
mempool->arena.offs += iter->size;
|
||||||
__RemoveMemNode(list, iter);
|
__RemoveMemNode(list, iter);
|
||||||
iter = list->head;
|
iter = list->head;
|
||||||
if (iter == NULL) return;
|
if (iter == NULL) {
|
||||||
|
list->head = node;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const uintptr_t inode = ( uintptr_t )node;
|
const uintptr_t inode = ( uintptr_t )node;
|
||||||
const uintptr_t iiter = ( uintptr_t )iter;
|
const uintptr_t iiter = ( uintptr_t )iter;
|
||||||
|
|
@ -293,6 +296,14 @@ static void __InsertMemNode(MemPool *const mempool, AllocList *const list, MemNo
|
||||||
iter->size += node->size;
|
iter->size += node->size;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if (iter->next == NULL)
|
||||||
|
{
|
||||||
|
// we reached the end of the free list -> append the node
|
||||||
|
iter->next = node;
|
||||||
|
node->prev = iter;
|
||||||
|
list->len++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (iter > node)
|
else if (iter > node)
|
||||||
{
|
{
|
||||||
|
|
@ -326,7 +337,7 @@ static void __InsertMemNode(MemPool *const mempool, AllocList *const list, MemNo
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
__InsertMemNodeBefore(list, iter, node);
|
__InsertMemNodeBefore(list, node, iter);
|
||||||
list->len++;
|
list->len++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -155,10 +155,6 @@ typedef int socklen_t;
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef INVALID_SOCKET
|
|
||||||
#define INVALID_SOCKET ~(0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __USE_W32_SOCKETS
|
#ifndef __USE_W32_SOCKETS
|
||||||
#define closesocket close
|
#define closesocket close
|
||||||
#define SOCKET int
|
#define SOCKET int
|
||||||
|
|
@ -166,6 +162,10 @@ typedef int socklen_t;
|
||||||
#define SOCKET_ERROR -1
|
#define SOCKET_ERROR -1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef INVALID_SOCKET
|
||||||
|
#define INVALID_SOCKET ~(0)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __USE_W32_SOCKETS
|
#ifdef __USE_W32_SOCKETS
|
||||||
#ifndef EINTR
|
#ifndef EINTR
|
||||||
#define EINTR WSAEINTR
|
#define EINTR WSAEINTR
|
||||||
|
|
|
||||||
84
src/raudio.c
84
src/raudio.c
|
|
@ -26,8 +26,9 @@
|
||||||
* supported by default, to remove support, just comment unrequired #define in this module
|
* supported by default, to remove support, just comment unrequired #define in this module
|
||||||
*
|
*
|
||||||
* DEPENDENCIES:
|
* DEPENDENCIES:
|
||||||
* miniaudio.h - Audio device management lib (https://github.com/dr-soft/miniaudio)
|
* miniaudio.h - Audio device management lib (https://github.com/mackron/miniaudio)
|
||||||
* stb_vorbis.h - Ogg audio files loading (http://www.nothings.org/stb_vorbis/)
|
* stb_vorbis.h - Ogg audio files loading (http://www.nothings.org/stb_vorbis/)
|
||||||
|
* dr_wav.h - WAV audio files loading (http://github.com/mackron/dr_libs)
|
||||||
* dr_mp3.h - MP3 audio file loading (https://github.com/mackron/dr_libs)
|
* dr_mp3.h - MP3 audio file loading (https://github.com/mackron/dr_libs)
|
||||||
* dr_flac.h - FLAC audio file loading (https://github.com/mackron/dr_libs)
|
* dr_flac.h - FLAC audio file loading (https://github.com/mackron/dr_libs)
|
||||||
* jar_xm.h - XM module file loading
|
* jar_xm.h - XM module file loading
|
||||||
|
|
@ -877,14 +878,14 @@ void UnloadSound(Sound sound)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update sound buffer with new data
|
// Update sound buffer with new data
|
||||||
void UpdateSound(Sound sound, const void *data, int samplesCount)
|
void UpdateSound(Sound sound, const void *data, int sampleCount)
|
||||||
{
|
{
|
||||||
if (sound.stream.buffer != NULL)
|
if (sound.stream.buffer != NULL)
|
||||||
{
|
{
|
||||||
StopAudioBuffer(sound.stream.buffer);
|
StopAudioBuffer(sound.stream.buffer);
|
||||||
|
|
||||||
// TODO: May want to lock/unlock this since this data buffer is read at mixing time
|
// TODO: May want to lock/unlock this since this data buffer is read at mixing time
|
||||||
memcpy(sound.stream.buffer->data, data, samplesCount*ma_get_bytes_per_frame(sound.stream.buffer->converter.config.formatIn, sound.stream.buffer->converter.config.channelsIn));
|
memcpy(sound.stream.buffer->data, data, sampleCount*ma_get_bytes_per_frame(sound.stream.buffer->converter.config.formatIn, sound.stream.buffer->converter.config.channelsIn));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -942,19 +943,19 @@ bool ExportWaveAsCode(Wave wave, const char *fileName)
|
||||||
|
|
||||||
// NOTE: Text data buffer size is estimated considering wave data size in bytes
|
// NOTE: Text data buffer size is estimated considering wave data size in bytes
|
||||||
// and requiring 6 char bytes for every byte: "0x00, "
|
// and requiring 6 char bytes for every byte: "0x00, "
|
||||||
char *txtData = (char *)RL_CALLOC(6*waveDataSize + 2000, sizeof(char));
|
char *txtData = (char *)RL_CALLOC(waveDataSize*6 + 2000, sizeof(char));
|
||||||
|
|
||||||
int bytesCount = 0;
|
int byteCount = 0;
|
||||||
bytesCount += sprintf(txtData + bytesCount, "\n//////////////////////////////////////////////////////////////////////////////////\n");
|
byteCount += sprintf(txtData + byteCount, "\n//////////////////////////////////////////////////////////////////////////////////\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "// //\n");
|
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "// WaveAsCode exporter v1.0 - Wave data exported as an array of bytes //\n");
|
byteCount += sprintf(txtData + byteCount, "// WaveAsCode exporter v1.0 - Wave data exported as an array of bytes //\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "// //\n");
|
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "// more info and bugs-report: github.com/raysan5/raylib //\n");
|
byteCount += sprintf(txtData + byteCount, "// more info and bugs-report: github.com/raysan5/raylib //\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "// feedback and support: ray[at]raylib.com //\n");
|
byteCount += sprintf(txtData + byteCount, "// feedback and support: ray[at]raylib.com //\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "// //\n");
|
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "// Copyright (c) 2018 Ramon Santamaria (@raysan5) //\n");
|
byteCount += sprintf(txtData + byteCount, "// Copyright (c) 2018-2021 Ramon Santamaria (@raysan5) //\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "// //\n");
|
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "//////////////////////////////////////////////////////////////////////////////////\n\n");
|
byteCount += sprintf(txtData + byteCount, "//////////////////////////////////////////////////////////////////////////////////\n\n");
|
||||||
|
|
||||||
char varFileName[256] = { 0 };
|
char varFileName[256] = { 0 };
|
||||||
#if !defined(RAUDIO_STANDALONE)
|
#if !defined(RAUDIO_STANDALONE)
|
||||||
|
|
@ -965,17 +966,18 @@ bool ExportWaveAsCode(Wave wave, const char *fileName)
|
||||||
strcpy(varFileName, fileName);
|
strcpy(varFileName, fileName);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bytesCount += sprintf(txtData + bytesCount, "// Wave data information\n");
|
byteCount += sprintf(txtData + byteCount, "// Wave data information\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "#define %s_FRAME_COUNT %u\n", varFileName, wave.frameCount);
|
byteCount += sprintf(txtData + byteCount, "#define %s_FRAME_COUNT %u\n", varFileName, wave.frameCount);
|
||||||
bytesCount += sprintf(txtData + bytesCount, "#define %s_SAMPLE_COUNT %u\n", varFileName, wave.frameCount*wave.channels);
|
byteCount += sprintf(txtData + byteCount, "#define %s_FRAME_COUNT %u\n", varFileName, wave.frameCount);
|
||||||
bytesCount += sprintf(txtData + bytesCount, "#define %s_SAMPLE_RATE %u\n", varFileName, wave.sampleRate);
|
byteCount += sprintf(txtData + byteCount, "#define %s_SAMPLE_RATE %u\n", varFileName, wave.sampleRate);
|
||||||
bytesCount += sprintf(txtData + bytesCount, "#define %s_SAMPLE_SIZE %u\n", varFileName, wave.sampleSize);
|
byteCount += sprintf(txtData + byteCount, "#define %s_SAMPLE_SIZE %u\n", varFileName, wave.sampleSize);
|
||||||
bytesCount += sprintf(txtData + bytesCount, "#define %s_CHANNELS %u\n\n", varFileName, wave.channels);
|
byteCount += sprintf(txtData + byteCount, "#define %s_CHANNELS %u\n\n", varFileName, wave.channels);
|
||||||
|
|
||||||
// Write byte data as hexadecimal text
|
// Write byte data as hexadecimal text
|
||||||
bytesCount += sprintf(txtData + bytesCount, "static unsigned char %s_DATA[%i] = { ", varFileName, waveDataSize);
|
// NOTE: Frame data exported is interlaced: Frame01[Sample-Channel01, Sample-Channel02, ...], Frame02[], Frame03[]
|
||||||
for (int i = 0; i < waveDataSize - 1; i++) bytesCount += sprintf(txtData + bytesCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%x,\n" : "0x%x, "), ((unsigned char *)wave.data)[i]);
|
byteCount += sprintf(txtData + byteCount, "static unsigned char %s_DATA[%i] = { ", varFileName, waveDataSize);
|
||||||
bytesCount += sprintf(txtData + bytesCount, "0x%x };\n", ((unsigned char *)wave.data)[waveDataSize - 1]);
|
for (int i = 0; i < waveDataSize - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%x,\n" : "0x%x, "), ((unsigned char *)wave.data)[i]);
|
||||||
|
byteCount += sprintf(txtData + byteCount, "0x%x };\n", ((unsigned char *)wave.data)[waveDataSize - 1]);
|
||||||
|
|
||||||
// NOTE: Text data length exported is determined by '\0' (NULL) character
|
// NOTE: Text data length exported is determined by '\0' (NULL) character
|
||||||
success = SaveFileText(fileName, txtData);
|
success = SaveFileText(fileName, txtData);
|
||||||
|
|
@ -1504,9 +1506,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, unsigned char *data, int d
|
||||||
// Copy data to allocated memory for default UnloadMusicStream
|
// Copy data to allocated memory for default UnloadMusicStream
|
||||||
unsigned char *newData = (unsigned char *)RL_MALLOC(dataSize);
|
unsigned char *newData = (unsigned char *)RL_MALLOC(dataSize);
|
||||||
int it = dataSize/sizeof(unsigned char);
|
int it = dataSize/sizeof(unsigned char);
|
||||||
for (int i = 0; i < it; i++){
|
for (int i = 0; i < it; i++) newData[i] = data[i];
|
||||||
newData[i] = data[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Memory loaded version for jar_mod_load_file()
|
// Memory loaded version for jar_mod_load_file()
|
||||||
if (dataSize && dataSize < 32*1024*1024)
|
if (dataSize && dataSize < 32*1024*1024)
|
||||||
|
|
@ -1656,6 +1656,34 @@ void StopMusicStream(Music music)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Seek music to a certain position (in seconds)
|
||||||
|
void SeekMusicStream(Music music, float position)
|
||||||
|
{
|
||||||
|
// Seeking is not supported in module formats
|
||||||
|
if ((music.ctxType == MUSIC_MODULE_XM) || (music.ctxType == MUSIC_MODULE_MOD)) return;
|
||||||
|
|
||||||
|
unsigned int positionInFrames = (unsigned int)(position*music.stream.sampleRate);
|
||||||
|
|
||||||
|
switch (music.ctxType)
|
||||||
|
{
|
||||||
|
#if defined(SUPPORT_FILEFORMAT_WAV)
|
||||||
|
case MUSIC_AUDIO_WAV: drwav_seek_to_pcm_frame((drwav *)music.ctxData, positionInFrames); break;
|
||||||
|
#endif
|
||||||
|
#if defined(SUPPORT_FILEFORMAT_OGG)
|
||||||
|
case MUSIC_AUDIO_OGG: stb_vorbis_seek_frame((stb_vorbis *)music.ctxData, positionInFrames); break;
|
||||||
|
#endif
|
||||||
|
#if defined(SUPPORT_FILEFORMAT_FLAC)
|
||||||
|
case MUSIC_AUDIO_FLAC: drflac_seek_to_pcm_frame((drflac *)music.ctxData, positionInFrames); break;
|
||||||
|
#endif
|
||||||
|
#if defined(SUPPORT_FILEFORMAT_MP3)
|
||||||
|
case MUSIC_AUDIO_MP3: drmp3_seek_to_pcm_frame((drmp3 *)music.ctxData, positionInFrames); break;
|
||||||
|
#endif
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
music.stream.buffer->framesProcessed = positionInFrames;
|
||||||
|
}
|
||||||
|
|
||||||
// Update (re-fill) music buffers if data already processed
|
// Update (re-fill) music buffers if data already processed
|
||||||
void UpdateMusicStream(Music music)
|
void UpdateMusicStream(Music music)
|
||||||
{
|
{
|
||||||
|
|
@ -1715,7 +1743,7 @@ void UpdateMusicStream(Music music)
|
||||||
#if defined(SUPPORT_FILEFORMAT_XM)
|
#if defined(SUPPORT_FILEFORMAT_XM)
|
||||||
case MUSIC_MODULE_XM:
|
case MUSIC_MODULE_XM:
|
||||||
{
|
{
|
||||||
// NOTE: Internally we consider 2 channels generation, so samplesCount/2
|
// NOTE: Internally we consider 2 channels generation, so sampleCount/2
|
||||||
if (AUDIO_DEVICE_FORMAT == ma_format_f32) jar_xm_generate_samples((jar_xm_context_t *)music.ctxData, (float *)pcm, frameCountToStream);
|
if (AUDIO_DEVICE_FORMAT == ma_format_f32) jar_xm_generate_samples((jar_xm_context_t *)music.ctxData, (float *)pcm, frameCountToStream);
|
||||||
else if (AUDIO_DEVICE_FORMAT == ma_format_s16) jar_xm_generate_samples_16bit((jar_xm_context_t *)music.ctxData, (short *)pcm, frameCountToStream);
|
else if (AUDIO_DEVICE_FORMAT == ma_format_s16) jar_xm_generate_samples_16bit((jar_xm_context_t *)music.ctxData, (short *)pcm, frameCountToStream);
|
||||||
else if (AUDIO_DEVICE_FORMAT == ma_format_u8) jar_xm_generate_samples_8bit((jar_xm_context_t *)music.ctxData, (char *)pcm, frameCountToStream);
|
else if (AUDIO_DEVICE_FORMAT == ma_format_u8) jar_xm_generate_samples_8bit((jar_xm_context_t *)music.ctxData, (char *)pcm, frameCountToStream);
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,7 @@ void UpdateMusicStream(Music music); // Updates buffe
|
||||||
void StopMusicStream(Music music); // Stop music playing
|
void StopMusicStream(Music music); // Stop music playing
|
||||||
void PauseMusicStream(Music music); // Pause music playing
|
void PauseMusicStream(Music music); // Pause music playing
|
||||||
void ResumeMusicStream(Music music); // Resume playing paused music
|
void ResumeMusicStream(Music music); // Resume playing paused music
|
||||||
|
void SeekMusicStream(Music music, float position); // Seek music to a position (in seconds)
|
||||||
void SetMusicVolume(Music music, float volume); // Set volume for music (1.0 is max level)
|
void SetMusicVolume(Music music, float volume); // Set volume for music (1.0 is max level)
|
||||||
void SetMusicPitch(Music music, float pitch); // Set pitch for a music (1.0 is base level)
|
void SetMusicPitch(Music music, float pitch); // Set pitch for a music (1.0 is base level)
|
||||||
float GetMusicTimeLength(Music music); // Get music time length (in seconds)
|
float GetMusicTimeLength(Music music); // Get music time length (in seconds)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
GLFW_ICON ICON "raylib.ico"
|
GLFW_ICON ICON "raylib.ico"
|
||||||
|
|
||||||
1 VERSIONINFO
|
1 VERSIONINFO
|
||||||
FILEVERSION 3,7,0,0
|
FILEVERSION 4,0,0,0
|
||||||
PRODUCTVERSION 3,7,0,0
|
PRODUCTVERSION 4,0,0,0
|
||||||
BEGIN
|
BEGIN
|
||||||
BLOCK "StringFileInfo"
|
BLOCK "StringFileInfo"
|
||||||
BEGIN
|
BEGIN
|
||||||
|
|
@ -11,12 +11,12 @@ BEGIN
|
||||||
BEGIN
|
BEGIN
|
||||||
//VALUE "CompanyName", "raylib technologies"
|
//VALUE "CompanyName", "raylib technologies"
|
||||||
VALUE "FileDescription", "raylib dynamic library (www.raylib.com)"
|
VALUE "FileDescription", "raylib dynamic library (www.raylib.com)"
|
||||||
VALUE "FileVersion", "3.7.0"
|
VALUE "FileVersion", "4.0.0"
|
||||||
VALUE "InternalName", "raylib.dll"
|
VALUE "InternalName", "raylib.dll"
|
||||||
VALUE "LegalCopyright", "(c) 2021 Ramon Santamaria (@raysan5)"
|
VALUE "LegalCopyright", "(c) 2021 Ramon Santamaria (@raysan5)"
|
||||||
VALUE "OriginalFilename", "raylib.dll"
|
VALUE "OriginalFilename", "raylib.dll"
|
||||||
VALUE "ProductName", "raylib"
|
VALUE "ProductName", "raylib"
|
||||||
VALUE "ProductVersion", "3.7.0"
|
VALUE "ProductVersion", "4.0.0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
|
||||||
Binary file not shown.
57
src/raylib.h
57
src/raylib.h
|
|
@ -287,11 +287,11 @@ typedef struct GlyphInfo {
|
||||||
// Font, font texture and GlyphInfo array data
|
// Font, font texture and GlyphInfo array data
|
||||||
typedef struct Font {
|
typedef struct Font {
|
||||||
int baseSize; // Base size (default chars height)
|
int baseSize; // Base size (default chars height)
|
||||||
int charsCount; // Number of characters
|
int glyphCount; // Number of glyph characters
|
||||||
int charsPadding; // Padding around the chars
|
int glyphPadding; // Padding around the glyph characters
|
||||||
Texture2D texture; // Characters texture atlas
|
Texture2D texture; // Texture atlas containing the glyphs
|
||||||
Rectangle *recs; // Characters rectangles in texture
|
Rectangle *recs; // Rectangles in texture for the glyphs
|
||||||
GlyphInfo *chars; // Characters glyphs info data
|
GlyphInfo *glyphs; // Glyphs info data
|
||||||
} Font;
|
} Font;
|
||||||
|
|
||||||
// Camera, defines position/orientation in 3d space
|
// Camera, defines position/orientation in 3d space
|
||||||
|
|
@ -841,7 +841,7 @@ typedef enum {
|
||||||
BLEND_CUSTOM // Belnd textures using custom src/dst factors (use rlSetBlendMode())
|
BLEND_CUSTOM // Belnd textures using custom src/dst factors (use rlSetBlendMode())
|
||||||
} BlendMode;
|
} BlendMode;
|
||||||
|
|
||||||
// Gestures
|
// Gesture
|
||||||
// NOTE: It could be used as flags to enable only some gestures
|
// NOTE: It could be used as flags to enable only some gestures
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GESTURE_NONE = 0, // No gesture
|
GESTURE_NONE = 0, // No gesture
|
||||||
|
|
@ -1009,6 +1009,7 @@ RLAPI double GetTime(void); // Get elapsed
|
||||||
|
|
||||||
// Misc. functions
|
// Misc. functions
|
||||||
RLAPI int GetRandomValue(int min, int max); // Get a random value between min and max (both included)
|
RLAPI int GetRandomValue(int min, int max); // Get a random value between min and max (both included)
|
||||||
|
RLAPI void SetRandomSeed(unsigned int seed); // Set the seed for the random number generator
|
||||||
RLAPI void TakeScreenshot(const char *fileName); // Takes a screenshot of current screen (filename extension defines format)
|
RLAPI void TakeScreenshot(const char *fileName); // Takes a screenshot of current screen (filename extension defines format)
|
||||||
RLAPI void SetConfigFlags(unsigned int flags); // Setup init configuration flags (view FLAGS)
|
RLAPI void SetConfigFlags(unsigned int flags); // Setup init configuration flags (view FLAGS)
|
||||||
|
|
||||||
|
|
@ -1104,14 +1105,16 @@ RLAPI void SetMouseCursor(int cursor); // Set mouse curso
|
||||||
RLAPI int GetTouchX(void); // Get touch position X for touch point 0 (relative to screen size)
|
RLAPI int GetTouchX(void); // Get touch position X for touch point 0 (relative to screen size)
|
||||||
RLAPI int GetTouchY(void); // Get touch position Y for touch point 0 (relative to screen size)
|
RLAPI int GetTouchY(void); // Get touch position Y for touch point 0 (relative to screen size)
|
||||||
RLAPI Vector2 GetTouchPosition(int index); // Get touch position XY for a touch point index (relative to screen size)
|
RLAPI Vector2 GetTouchPosition(int index); // Get touch position XY for a touch point index (relative to screen size)
|
||||||
|
RLAPI int GetTouchPointId(int index); // Get touch point identifier for given index
|
||||||
|
RLAPI int GetTouchPointCount(void); // Get number of touch points
|
||||||
|
RLAPI int GetTouchEvent(void); // Get last touch event registered
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Gestures and Touch Handling Functions (Module: gestures)
|
// Gestures and Touch Handling Functions (Module: rgestures)
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
RLAPI void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
|
RLAPI void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
|
||||||
RLAPI bool IsGestureDetected(int gesture); // Check if a gesture have been detected
|
RLAPI bool IsGestureDetected(int gesture); // Check if a gesture have been detected
|
||||||
RLAPI int GetGestureDetected(void); // Get latest detected gesture
|
RLAPI int GetGestureDetected(void); // Get latest detected gesture
|
||||||
RLAPI int GetTouchPointsCount(void); // Get touch points count
|
|
||||||
RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds
|
RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds
|
||||||
RLAPI Vector2 GetGestureDragVector(void); // Get gesture drag vector
|
RLAPI Vector2 GetGestureDragVector(void); // Get gesture drag vector
|
||||||
RLAPI float GetGestureDragAngle(void); // Get gesture drag angle
|
RLAPI float GetGestureDragAngle(void); // Get gesture drag angle
|
||||||
|
|
@ -1119,7 +1122,7 @@ RLAPI Vector2 GetGesturePinchVector(void); // Get gesture pinch del
|
||||||
RLAPI float GetGesturePinchAngle(void); // Get gesture pinch angle
|
RLAPI float GetGesturePinchAngle(void); // Get gesture pinch angle
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Camera System Functions (Module: camera)
|
// Camera System Functions (Module: rcamera)
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
RLAPI void SetCameraMode(Camera camera, int mode); // Set camera mode (multiple camera modes available)
|
RLAPI void SetCameraMode(Camera camera, int mode); // Set camera mode (multiple camera modes available)
|
||||||
RLAPI void UpdateCamera(Camera *camera); // Update camera position for selected mode
|
RLAPI void UpdateCamera(Camera *camera); // Update camera position for selected mode
|
||||||
|
|
@ -1145,7 +1148,7 @@ RLAPI void DrawLineV(Vector2 startPos, Vector2 endPos, Color color);
|
||||||
RLAPI void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line defining thickness
|
RLAPI void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line defining thickness
|
||||||
RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line using cubic-bezier curves in-out
|
RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line using cubic-bezier curves in-out
|
||||||
RLAPI void DrawLineBezierQuad(Vector2 startPos, Vector2 endPos, Vector2 controlPos, float thick, Color color); //Draw line using quadratic bezier curves with a control point
|
RLAPI void DrawLineBezierQuad(Vector2 startPos, Vector2 endPos, Vector2 controlPos, float thick, Color color); //Draw line using quadratic bezier curves with a control point
|
||||||
RLAPI void DrawLineStrip(Vector2 *points, int pointsCount, Color color); // Draw lines sequence
|
RLAPI void DrawLineStrip(Vector2 *points, int pointCount, Color color); // Draw lines sequence
|
||||||
RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle
|
RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle
|
||||||
RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle
|
RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle
|
||||||
RLAPI void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw circle sector outline
|
RLAPI void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw circle sector outline
|
||||||
|
|
@ -1169,8 +1172,8 @@ RLAPI void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Co
|
||||||
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, 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 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 DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline (vertex in counter-clockwise order!)
|
||||||
RLAPI void DrawTriangleFan(Vector2 *points, int pointsCount, Color color); // Draw a triangle fan defined by points (first vertex is the center)
|
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 pointsCount, Color color); // Draw a triangle strip defined by points
|
RLAPI void DrawTriangleStrip(Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points
|
||||||
RLAPI void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a regular polygon (Vector version)
|
RLAPI void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a 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 DrawPolyLines(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a polygon outline of n sides
|
||||||
RLAPI void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, float lineThick, Color color); // Draw a polygon outline of n sides with extended parameters
|
RLAPI void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, float lineThick, Color color); // Draw a polygon outline of n sides with extended parameters
|
||||||
|
|
@ -1239,7 +1242,7 @@ RLAPI void ImageColorContrast(Image *image, float contrast);
|
||||||
RLAPI void ImageColorBrightness(Image *image, int brightness); // Modify image color: brightness (-255 to 255)
|
RLAPI void ImageColorBrightness(Image *image, int brightness); // Modify image color: brightness (-255 to 255)
|
||||||
RLAPI void ImageColorReplace(Image *image, Color color, Color replace); // Modify image color: replace color
|
RLAPI void ImageColorReplace(Image *image, Color color, Color replace); // Modify image color: replace color
|
||||||
RLAPI Color *LoadImageColors(Image image); // Load color data from image as a Color array (RGBA - 32bit)
|
RLAPI Color *LoadImageColors(Image image); // Load color data from image as a Color array (RGBA - 32bit)
|
||||||
RLAPI Color *LoadImagePalette(Image image, int maxPaletteSize, int *colorsCount); // Load colors palette from image as a Color array (RGBA - 32bit)
|
RLAPI Color *LoadImagePalette(Image image, int maxPaletteSize, int *colorCount); // Load colors palette from image as a Color array (RGBA - 32bit)
|
||||||
RLAPI void UnloadImageColors(Color *colors); // Unload color data loaded with LoadImageColors()
|
RLAPI void UnloadImageColors(Color *colors); // Unload color data loaded with LoadImageColors()
|
||||||
RLAPI void UnloadImagePalette(Color *colors); // Unload colors palette loaded with LoadImagePalette()
|
RLAPI void UnloadImagePalette(Color *colors); // Unload colors palette loaded with LoadImagePalette()
|
||||||
RLAPI Rectangle GetImageAlphaBorder(Image image, float threshold); // Get image alpha border rectangle
|
RLAPI Rectangle GetImageAlphaBorder(Image image, float threshold); // Get image alpha border rectangle
|
||||||
|
|
@ -1286,7 +1289,7 @@ RLAPI void DrawTextureQuad(Texture2D texture, Vector2 tiling, Vector2 offset, Re
|
||||||
RLAPI void DrawTextureTiled(Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, float scale, Color tint); // Draw part of a texture (defined by a rectangle) with rotation and scale tiled into dest.
|
RLAPI void DrawTextureTiled(Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, float scale, Color tint); // Draw part of a texture (defined by a rectangle) with rotation and scale tiled into dest.
|
||||||
RLAPI void DrawTexturePro(Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, Color tint); // Draw a part of a texture defined by a rectangle with 'pro' parameters
|
RLAPI void DrawTexturePro(Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, Color tint); // Draw a part of a texture defined by a rectangle with 'pro' parameters
|
||||||
RLAPI void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle dest, Vector2 origin, float rotation, Color tint); // Draws a texture (or part of it) that stretches or shrinks nicely
|
RLAPI void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle dest, Vector2 origin, float rotation, Color tint); // Draws a texture (or part of it) that stretches or shrinks nicely
|
||||||
RLAPI void DrawTexturePoly(Texture2D texture, Vector2 center, Vector2 *points, Vector2 *texcoords, int pointsCount, Color tint); // Draw a textured polygon
|
RLAPI void DrawTexturePoly(Texture2D texture, Vector2 center, Vector2 *points, Vector2 *texcoords, int pointCount, Color tint); // Draw a textured polygon
|
||||||
|
|
||||||
// Color/pixel related functions
|
// Color/pixel related functions
|
||||||
RLAPI Color Fade(Color color, float alpha); // Get color with alpha applied, alpha goes from 0.0f to 1.0f
|
RLAPI Color Fade(Color color, float alpha); // Get color with alpha applied, alpha goes from 0.0f to 1.0f
|
||||||
|
|
@ -1309,12 +1312,12 @@ RLAPI int GetPixelDataSize(int width, int height, int format); // G
|
||||||
// Font loading/unloading functions
|
// Font loading/unloading functions
|
||||||
RLAPI Font GetFontDefault(void); // Get the default Font
|
RLAPI Font GetFontDefault(void); // Get the default Font
|
||||||
RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM)
|
RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM)
|
||||||
RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int charsCount); // Load font from file with extended parameters
|
RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int glyphCount); // Load font from file with extended parameters
|
||||||
RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style)
|
RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style)
|
||||||
RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int charsCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf'
|
RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int glyphCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf'
|
||||||
RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int charsCount, int type); // Load font data for further use
|
RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int glyphCount, int type); // Load font data for further use
|
||||||
RLAPI Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **recs, int charsCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info
|
RLAPI Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **recs, int glyphCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info
|
||||||
RLAPI void UnloadFontData(GlyphInfo *chars, int charsCount); // Unload font chars info data (RAM)
|
RLAPI void UnloadFontData(GlyphInfo *chars, int glyphCount); // Unload font chars info data (RAM)
|
||||||
RLAPI void UnloadFont(Font font); // Unload Font from GPU memory (VRAM)
|
RLAPI void UnloadFont(Font font); // Unload Font from GPU memory (VRAM)
|
||||||
|
|
||||||
// Text drawing functions
|
// Text drawing functions
|
||||||
|
|
@ -1334,9 +1337,9 @@ RLAPI Rectangle GetGlyphAtlasRec(Font font, int codepoint);
|
||||||
// Text codepoints management functions (unicode characters)
|
// Text codepoints management functions (unicode characters)
|
||||||
RLAPI int *LoadCodepoints(const char *text, int *count); // Load all codepoints from a UTF-8 text string, codepoints count returned by parameter
|
RLAPI int *LoadCodepoints(const char *text, int *count); // Load all codepoints from a UTF-8 text string, codepoints count returned by parameter
|
||||||
RLAPI void UnloadCodepoints(int *codepoints); // Unload codepoints data from memory
|
RLAPI void UnloadCodepoints(int *codepoints); // Unload codepoints data from memory
|
||||||
RLAPI int GetCodepointsCount(const char *text); // Get total number of codepoints in a UTF-8 encoded string
|
RLAPI int GetCodepointCount(const char *text); // Get total number of codepoints in a UTF-8 encoded string
|
||||||
RLAPI int GetCodepoint(const char *text, int *bytesProcessed); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
|
RLAPI int GetCodepoint(const char *text, int *bytesProcessed); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
|
||||||
RLAPI const char *CodepointToUTF8(int codepoint, int *byteLength); // Encode one codepoint into UTF-8 byte array (array length returned as parameter)
|
RLAPI const char *CodepointToUTF8(int codepoint, int *byteSize); // Encode one codepoint into UTF-8 byte array (array length returned as parameter)
|
||||||
RLAPI char *TextCodepointsToUTF8(int *codepoints, int length); // Encode text as codepoints array into UTF-8 text string (WARNING: memory must be freed!)
|
RLAPI char *TextCodepointsToUTF8(int *codepoints, int length); // Encode text as codepoints array into UTF-8 text string (WARNING: memory must be freed!)
|
||||||
|
|
||||||
// Text strings management functions (no UTF-8 strings, only byte chars)
|
// Text strings management functions (no UTF-8 strings, only byte chars)
|
||||||
|
|
@ -1366,12 +1369,13 @@ 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 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 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 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 pointsCount, Color color); // Draw a triangle strip defined by points
|
RLAPI void DrawTriangleStrip3D(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 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 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
|
RLAPI void DrawCubeWires(Vector3 position, float width, float height, float length, Color color); // Draw cube wires
|
||||||
RLAPI void DrawCubeWiresV(Vector3 position, Vector3 size, Color color); // Draw cube wires (Vector version)
|
RLAPI void DrawCubeWiresV(Vector3 position, Vector3 size, Color color); // Draw cube wires (Vector version)
|
||||||
RLAPI void DrawCubeTexture(Texture2D texture, Vector3 position, float width, float height, float length, Color color); // Draw cube textured
|
RLAPI void DrawCubeTexture(Texture2D texture, Vector3 position, float width, float height, float length, Color color); // Draw cube textured
|
||||||
|
RLAPI void DrawCubeTextureRec(Texture2D texture, Rectangle source, Vector3 position, float width, float height, float length, Color color); // Draw cube with a region of a texture
|
||||||
RLAPI void DrawSphere(Vector3 centerPos, float radius, Color color); // Draw sphere
|
RLAPI void DrawSphere(Vector3 centerPos, float radius, Color color); // Draw sphere
|
||||||
RLAPI void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color color); // Draw sphere with extended parameters
|
RLAPI void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color color); // Draw sphere with extended parameters
|
||||||
RLAPI void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Color color); // Draw sphere wires
|
RLAPI void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Color color); // Draw sphere wires
|
||||||
|
|
@ -1400,7 +1404,7 @@ RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis,
|
||||||
RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires)
|
RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires)
|
||||||
RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float size, Color tint); // Draw a billboard texture
|
RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float size, Color tint); // Draw a billboard texture
|
||||||
RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source
|
RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source
|
||||||
RLAPI void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Vector2 origin, float rotation, Color tint); // Draw a billboard texture defined by source and rotation
|
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
|
||||||
|
|
||||||
// Mesh management functions
|
// Mesh management functions
|
||||||
RLAPI void UploadMesh(Mesh *mesh, bool dynamic); // Upload mesh vertex data in GPU and provide VAO/VBO ids
|
RLAPI void UploadMesh(Mesh *mesh, bool dynamic); // Upload mesh vertex data in GPU and provide VAO/VBO ids
|
||||||
|
|
@ -1434,7 +1438,7 @@ RLAPI void SetMaterialTexture(Material *material, int mapType, Texture2D texture
|
||||||
RLAPI void SetModelMeshMaterial(Model *model, int meshId, int materialId); // Set material for a mesh
|
RLAPI void SetModelMeshMaterial(Model *model, int meshId, int materialId); // Set material for a mesh
|
||||||
|
|
||||||
// Model animations loading/unloading functions
|
// Model animations loading/unloading functions
|
||||||
RLAPI ModelAnimation *LoadModelAnimations(const char *fileName, int *animsCount); // Load model animations from file
|
RLAPI ModelAnimation *LoadModelAnimations(const char *fileName, unsigned 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
|
||||||
RLAPI void UnloadModelAnimation(ModelAnimation anim); // Unload animation data
|
RLAPI void UnloadModelAnimation(ModelAnimation anim); // Unload animation data
|
||||||
RLAPI void UnloadModelAnimations(ModelAnimation* animations, unsigned int count); // Unload animation array data
|
RLAPI void UnloadModelAnimations(ModelAnimation* animations, unsigned int count); // Unload animation array data
|
||||||
|
|
@ -1466,7 +1470,7 @@ RLAPI Wave LoadWave(const char *fileName); // Load wa
|
||||||
RLAPI Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load wave from memory buffer, fileType refers to extension: i.e. '.wav'
|
RLAPI Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load wave from memory buffer, fileType refers to extension: i.e. '.wav'
|
||||||
RLAPI Sound LoadSound(const char *fileName); // Load sound from file
|
RLAPI Sound LoadSound(const char *fileName); // Load sound from file
|
||||||
RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound from wave data
|
RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound from wave data
|
||||||
RLAPI void UpdateSound(Sound sound, const void *data, int samplesCount);// Update sound buffer with new data
|
RLAPI void UpdateSound(Sound sound, const void *data, int sampleCount); // Update sound buffer with new data
|
||||||
RLAPI void UnloadWave(Wave wave); // Unload wave data
|
RLAPI void UnloadWave(Wave wave); // Unload wave data
|
||||||
RLAPI void UnloadSound(Sound sound); // Unload sound
|
RLAPI void UnloadSound(Sound sound); // Unload sound
|
||||||
RLAPI bool ExportWave(Wave wave, const char *fileName); // Export wave data to file, returns true on success
|
RLAPI bool ExportWave(Wave wave, const char *fileName); // Export wave data to file, returns true on success
|
||||||
|
|
@ -1499,6 +1503,7 @@ RLAPI void UpdateMusicStream(Music music); // Updates
|
||||||
RLAPI void StopMusicStream(Music music); // Stop music playing
|
RLAPI void StopMusicStream(Music music); // Stop music playing
|
||||||
RLAPI void PauseMusicStream(Music music); // Pause music playing
|
RLAPI void PauseMusicStream(Music music); // Pause music playing
|
||||||
RLAPI void ResumeMusicStream(Music music); // Resume playing paused music
|
RLAPI void ResumeMusicStream(Music music); // Resume playing paused music
|
||||||
|
RLAPI void SeekMusicStream(Music music, float position); // Seek music to a position (in seconds)
|
||||||
RLAPI void SetMusicVolume(Music music, float volume); // Set volume for music (1.0 is max level)
|
RLAPI void SetMusicVolume(Music music, float volume); // Set volume for music (1.0 is max level)
|
||||||
RLAPI void SetMusicPitch(Music music, float pitch); // Set pitch for a music (1.0 is base level)
|
RLAPI void SetMusicPitch(Music music, float pitch); // Set pitch for a music (1.0 is base level)
|
||||||
RLAPI float GetMusicTimeLength(Music music); // Get music time length (in seconds)
|
RLAPI float GetMusicTimeLength(Music music); // Get music time length (in seconds)
|
||||||
|
|
@ -1507,7 +1512,7 @@ RLAPI float GetMusicTimePlayed(Music music); // Get cur
|
||||||
// AudioStream management functions
|
// AudioStream management functions
|
||||||
RLAPI AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, unsigned int channels); // Load audio stream (to stream raw audio pcm data)
|
RLAPI AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, unsigned int channels); // Load audio stream (to stream raw audio pcm data)
|
||||||
RLAPI void UnloadAudioStream(AudioStream stream); // Unload audio stream and free memory
|
RLAPI void UnloadAudioStream(AudioStream stream); // Unload audio stream and free memory
|
||||||
RLAPI void UpdateAudioStream(AudioStream stream, const void *data, int framesCount); // Update audio stream buffers with data
|
RLAPI void UpdateAudioStream(AudioStream stream, const void *data, int frameCount); // Update audio stream buffers with data
|
||||||
RLAPI bool IsAudioStreamProcessed(AudioStream stream); // Check if any audio stream buffers requires refill
|
RLAPI bool IsAudioStreamProcessed(AudioStream stream); // Check if any audio stream buffers requires refill
|
||||||
RLAPI void PlayAudioStream(AudioStream stream); // Play audio stream
|
RLAPI void PlayAudioStream(AudioStream stream); // Play audio stream
|
||||||
RLAPI void PauseAudioStream(AudioStream stream); // Pause audio stream
|
RLAPI void PauseAudioStream(AudioStream stream); // Pause audio stream
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
GLFW_ICON ICON "raylib.ico"
|
GLFW_ICON ICON "raylib.ico"
|
||||||
|
|
||||||
1 VERSIONINFO
|
1 VERSIONINFO
|
||||||
FILEVERSION 3,7,0,0
|
FILEVERSION 4,0,0,0
|
||||||
PRODUCTVERSION 3,7,0,0
|
PRODUCTVERSION 4,0,0,0
|
||||||
BEGIN
|
BEGIN
|
||||||
BLOCK "StringFileInfo"
|
BLOCK "StringFileInfo"
|
||||||
BEGIN
|
BEGIN
|
||||||
|
|
@ -11,12 +11,12 @@ BEGIN
|
||||||
BEGIN
|
BEGIN
|
||||||
//VALUE "CompanyName", "raylib technologies"
|
//VALUE "CompanyName", "raylib technologies"
|
||||||
VALUE "FileDescription", "raylib application (www.raylib.com)"
|
VALUE "FileDescription", "raylib application (www.raylib.com)"
|
||||||
VALUE "FileVersion", "3.7.0"
|
VALUE "FileVersion", "4.0.0"
|
||||||
VALUE "InternalName", "raylib app"
|
VALUE "InternalName", "raylib app"
|
||||||
VALUE "LegalCopyright", "(c) 2021 Ramon Santamaria (@raysan5)"
|
VALUE "LegalCopyright", "(c) 2021 Ramon Santamaria (@raysan5)"
|
||||||
//VALUE "OriginalFilename", "raylib_app.exe"
|
//VALUE "OriginalFilename", "raylib_app.exe"
|
||||||
VALUE "ProductName", "raylib app"
|
VALUE "ProductName", "raylib app"
|
||||||
VALUE "ProductVersion", "3.7.0"
|
VALUE "ProductVersion", "4.0.0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -88,7 +88,6 @@
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Types and Structures Definition
|
// Types and Structures Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
#if !defined(RL_VECTOR2_TYPE)
|
#if !defined(RL_VECTOR2_TYPE)
|
||||||
// Vector2 type
|
// Vector2 type
|
||||||
typedef struct Vector2 {
|
typedef struct Vector2 {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************************
|
/*******************************************************************************************
|
||||||
*
|
*
|
||||||
* raylib.camera - Camera system with multiple modes support
|
* rcamera - Basic camera system for multiple camera modes
|
||||||
*
|
*
|
||||||
* NOTE: Memory footprint of this library is aproximately 52 bytes (global variables)
|
* NOTE: Memory footprint of this library is aproximately 52 bytes (global variables)
|
||||||
*
|
*
|
||||||
|
|
@ -41,8 +41,8 @@
|
||||||
*
|
*
|
||||||
**********************************************************************************************/
|
**********************************************************************************************/
|
||||||
|
|
||||||
#ifndef CAMERA_H
|
#ifndef RCAMERA_H
|
||||||
#define CAMERA_H
|
#define RCAMERA_H
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Defines and Macros
|
// Defines and Macros
|
||||||
|
|
@ -204,6 +204,7 @@ typedef struct {
|
||||||
float targetDistance; // Camera distance from position to target
|
float targetDistance; // Camera distance from position to target
|
||||||
float playerEyesPosition; // Player eyes position from ground (in meters)
|
float playerEyesPosition; // Player eyes position from ground (in meters)
|
||||||
Vector2 angle; // Camera angle in plane XZ
|
Vector2 angle; // Camera angle in plane XZ
|
||||||
|
Vector2 previousMousePosition; // Previous mouse position
|
||||||
|
|
||||||
// Camera movement control keys
|
// Camera movement control keys
|
||||||
int moveControl[6]; // Move controls (CAMERA_FIRST_PERSON)
|
int moveControl[6]; // Move controls (CAMERA_FIRST_PERSON)
|
||||||
|
|
@ -220,6 +221,7 @@ static CameraData CAMERA = { // Global CAMERA state context
|
||||||
.targetDistance = 0,
|
.targetDistance = 0,
|
||||||
.playerEyesPosition = 1.85f,
|
.playerEyesPosition = 1.85f,
|
||||||
.angle = { 0 },
|
.angle = { 0 },
|
||||||
|
.previousMousePosition = { 0 },
|
||||||
.moveControl = { 'W', 'S', 'D', 'A', 'E', 'Q' },
|
.moveControl = { 'W', 'S', 'D', 'A', 'E', 'Q' },
|
||||||
.smoothZoomControl = 341, // raylib: KEY_LEFT_CONTROL
|
.smoothZoomControl = 341, // raylib: KEY_LEFT_CONTROL
|
||||||
.altControl = 342, // raylib: KEY_LEFT_ALT
|
.altControl = 342, // raylib: KEY_LEFT_ALT
|
||||||
|
|
@ -263,6 +265,8 @@ void SetCameraMode(Camera camera, int mode)
|
||||||
|
|
||||||
CAMERA.playerEyesPosition = camera.position.y; // Init player eyes position to camera Y position
|
CAMERA.playerEyesPosition = camera.position.y; // Init player eyes position to camera Y position
|
||||||
|
|
||||||
|
CAMERA.previousMousePosition = GetMousePosition(); // Init mouse position
|
||||||
|
|
||||||
// Lock cursor for first person and third person cameras
|
// Lock cursor for first person and third person cameras
|
||||||
if ((mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON)) DisableCursor();
|
if ((mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON)) DisableCursor();
|
||||||
else EnableCursor();
|
else EnableCursor();
|
||||||
|
|
@ -279,7 +283,6 @@ void SetCameraMode(Camera camera, int mode)
|
||||||
void UpdateCamera(Camera *camera)
|
void UpdateCamera(Camera *camera)
|
||||||
{
|
{
|
||||||
static int swingCounter = 0; // Used for 1st person swinging movement
|
static int swingCounter = 0; // Used for 1st person swinging movement
|
||||||
static Vector2 previousMousePosition = { 0.0f, 0.0f };
|
|
||||||
|
|
||||||
// TODO: Compute CAMERA.targetDistance and CAMERA.angle here (?)
|
// TODO: Compute CAMERA.targetDistance and CAMERA.angle here (?)
|
||||||
|
|
||||||
|
|
@ -302,10 +305,10 @@ void UpdateCamera(Camera *camera)
|
||||||
|
|
||||||
if (CAMERA.mode != CAMERA_CUSTOM)
|
if (CAMERA.mode != CAMERA_CUSTOM)
|
||||||
{
|
{
|
||||||
mousePositionDelta.x = mousePosition.x - previousMousePosition.x;
|
mousePositionDelta.x = mousePosition.x - CAMERA.previousMousePosition.x;
|
||||||
mousePositionDelta.y = mousePosition.y - previousMousePosition.y;
|
mousePositionDelta.y = mousePosition.y - CAMERA.previousMousePosition.y;
|
||||||
|
|
||||||
previousMousePosition = mousePosition;
|
CAMERA.previousMousePosition = mousePosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Support for multiple automatic camera modes
|
// Support for multiple automatic camera modes
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/**********************************************************************************************
|
/**********************************************************************************************
|
||||||
*
|
*
|
||||||
* raylib.core - Basic functions to manage windows, OpenGL context and input on multiple platforms
|
* rcore - Basic functions to manage windows, OpenGL context and input on multiple platforms
|
||||||
*
|
*
|
||||||
* PLATFORMS SUPPORTED:
|
* PLATFORMS SUPPORTED:
|
||||||
* - PLATFORM_DESKTOP: Windows (Win32, Win64)
|
* - PLATFORM_DESKTOP: Windows (Win32, Win64)
|
||||||
|
|
@ -39,10 +39,10 @@
|
||||||
* NOTE: If enabled, uses external module functions to load default raylib font (module: text)
|
* NOTE: If enabled, uses external module functions to load default raylib font (module: text)
|
||||||
*
|
*
|
||||||
* #define SUPPORT_CAMERA_SYSTEM
|
* #define SUPPORT_CAMERA_SYSTEM
|
||||||
* Camera module is included (camera.h) and multiple predefined cameras are available: free, 1st/3rd person, orbital
|
* Camera module is included (rcamera.h) and multiple predefined cameras are available: free, 1st/3rd person, orbital
|
||||||
*
|
*
|
||||||
* #define SUPPORT_GESTURES_SYSTEM
|
* #define SUPPORT_GESTURES_SYSTEM
|
||||||
* Gestures module is included (gestures.h) to support gestures detection: tap, hold, swipe, drag
|
* Gestures module is included (rgestures.h) to support gestures detection: tap, hold, swipe, drag
|
||||||
*
|
*
|
||||||
* #define SUPPORT_MOUSE_GESTURES
|
* #define SUPPORT_MOUSE_GESTURES
|
||||||
* Mouse gestures are directly mapped like touches and processed by gestures system.
|
* Mouse gestures are directly mapped like touches and processed by gestures system.
|
||||||
|
|
@ -129,12 +129,12 @@
|
||||||
|
|
||||||
#if defined(SUPPORT_GESTURES_SYSTEM)
|
#if defined(SUPPORT_GESTURES_SYSTEM)
|
||||||
#define GESTURES_IMPLEMENTATION
|
#define GESTURES_IMPLEMENTATION
|
||||||
#include "gestures.h" // Gestures detection functionality
|
#include "rgestures.h" // Gestures detection functionality
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(SUPPORT_CAMERA_SYSTEM)
|
#if defined(SUPPORT_CAMERA_SYSTEM)
|
||||||
#define CAMERA_IMPLEMENTATION
|
#define CAMERA_IMPLEMENTATION
|
||||||
#include "camera.h" // Camera system functionality
|
#include "rcamera.h" // Camera system functionality
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(SUPPORT_GIF_RECORDING)
|
#if defined(SUPPORT_GIF_RECORDING)
|
||||||
|
|
@ -298,7 +298,7 @@
|
||||||
#define MAX_GAMEPAD_BUTTONS 32 // Maximum number of buttons supported (per gamepad)
|
#define MAX_GAMEPAD_BUTTONS 32 // Maximum number of buttons supported (per gamepad)
|
||||||
#endif
|
#endif
|
||||||
#ifndef MAX_TOUCH_POINTS
|
#ifndef MAX_TOUCH_POINTS
|
||||||
#define MAX_TOUCH_POINTS 10 // Maximum number of touch points supported
|
#define MAX_TOUCH_POINTS 8 // Maximum number of touch points supported
|
||||||
#endif
|
#endif
|
||||||
#ifndef MAX_KEY_PRESSED_QUEUE
|
#ifndef MAX_KEY_PRESSED_QUEUE
|
||||||
#define MAX_KEY_PRESSED_QUEUE 16 // Maximum number of keys in the key input queue
|
#define MAX_KEY_PRESSED_QUEUE 16 // Maximum number of keys in the key input queue
|
||||||
|
|
@ -385,7 +385,7 @@ typedef struct CoreData {
|
||||||
Matrix screenScale; // Matrix to scale screen (framebuffer rendering)
|
Matrix screenScale; // Matrix to scale screen (framebuffer rendering)
|
||||||
|
|
||||||
char **dropFilesPath; // Store dropped files paths as strings
|
char **dropFilesPath; // Store dropped files paths as strings
|
||||||
int dropFilesCount; // Count dropped files strings
|
int dropFileCount; // Count dropped files strings
|
||||||
|
|
||||||
} Window;
|
} Window;
|
||||||
#if defined(PLATFORM_ANDROID)
|
#if defined(PLATFORM_ANDROID)
|
||||||
|
|
@ -411,7 +411,7 @@ typedef struct CoreData {
|
||||||
int keyPressedQueue[MAX_KEY_PRESSED_QUEUE]; // Input keys queue
|
int keyPressedQueue[MAX_KEY_PRESSED_QUEUE]; // Input keys queue
|
||||||
int keyPressedQueueCount; // Input keys queue count
|
int keyPressedQueueCount; // Input keys queue count
|
||||||
|
|
||||||
int charPressedQueue[MAX_CHAR_PRESSED_QUEUE]; // Input characters queue
|
int charPressedQueue[MAX_CHAR_PRESSED_QUEUE]; // Input characters queue (unicode)
|
||||||
int charPressedQueueCount; // Input characters queue count
|
int charPressedQueueCount; // Input characters queue count
|
||||||
|
|
||||||
#if defined(PLATFORM_RPI) || defined(PLATFORM_DRM)
|
#if defined(PLATFORM_RPI) || defined(PLATFORM_DRM)
|
||||||
|
|
@ -443,6 +443,8 @@ typedef struct CoreData {
|
||||||
#endif
|
#endif
|
||||||
} Mouse;
|
} Mouse;
|
||||||
struct {
|
struct {
|
||||||
|
int pointCount; // Number of touch points active
|
||||||
|
int pointId[MAX_TOUCH_POINTS]; // Point identifiers
|
||||||
Vector2 position[MAX_TOUCH_POINTS]; // Touch position on screen
|
Vector2 position[MAX_TOUCH_POINTS]; // Touch position on screen
|
||||||
char currentTouchState[MAX_TOUCH_POINTS]; // Registers current touch state
|
char currentTouchState[MAX_TOUCH_POINTS]; // Registers current touch state
|
||||||
char previousTouchState[MAX_TOUCH_POINTS]; // Registers previous touch state
|
char previousTouchState[MAX_TOUCH_POINTS]; // Registers previous touch state
|
||||||
|
|
@ -454,10 +456,10 @@ typedef struct CoreData {
|
||||||
char currentButtonState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Current gamepad buttons state
|
char currentButtonState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Current gamepad buttons state
|
||||||
char previousButtonState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Previous gamepad buttons state
|
char previousButtonState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Previous gamepad buttons state
|
||||||
float axisState[MAX_GAMEPADS][MAX_GAMEPAD_AXIS]; // Gamepad axis state
|
float axisState[MAX_GAMEPADS][MAX_GAMEPAD_AXIS]; // Gamepad axis state
|
||||||
#if defined(PLATFORM_RPI) || defined(PLATFORM_DRM)
|
#if defined(PLATFORM_RPI) || defined(PLATFORM_DRM) || defined(PLATFORM_WEB)
|
||||||
pthread_t threadId; // Gamepad reading thread id
|
pthread_t threadId; // Gamepad reading thread id
|
||||||
int streamId[MAX_GAMEPADS]; // Gamepad device file descriptor
|
int streamId[MAX_GAMEPADS]; // Gamepad device file descriptor
|
||||||
char name[64]; // Gamepad name holder
|
char name[MAX_GAMEPADS][64]; // Gamepad name holder
|
||||||
#endif
|
#endif
|
||||||
} Gamepad;
|
} Gamepad;
|
||||||
} Input;
|
} Input;
|
||||||
|
|
@ -481,14 +483,14 @@ typedef struct CoreData {
|
||||||
static CoreData CORE = { 0 }; // Global CORE state context
|
static CoreData CORE = { 0 }; // Global CORE state context
|
||||||
|
|
||||||
static char **dirFilesPath = NULL; // Store directory files paths as strings
|
static char **dirFilesPath = NULL; // Store directory files paths as strings
|
||||||
static int dirFilesCount = 0; // Count directory files strings
|
static int dirFileCount = 0; // Count directory files strings
|
||||||
|
|
||||||
#if defined(SUPPORT_SCREEN_CAPTURE)
|
#if defined(SUPPORT_SCREEN_CAPTURE)
|
||||||
static int screenshotCounter = 0; // Screenshots counter
|
static int screenshotCounter = 0; // Screenshots counter
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(SUPPORT_GIF_RECORDING)
|
#if defined(SUPPORT_GIF_RECORDING)
|
||||||
static int gifFramesCounter = 0; // GIF frames counter
|
static int gifFrameCounter = 0; // GIF frames counter
|
||||||
static bool gifRecording = false; // GIF recording state
|
static bool gifRecording = false; // GIF recording state
|
||||||
static MsfGifState gifState = { 0 }; // MSGIF context state
|
static MsfGifState gifState = { 0 }; // MSGIF context state
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1079,7 +1081,7 @@ bool IsWindowMaximized(void)
|
||||||
bool IsWindowFocused(void)
|
bool IsWindowFocused(void)
|
||||||
{
|
{
|
||||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
||||||
return ((CORE.Window.flags & FLAG_WINDOW_UNFOCUSED) == 0); // TODO!
|
return ((CORE.Window.flags & FLAG_WINDOW_UNFOCUSED) == 0);
|
||||||
#else
|
#else
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1926,10 +1928,10 @@ void EndDrawing(void)
|
||||||
if (gifRecording)
|
if (gifRecording)
|
||||||
{
|
{
|
||||||
#define GIF_RECORD_FRAMERATE 10
|
#define GIF_RECORD_FRAMERATE 10
|
||||||
gifFramesCounter++;
|
gifFrameCounter++;
|
||||||
|
|
||||||
// NOTE: We record one gif frame every 10 game frames
|
// NOTE: We record one gif frame every 10 game frames
|
||||||
if ((gifFramesCounter%GIF_RECORD_FRAMERATE) == 0)
|
if ((gifFrameCounter%GIF_RECORD_FRAMERATE) == 0)
|
||||||
{
|
{
|
||||||
// Get image data for the current frame (from backbuffer)
|
// Get image data for the current frame (from backbuffer)
|
||||||
// NOTE: This process is quite slow... :(
|
// NOTE: This process is quite slow... :(
|
||||||
|
|
@ -1939,7 +1941,7 @@ void EndDrawing(void)
|
||||||
RL_FREE(screenData); // Free image data
|
RL_FREE(screenData); // Free image data
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((gifFramesCounter/15)%2) == 1)
|
if (((gifFrameCounter/15)%2) == 1)
|
||||||
{
|
{
|
||||||
DrawCircle(30, CORE.Window.screen.height - 20, 10, MAROON);
|
DrawCircle(30, CORE.Window.screen.height - 20, 10, MAROON);
|
||||||
DrawText("GIF RECORDING", 50, CORE.Window.screen.height - 25, 10, RED);
|
DrawText("GIF RECORDING", 50, CORE.Window.screen.height - 25, 10, RED);
|
||||||
|
|
@ -1953,9 +1955,9 @@ void EndDrawing(void)
|
||||||
// Draw record/play indicator
|
// Draw record/play indicator
|
||||||
if (eventsRecording)
|
if (eventsRecording)
|
||||||
{
|
{
|
||||||
gifFramesCounter++;
|
gifFrameCounter++;
|
||||||
|
|
||||||
if (((gifFramesCounter/15)%2) == 1)
|
if (((gifFrameCounter/15)%2) == 1)
|
||||||
{
|
{
|
||||||
DrawCircle(30, CORE.Window.screen.height - 20, 10, MAROON);
|
DrawCircle(30, CORE.Window.screen.height - 20, 10, MAROON);
|
||||||
DrawText("EVENTS RECORDING", 50, CORE.Window.screen.height - 25, 10, RED);
|
DrawText("EVENTS RECORDING", 50, CORE.Window.screen.height - 25, 10, RED);
|
||||||
|
|
@ -1965,9 +1967,9 @@ void EndDrawing(void)
|
||||||
}
|
}
|
||||||
else if (eventsPlaying)
|
else if (eventsPlaying)
|
||||||
{
|
{
|
||||||
gifFramesCounter++;
|
gifFrameCounter++;
|
||||||
|
|
||||||
if (((gifFramesCounter/15)%2) == 1)
|
if (((gifFrameCounter/15)%2) == 1)
|
||||||
{
|
{
|
||||||
DrawCircle(30, CORE.Window.screen.height - 20, 10, LIME);
|
DrawCircle(30, CORE.Window.screen.height - 20, 10, LIME);
|
||||||
DrawText("EVENTS PLAYING", 50, CORE.Window.screen.height - 25, 10, GREEN);
|
DrawText("EVENTS PLAYING", 50, CORE.Window.screen.height - 25, 10, GREEN);
|
||||||
|
|
@ -2667,6 +2669,12 @@ int GetRandomValue(int min, int max)
|
||||||
return (rand()%(abs(max - min) + 1) + min);
|
return (rand()%(abs(max - min) + 1) + min);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the seed for the random number generator
|
||||||
|
void SetRandomSeed(unsigned int seed)
|
||||||
|
{
|
||||||
|
srand(seed);
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the file exists
|
// Check if the file exists
|
||||||
bool FileExists(const char *fileName)
|
bool FileExists(const char *fileName)
|
||||||
{
|
{
|
||||||
|
|
@ -2767,9 +2775,9 @@ const char *GetFileNameWithoutExt(const char *filePath)
|
||||||
|
|
||||||
if (filePath != NULL) strcpy(fileName, GetFileName(filePath)); // Get filename with extension
|
if (filePath != NULL) strcpy(fileName, GetFileName(filePath)); // Get filename with extension
|
||||||
|
|
||||||
int len = (int)strlen(fileName);
|
int size = (int)strlen(fileName); // Get size in bytes
|
||||||
|
|
||||||
for (int i = 0; (i < len) && (i < MAX_FILENAMEWITHOUTEXT_LENGTH); i++)
|
for (int i = 0; (i < size) && (i < MAX_FILENAMEWITHOUTEXT_LENGTH); i++)
|
||||||
{
|
{
|
||||||
if (fileName[i] == '.')
|
if (fileName[i] == '.')
|
||||||
{
|
{
|
||||||
|
|
@ -2895,8 +2903,8 @@ char **GetDirectoryFiles(const char *dirPath, int *fileCount)
|
||||||
}
|
}
|
||||||
else TRACELOG(LOG_WARNING, "FILEIO: Failed to open requested directory"); // Maybe it's a file...
|
else TRACELOG(LOG_WARNING, "FILEIO: Failed to open requested directory"); // Maybe it's a file...
|
||||||
|
|
||||||
dirFilesCount = counter;
|
dirFileCount = counter;
|
||||||
*fileCount = dirFilesCount;
|
*fileCount = dirFileCount;
|
||||||
|
|
||||||
return dirFilesPath;
|
return dirFilesPath;
|
||||||
}
|
}
|
||||||
|
|
@ -2904,14 +2912,14 @@ char **GetDirectoryFiles(const char *dirPath, int *fileCount)
|
||||||
// Clear directory files paths buffers
|
// Clear directory files paths buffers
|
||||||
void ClearDirectoryFiles(void)
|
void ClearDirectoryFiles(void)
|
||||||
{
|
{
|
||||||
if (dirFilesCount > 0)
|
if (dirFileCount > 0)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < MAX_DIRECTORY_FILES; i++) RL_FREE(dirFilesPath[i]);
|
for (int i = 0; i < MAX_DIRECTORY_FILES; i++) RL_FREE(dirFilesPath[i]);
|
||||||
|
|
||||||
RL_FREE(dirFilesPath);
|
RL_FREE(dirFilesPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
dirFilesCount = 0;
|
dirFileCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change working directory, returns true on success
|
// Change working directory, returns true on success
|
||||||
|
|
@ -2927,27 +2935,27 @@ bool ChangeDirectory(const char *dir)
|
||||||
// Check if a file has been dropped into window
|
// Check if a file has been dropped into window
|
||||||
bool IsFileDropped(void)
|
bool IsFileDropped(void)
|
||||||
{
|
{
|
||||||
if (CORE.Window.dropFilesCount > 0) return true;
|
if (CORE.Window.dropFileCount > 0) return true;
|
||||||
else return false;
|
else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get dropped files names
|
// Get dropped files names
|
||||||
char **GetDroppedFiles(int *count)
|
char **GetDroppedFiles(int *count)
|
||||||
{
|
{
|
||||||
*count = CORE.Window.dropFilesCount;
|
*count = CORE.Window.dropFileCount;
|
||||||
return CORE.Window.dropFilesPath;
|
return CORE.Window.dropFilesPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear dropped files paths buffer
|
// Clear dropped files paths buffer
|
||||||
void ClearDroppedFiles(void)
|
void ClearDroppedFiles(void)
|
||||||
{
|
{
|
||||||
if (CORE.Window.dropFilesCount > 0)
|
if (CORE.Window.dropFileCount > 0)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < CORE.Window.dropFilesCount; i++) RL_FREE(CORE.Window.dropFilesPath[i]);
|
for (int i = 0; i < CORE.Window.dropFileCount; i++) RL_FREE(CORE.Window.dropFilesPath[i]);
|
||||||
|
|
||||||
RL_FREE(CORE.Window.dropFilesPath);
|
RL_FREE(CORE.Window.dropFilesPath);
|
||||||
|
|
||||||
CORE.Window.dropFilesCount = 0;
|
CORE.Window.dropFileCount = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3271,8 +3279,11 @@ const char *GetGamepadName(int gamepad)
|
||||||
else return NULL;
|
else return NULL;
|
||||||
#endif
|
#endif
|
||||||
#if defined(PLATFORM_RPI) || defined(PLATFORM_DRM)
|
#if defined(PLATFORM_RPI) || defined(PLATFORM_DRM)
|
||||||
if (CORE.Input.Gamepad.ready[gamepad]) ioctl(CORE.Input.Gamepad.streamId[gamepad], JSIOCGNAME(64), &CORE.Input.Gamepad.name);
|
if (CORE.Input.Gamepad.ready[gamepad]) ioctl(CORE.Input.Gamepad.streamId[gamepad], JSIOCGNAME(64), &CORE.Input.Gamepad.name[gamepad]);
|
||||||
return CORE.Input.Gamepad.name;
|
return CORE.Input.Gamepad.name[gamepad];
|
||||||
|
#endif
|
||||||
|
#if defined(PLATFORM_WEB)
|
||||||
|
return CORE.Input.Gamepad.name[gamepad];
|
||||||
#endif
|
#endif
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -3564,6 +3575,22 @@ Vector2 GetTouchPosition(int index)
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get touch point identifier for given index
|
||||||
|
int GetTouchPointId(int index)
|
||||||
|
{
|
||||||
|
int id = -1;
|
||||||
|
|
||||||
|
if (index < MAX_TOUCH_POINTS) id = CORE.Input.Touch.pointId[index];
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get number of touch points
|
||||||
|
int GetTouchPointCount(void)
|
||||||
|
{
|
||||||
|
return CORE.Input.Touch.pointCount;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module specific Functions Definition
|
// Module specific Functions Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
@ -4848,7 +4875,9 @@ static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent *
|
||||||
// NOTE: Window resizing not allowed by default
|
// NOTE: Window resizing not allowed by default
|
||||||
static void WindowSizeCallback(GLFWwindow *window, int width, int height)
|
static void WindowSizeCallback(GLFWwindow *window, int width, int height)
|
||||||
{
|
{
|
||||||
SetupViewport(width, height); // Reset viewport and projection matrix for new size
|
// Reset viewport and projection matrix for new size
|
||||||
|
SetupViewport(width, height);
|
||||||
|
|
||||||
CORE.Window.currentFbo.width = width;
|
CORE.Window.currentFbo.width = width;
|
||||||
CORE.Window.currentFbo.height = height;
|
CORE.Window.currentFbo.height = height;
|
||||||
CORE.Window.resizedLastFrame = true;
|
CORE.Window.resizedLastFrame = true;
|
||||||
|
|
@ -4858,8 +4887,8 @@ static void WindowSizeCallback(GLFWwindow *window, int width, int height)
|
||||||
// Set current screen size
|
// Set current screen size
|
||||||
CORE.Window.screen.width = width;
|
CORE.Window.screen.width = width;
|
||||||
CORE.Window.screen.height = height;
|
CORE.Window.screen.height = height;
|
||||||
// NOTE: Postprocessing texture is not scaled to new size
|
|
||||||
|
|
||||||
|
// NOTE: Postprocessing texture is not scaled to new size
|
||||||
}
|
}
|
||||||
|
|
||||||
// GLFW3 WindowIconify Callback, runs when window is minimized/restored
|
// GLFW3 WindowIconify Callback, runs when window is minimized/restored
|
||||||
|
|
@ -4922,7 +4951,7 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gifRecording = true;
|
gifRecording = true;
|
||||||
gifFramesCounter = 0;
|
gifFrameCounter = 0;
|
||||||
|
|
||||||
msf_gif_begin(&gifState, CORE.Window.screen.width, CORE.Window.screen.height);
|
msf_gif_begin(&gifState, CORE.Window.screen.width, CORE.Window.screen.height);
|
||||||
screenshotCounter++;
|
screenshotCounter++;
|
||||||
|
|
@ -4997,18 +5026,18 @@ static void MouseButtonCallback(GLFWwindow *window, int button, int action, int
|
||||||
// but future releases may add more actions (i.e. GLFW_REPEAT)
|
// but future releases may add more actions (i.e. GLFW_REPEAT)
|
||||||
CORE.Input.Mouse.currentButtonState[button] = action;
|
CORE.Input.Mouse.currentButtonState[button] = action;
|
||||||
|
|
||||||
#if defined(SUPPORT_GESTURES_SYSTEM) && defined(SUPPORT_MOUSE_GESTURES)
|
#if defined(SUPPORT_GESTURES_SYSTEM) && defined(SUPPORT_MOUSE_GESTURES) // PLATFORM_DESKTOP
|
||||||
// Process mouse events as touches to be able to use mouse-gestures
|
// Process mouse events as touches to be able to use mouse-gestures
|
||||||
GestureEvent gestureEvent = { 0 };
|
GestureEvent gestureEvent = { 0 };
|
||||||
|
|
||||||
// Register touch actions
|
// Register touch actions
|
||||||
if ((CORE.Input.Mouse.currentButtonState[button] == 1) && (CORE.Input.Mouse.previousButtonState[button] == 0)) gestureEvent.touchAction = TOUCH_DOWN;
|
if ((CORE.Input.Mouse.currentButtonState[button] == 1) && (CORE.Input.Mouse.previousButtonState[button] == 0)) gestureEvent.touchAction = TOUCH_ACTION_DOWN;
|
||||||
else if ((CORE.Input.Mouse.currentButtonState[button] == 0) && (CORE.Input.Mouse.previousButtonState[button] == 1)) gestureEvent.touchAction = TOUCH_UP;
|
else if ((CORE.Input.Mouse.currentButtonState[button] == 0) && (CORE.Input.Mouse.previousButtonState[button] == 1)) gestureEvent.touchAction = TOUCH_ACTION_UP;
|
||||||
|
|
||||||
// NOTE: TOUCH_MOVE event is registered in MouseCursorPosCallback()
|
// NOTE: TOUCH_ACTION_MOVE event is registered in MouseCursorPosCallback()
|
||||||
|
|
||||||
// Assign a pointer ID
|
// Assign a pointer ID
|
||||||
gestureEvent.pointerId[0] = 0;
|
gestureEvent.pointId[0] = 0;
|
||||||
|
|
||||||
// Register touch points count
|
// Register touch points count
|
||||||
gestureEvent.pointCount = 1;
|
gestureEvent.pointCount = 1;
|
||||||
|
|
@ -5032,14 +5061,14 @@ static void MouseCursorPosCallback(GLFWwindow *window, double x, double y)
|
||||||
CORE.Input.Mouse.currentPosition.y = (float)y;
|
CORE.Input.Mouse.currentPosition.y = (float)y;
|
||||||
CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
|
CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
|
||||||
|
|
||||||
#if defined(SUPPORT_GESTURES_SYSTEM) && defined(SUPPORT_MOUSE_GESTURES)
|
#if defined(SUPPORT_GESTURES_SYSTEM) && defined(SUPPORT_MOUSE_GESTURES) // PLATFORM_DESKTOP
|
||||||
// Process mouse events as touches to be able to use mouse-gestures
|
// Process mouse events as touches to be able to use mouse-gestures
|
||||||
GestureEvent gestureEvent = { 0 };
|
GestureEvent gestureEvent = { 0 };
|
||||||
|
|
||||||
gestureEvent.touchAction = TOUCH_MOVE;
|
gestureEvent.touchAction = TOUCH_ACTION_MOVE;
|
||||||
|
|
||||||
// Assign a pointer ID
|
// Assign a pointer ID
|
||||||
gestureEvent.pointerId[0] = 0;
|
gestureEvent.pointId[0] = 0;
|
||||||
|
|
||||||
// Register touch points count
|
// Register touch points count
|
||||||
gestureEvent.pointCount = 1;
|
gestureEvent.pointCount = 1;
|
||||||
|
|
@ -5085,7 +5114,7 @@ static void WindowDropCallback(GLFWwindow *window, int count, const char **paths
|
||||||
strcpy(CORE.Window.dropFilesPath[i], paths[i]);
|
strcpy(CORE.Window.dropFilesPath[i], paths[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
CORE.Window.dropFilesCount = count;
|
CORE.Window.dropFileCount = count;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -5145,7 +5174,7 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
|
||||||
/*
|
/*
|
||||||
if (assetsReloadRequired)
|
if (assetsReloadRequired)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < assetsCount; i++)
|
for (int i = 0; i < assetCount; i++)
|
||||||
{
|
{
|
||||||
// TODO: Unload old asset if required
|
// TODO: Unload old asset if required
|
||||||
|
|
||||||
|
|
@ -5272,63 +5301,47 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CORE.Input.Touch.position[0].x = AMotionEvent_getX(event, 0);
|
// Register touch points count
|
||||||
CORE.Input.Touch.position[0].y = AMotionEvent_getY(event, 0);
|
CORE.Input.Touch.pointCount = AMotionEvent_getPointerCount(event);
|
||||||
|
|
||||||
unsigned int touchCount = AMotionEvent_getPointerCount(event);
|
for (int i = 0; (i < CORE.Input.Touch.pointCount) && (i < MAX_TOUCH_POINTS); i++)
|
||||||
for (int i = 1; i < touchCount && i < MAX_TOUCH_POINTS; i++)
|
|
||||||
{
|
{
|
||||||
CORE.Input.Touch.position[i].x = AMotionEvent_getX(event, i);
|
// Register touch points id
|
||||||
CORE.Input.Touch.position[i].y = AMotionEvent_getY(event, i);
|
CORE.Input.Touch.pointId[i] = AMotionEvent_getPointerId(event, i);
|
||||||
|
|
||||||
|
// Register touch points position
|
||||||
|
CORE.Input.Touch.position[i] = (Vector2){ AMotionEvent_getX(event, i), AMotionEvent_getY(event, i) };
|
||||||
|
|
||||||
|
// Normalize CORE.Input.Touch.position[x] for screenWidth and screenHeight
|
||||||
|
CORE.Input.Touch.position[i].x /= (float)GetScreenWidth();
|
||||||
|
CORE.Input.Touch.position[i].y /= (float)GetScreenHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t action = AMotionEvent_getAction(event);
|
int32_t action = AMotionEvent_getAction(event);
|
||||||
unsigned int flags = action & AMOTION_EVENT_ACTION_MASK;
|
unsigned int flags = action & AMOTION_EVENT_ACTION_MASK;
|
||||||
|
|
||||||
if (flags == AMOTION_EVENT_ACTION_DOWN || flags == AMOTION_EVENT_ACTION_MOVE)
|
if (flags == AMOTION_EVENT_ACTION_DOWN || flags == AMOTION_EVENT_ACTION_MOVE) CORE.Input.Touch.currentTouchState[MOUSE_BUTTON_LEFT] = 1;
|
||||||
{
|
else if (flags == AMOTION_EVENT_ACTION_UP) CORE.Input.Touch.currentTouchState[MOUSE_BUTTON_LEFT] = 0;
|
||||||
CORE.Input.Touch.currentTouchState[MOUSE_BUTTON_LEFT] = 1;
|
|
||||||
}
|
|
||||||
else if (flags == AMOTION_EVENT_ACTION_UP)
|
|
||||||
{
|
|
||||||
CORE.Input.Touch.currentTouchState[MOUSE_BUTTON_LEFT] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(SUPPORT_GESTURES_SYSTEM)
|
#if defined(SUPPORT_GESTURES_SYSTEM) // PLATFORM_ANDROID
|
||||||
GestureEvent gestureEvent = { 0 };
|
GestureEvent gestureEvent = { 0 };
|
||||||
|
|
||||||
|
gestureEvent.pointCount = CORE.Input.Touch.pointCount;
|
||||||
|
|
||||||
// Register touch actions
|
// Register touch actions
|
||||||
if (flags == AMOTION_EVENT_ACTION_DOWN) gestureEvent.touchAction = TOUCH_DOWN;
|
if (flags == AMOTION_EVENT_ACTION_DOWN) gestureEvent.touchAction = TOUCH_ACTION_DOWN;
|
||||||
else if (flags == AMOTION_EVENT_ACTION_UP) gestureEvent.touchAction = TOUCH_UP;
|
else if (flags == AMOTION_EVENT_ACTION_UP) gestureEvent.touchAction = TOUCH_ACTION_UP;
|
||||||
else if (flags == AMOTION_EVENT_ACTION_MOVE) gestureEvent.touchAction = TOUCH_MOVE;
|
else if (flags == AMOTION_EVENT_ACTION_MOVE) gestureEvent.touchAction = TOUCH_ACTION_MOVE;
|
||||||
|
else if (flags == AMOTION_EVENT_ACTION_CANCEL) gestureEvent.touchAction = TOUCH_ACTION_CANCEL;
|
||||||
|
|
||||||
// Register touch points count
|
for (int i = 0; (i < gestureEvent.pointCount) && (i < MAX_TOUCH_POINTS); i++)
|
||||||
// NOTE: Documentation says pointerCount is Always >= 1,
|
|
||||||
// but in practice it can be 0 or over a million
|
|
||||||
gestureEvent.pointCount = AMotionEvent_getPointerCount(event);
|
|
||||||
|
|
||||||
// Only enable gestures for 1-3 touch points
|
|
||||||
if ((gestureEvent.pointCount > 0) && (gestureEvent.pointCount < 4))
|
|
||||||
{
|
{
|
||||||
// Register touch points id
|
gestureEvent.pointId[i] = CORE.Input.Touch.pointId[i];
|
||||||
// NOTE: Only two points registered
|
gestureEvent.position[i] = CORE.Input.Touch.position[i];
|
||||||
gestureEvent.pointerId[0] = AMotionEvent_getPointerId(event, 0);
|
}
|
||||||
gestureEvent.pointerId[1] = AMotionEvent_getPointerId(event, 1);
|
|
||||||
|
|
||||||
// Register touch points position
|
|
||||||
gestureEvent.position[0] = (Vector2){ AMotionEvent_getX(event, 0), AMotionEvent_getY(event, 0) };
|
|
||||||
gestureEvent.position[1] = (Vector2){ AMotionEvent_getX(event, 1), AMotionEvent_getY(event, 1) };
|
|
||||||
|
|
||||||
// Normalize gestureEvent.position[x] for screenWidth and screenHeight
|
|
||||||
gestureEvent.position[0].x /= (float)GetScreenWidth();
|
|
||||||
gestureEvent.position[0].y /= (float)GetScreenHeight();
|
|
||||||
|
|
||||||
gestureEvent.position[1].x /= (float)GetScreenWidth();
|
|
||||||
gestureEvent.position[1].y /= (float)GetScreenHeight();
|
|
||||||
|
|
||||||
// Gesture data is sent to gestures system for processing
|
// Gesture data is sent to gestures system for processing
|
||||||
ProcessGestureEvent(gestureEvent);
|
ProcessGestureEvent(gestureEvent);
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -5346,64 +5359,51 @@ static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent
|
||||||
// Register touch input events
|
// Register touch input events
|
||||||
static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData)
|
static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < touchEvent->numTouches; i++)
|
|
||||||
{
|
|
||||||
if (eventType == EMSCRIPTEN_EVENT_TOUCHSTART) CORE.Input.Touch.currentTouchState[i] = 1;
|
|
||||||
else if (eventType == EMSCRIPTEN_EVENT_TOUCHEND) CORE.Input.Touch.currentTouchState[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(SUPPORT_GESTURES_SYSTEM)
|
|
||||||
GestureEvent gestureEvent = { 0 };
|
|
||||||
|
|
||||||
// Register touch actions
|
|
||||||
if (eventType == EMSCRIPTEN_EVENT_TOUCHSTART) gestureEvent.touchAction = TOUCH_DOWN;
|
|
||||||
else if (eventType == EMSCRIPTEN_EVENT_TOUCHEND) gestureEvent.touchAction = TOUCH_UP;
|
|
||||||
else if (eventType == EMSCRIPTEN_EVENT_TOUCHMOVE) gestureEvent.touchAction = TOUCH_MOVE;
|
|
||||||
|
|
||||||
// Register touch points count
|
// Register touch points count
|
||||||
gestureEvent.pointCount = touchEvent->numTouches;
|
CORE.Input.Touch.pointCount = touchEvent->numTouches;
|
||||||
|
|
||||||
// Register touch points id
|
double canvasWidth = 0.0;
|
||||||
gestureEvent.pointerId[0] = touchEvent->touches[0].identifier;
|
double canvasHeight = 0.0;
|
||||||
gestureEvent.pointerId[1] = touchEvent->touches[1].identifier;
|
|
||||||
|
|
||||||
// Register touch points position
|
|
||||||
// NOTE: Only two points registered
|
|
||||||
gestureEvent.position[0] = (Vector2){ touchEvent->touches[0].targetX, touchEvent->touches[0].targetY };
|
|
||||||
gestureEvent.position[1] = (Vector2){ touchEvent->touches[1].targetX, touchEvent->touches[1].targetY };
|
|
||||||
|
|
||||||
double canvasWidth, canvasHeight;
|
|
||||||
// NOTE: emscripten_get_canvas_element_size() returns canvas.width and canvas.height but
|
// NOTE: emscripten_get_canvas_element_size() returns canvas.width and canvas.height but
|
||||||
// we are looking for actual CSS size: canvas.style.width and canvas.style.height
|
// we are looking for actual CSS size: canvas.style.width and canvas.style.height
|
||||||
//EMSCRIPTEN_RESULT res = emscripten_get_canvas_element_size("#canvas", &canvasWidth, &canvasHeight);
|
//EMSCRIPTEN_RESULT res = emscripten_get_canvas_element_size("#canvas", &canvasWidth, &canvasHeight);
|
||||||
emscripten_get_element_css_size("#canvas", &canvasWidth, &canvasHeight);
|
emscripten_get_element_css_size("#canvas", &canvasWidth, &canvasHeight);
|
||||||
|
|
||||||
// Normalize gestureEvent.position[x] for CORE.Window.screen.width and CORE.Window.screen.height
|
for (int i = 0; (i < CORE.Input.Touch.pointCount) && (i < MAX_TOUCH_POINTS); i++)
|
||||||
gestureEvent.position[0].x *= ((float)GetScreenWidth()/(float)canvasWidth);
|
{
|
||||||
gestureEvent.position[0].y *= ((float)GetScreenHeight()/(float)canvasHeight);
|
// Register touch points id
|
||||||
gestureEvent.position[1].x *= ((float)GetScreenWidth()/(float)canvasWidth);
|
CORE.Input.Touch.pointId[i] = touchEvent->touches[i].identifier;
|
||||||
gestureEvent.position[1].y *= ((float)GetScreenHeight()/(float)canvasHeight);
|
|
||||||
|
|
||||||
CORE.Input.Touch.position[0] = gestureEvent.position[0];
|
// Register touch points position
|
||||||
CORE.Input.Touch.position[1] = gestureEvent.position[1];
|
CORE.Input.Touch.position[i] = (Vector2){ touchEvent->touches[i].targetX, touchEvent->touches[i].targetY };
|
||||||
|
|
||||||
|
// Normalize gestureEvent.position[x] for CORE.Window.screen.width and CORE.Window.screen.height
|
||||||
|
CORE.Input.Touch.position[i].x *= ((float)GetScreenWidth()/(float)canvasWidth);
|
||||||
|
CORE.Input.Touch.position[i].y *= ((float)GetScreenHeight()/(float)canvasHeight);
|
||||||
|
|
||||||
|
if (eventType == EMSCRIPTEN_EVENT_TOUCHSTART) CORE.Input.Touch.currentTouchState[i] = 1;
|
||||||
|
else if (eventType == EMSCRIPTEN_EVENT_TOUCHEND) CORE.Input.Touch.currentTouchState[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(SUPPORT_GESTURES_SYSTEM) // PLATFORM_WEB
|
||||||
|
GestureEvent gestureEvent = { 0 };
|
||||||
|
|
||||||
|
gestureEvent.pointCount = CORE.Input.Touch.pointCount;
|
||||||
|
|
||||||
|
// Register touch actions
|
||||||
|
if (eventType == EMSCRIPTEN_EVENT_TOUCHSTART) gestureEvent.touchAction = TOUCH_ACTION_DOWN;
|
||||||
|
else if (eventType == EMSCRIPTEN_EVENT_TOUCHEND) gestureEvent.touchAction = TOUCH_ACTION_UP;
|
||||||
|
else if (eventType == EMSCRIPTEN_EVENT_TOUCHMOVE) gestureEvent.touchAction = TOUCH_ACTION_MOVE;
|
||||||
|
else if (eventType == EMSCRIPTEN_EVENT_TOUCHCANCEL) gestureEvent.touchAction = TOUCH_ACTION_CANCEL;
|
||||||
|
|
||||||
|
for (int i = 0; (i < gestureEvent.pointCount) && (i < MAX_TOUCH_POINTS); i++)
|
||||||
|
{
|
||||||
|
gestureEvent.pointId[i] = CORE.Input.Touch.pointId[i];
|
||||||
|
gestureEvent.position[i] = CORE.Input.Touch.position[i];
|
||||||
|
}
|
||||||
|
|
||||||
// Gesture data is sent to gestures system for processing
|
// Gesture data is sent to gestures system for processing
|
||||||
ProcessGestureEvent(gestureEvent);
|
ProcessGestureEvent(gestureEvent);
|
||||||
#else
|
|
||||||
// Support only simple touch position
|
|
||||||
if (eventType == EMSCRIPTEN_EVENT_TOUCHSTART)
|
|
||||||
{
|
|
||||||
// Get first touch position
|
|
||||||
CORE.Input.Touch.position[0] = (Vector2){ touchEvent->touches[0].targetX, touchEvent->touches[0].targetY };
|
|
||||||
|
|
||||||
double canvasWidth, canvasHeight;
|
|
||||||
//EMSCRIPTEN_RESULT res = emscripten_get_canvas_element_size("#canvas", &canvasWidth, &canvasHeight);
|
|
||||||
emscripten_get_element_css_size("#canvas", &canvasWidth, &canvasHeight);
|
|
||||||
|
|
||||||
// Normalize gestureEvent.position[x] for screenWidth and screenHeight
|
|
||||||
CORE.Input.Touch.position[0].x *= ((float)GetScreenWidth()/(float)canvasWidth);
|
|
||||||
CORE.Input.Touch.position[0].y *= ((float)GetScreenHeight()/(float)canvasHeight);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -5421,7 +5421,11 @@ static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadE
|
||||||
for (int i = 0; i < gamepadEvent->numButtons; ++i) TRACELOGD("Button %d: Digital: %d, Analog: %g", i, gamepadEvent->digitalButton[i], gamepadEvent->analogButton[i]);
|
for (int i = 0; i < gamepadEvent->numButtons; ++i) TRACELOGD("Button %d: Digital: %d, Analog: %g", i, gamepadEvent->digitalButton[i], gamepadEvent->analogButton[i]);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ((gamepadEvent->connected) && (gamepadEvent->index < MAX_GAMEPADS)) CORE.Input.Gamepad.ready[gamepadEvent->index] = true;
|
if ((gamepadEvent->connected) && (gamepadEvent->index < MAX_GAMEPADS))
|
||||||
|
{
|
||||||
|
CORE.Input.Gamepad.ready[gamepadEvent->index] = true;
|
||||||
|
sprintf(CORE.Input.Gamepad.name[gamepadEvent->index],"%s",gamepadEvent->id);
|
||||||
|
}
|
||||||
else CORE.Input.Gamepad.ready[gamepadEvent->index] = false;
|
else CORE.Input.Gamepad.ready[gamepadEvent->index] = false;
|
||||||
|
|
||||||
// TODO: Test gamepadEvent->index
|
// TODO: Test gamepadEvent->index
|
||||||
|
|
@ -5923,8 +5927,8 @@ static void *EventThread(void *arg)
|
||||||
struct input_event event = { 0 };
|
struct input_event event = { 0 };
|
||||||
InputEventWorker *worker = (InputEventWorker *)arg;
|
InputEventWorker *worker = (InputEventWorker *)arg;
|
||||||
|
|
||||||
int touchAction = -1;
|
int touchAction = -1; // 0-TOUCH_ACTION_UP, 1-TOUCH_ACTION_DOWN, 2-TOUCH_ACTION_MOVE
|
||||||
bool gestureUpdate = false;
|
bool gestureUpdate = false; // Flag to note gestures require to update
|
||||||
|
|
||||||
while (!CORE.Window.shouldClose)
|
while (!CORE.Window.shouldClose)
|
||||||
{
|
{
|
||||||
|
|
@ -5939,10 +5943,8 @@ static void *EventThread(void *arg)
|
||||||
CORE.Input.Mouse.currentPosition.x += event.value;
|
CORE.Input.Mouse.currentPosition.x += event.value;
|
||||||
CORE.Input.Touch.position[0].x = CORE.Input.Mouse.currentPosition.x;
|
CORE.Input.Touch.position[0].x = CORE.Input.Mouse.currentPosition.x;
|
||||||
|
|
||||||
#if defined(SUPPORT_GESTURES_SYSTEM)
|
touchAction = 2; // TOUCH_ACTION_MOVE
|
||||||
touchAction = TOUCH_MOVE;
|
|
||||||
gestureUpdate = true;
|
gestureUpdate = true;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.code == REL_Y)
|
if (event.code == REL_Y)
|
||||||
|
|
@ -5950,10 +5952,8 @@ static void *EventThread(void *arg)
|
||||||
CORE.Input.Mouse.currentPosition.y += event.value;
|
CORE.Input.Mouse.currentPosition.y += event.value;
|
||||||
CORE.Input.Touch.position[0].y = CORE.Input.Mouse.currentPosition.y;
|
CORE.Input.Touch.position[0].y = CORE.Input.Mouse.currentPosition.y;
|
||||||
|
|
||||||
#if defined(SUPPORT_GESTURES_SYSTEM)
|
touchAction = 2; // TOUCH_ACTION_MOVE
|
||||||
touchAction = TOUCH_MOVE;
|
|
||||||
gestureUpdate = true;
|
gestureUpdate = true;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.code == REL_WHEEL) CORE.Input.Mouse.currentWheelMove += event.value;
|
if (event.code == REL_WHEEL) CORE.Input.Mouse.currentWheelMove += event.value;
|
||||||
|
|
@ -5968,10 +5968,8 @@ static void *EventThread(void *arg)
|
||||||
CORE.Input.Mouse.currentPosition.x = (event.value - worker->absRange.x)*CORE.Window.screen.width/worker->absRange.width; // Scale acording to absRange
|
CORE.Input.Mouse.currentPosition.x = (event.value - worker->absRange.x)*CORE.Window.screen.width/worker->absRange.width; // Scale acording to absRange
|
||||||
CORE.Input.Touch.position[0].x = (event.value - worker->absRange.x)*CORE.Window.screen.width/worker->absRange.width; // Scale acording to absRange
|
CORE.Input.Touch.position[0].x = (event.value - worker->absRange.x)*CORE.Window.screen.width/worker->absRange.width; // Scale acording to absRange
|
||||||
|
|
||||||
#if defined(SUPPORT_GESTURES_SYSTEM)
|
touchAction = 2; // TOUCH_ACTION_MOVE
|
||||||
touchAction = TOUCH_MOVE;
|
|
||||||
gestureUpdate = true;
|
gestureUpdate = true;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.code == ABS_Y)
|
if (event.code == ABS_Y)
|
||||||
|
|
@ -5979,10 +5977,8 @@ static void *EventThread(void *arg)
|
||||||
CORE.Input.Mouse.currentPosition.y = (event.value - worker->absRange.y)*CORE.Window.screen.height/worker->absRange.height; // Scale acording to absRange
|
CORE.Input.Mouse.currentPosition.y = (event.value - worker->absRange.y)*CORE.Window.screen.height/worker->absRange.height; // Scale acording to absRange
|
||||||
CORE.Input.Touch.position[0].y = (event.value - worker->absRange.y)*CORE.Window.screen.height/worker->absRange.height; // Scale acording to absRange
|
CORE.Input.Touch.position[0].y = (event.value - worker->absRange.y)*CORE.Window.screen.height/worker->absRange.height; // Scale acording to absRange
|
||||||
|
|
||||||
#if defined(SUPPORT_GESTURES_SYSTEM)
|
touchAction = 2; // TOUCH_ACTION_MOVE
|
||||||
touchAction = TOUCH_MOVE;
|
|
||||||
gestureUpdate = true;
|
gestureUpdate = true;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Multitouch movement
|
// Multitouch movement
|
||||||
|
|
@ -6017,20 +6013,16 @@ static void *EventThread(void *arg)
|
||||||
{
|
{
|
||||||
CORE.Input.Mouse.currentButtonStateEvdev[MOUSE_BUTTON_LEFT] = 0;
|
CORE.Input.Mouse.currentButtonStateEvdev[MOUSE_BUTTON_LEFT] = 0;
|
||||||
|
|
||||||
#if defined(SUPPORT_GESTURES_SYSTEM)
|
touchAction = 0; // TOUCH_ACTION_UP
|
||||||
touchAction = TOUCH_UP;
|
|
||||||
gestureUpdate = true;
|
gestureUpdate = true;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.value && !previousMouseLeftButtonState)
|
if (event.value && !previousMouseLeftButtonState)
|
||||||
{
|
{
|
||||||
CORE.Input.Mouse.currentButtonStateEvdev[MOUSE_BUTTON_LEFT] = 1;
|
CORE.Input.Mouse.currentButtonStateEvdev[MOUSE_BUTTON_LEFT] = 1;
|
||||||
|
|
||||||
#if defined(SUPPORT_GESTURES_SYSTEM)
|
touchAction = 1; // TOUCH_ACTION_DOWN
|
||||||
touchAction = TOUCH_DOWN;
|
|
||||||
gestureUpdate = true;
|
gestureUpdate = true;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -6044,11 +6036,9 @@ static void *EventThread(void *arg)
|
||||||
{
|
{
|
||||||
CORE.Input.Mouse.currentButtonStateEvdev[MOUSE_BUTTON_LEFT] = event.value;
|
CORE.Input.Mouse.currentButtonStateEvdev[MOUSE_BUTTON_LEFT] = event.value;
|
||||||
|
|
||||||
#if defined(SUPPORT_GESTURES_SYSTEM)
|
if (event.value > 0) touchAction = 1; // TOUCH_ACTION_DOWN
|
||||||
if (event.value > 0) touchAction = TOUCH_DOWN;
|
else touchAction = 0; // TOUCH_ACTION_UP
|
||||||
else touchAction = TOUCH_UP;
|
|
||||||
gestureUpdate = true;
|
gestureUpdate = true;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.code == BTN_RIGHT) CORE.Input.Mouse.currentButtonStateEvdev[MOUSE_BUTTON_RIGHT] = event.value;
|
if (event.code == BTN_RIGHT) CORE.Input.Mouse.currentButtonStateEvdev[MOUSE_BUTTON_RIGHT] = event.value;
|
||||||
|
|
@ -6069,7 +6059,7 @@ static void *EventThread(void *arg)
|
||||||
if (CORE.Input.Mouse.currentPosition.y > CORE.Window.screen.height/CORE.Input.Mouse.scale.y) CORE.Input.Mouse.currentPosition.y = CORE.Window.screen.height/CORE.Input.Mouse.scale.y;
|
if (CORE.Input.Mouse.currentPosition.y > CORE.Window.screen.height/CORE.Input.Mouse.scale.y) CORE.Input.Mouse.currentPosition.y = CORE.Window.screen.height/CORE.Input.Mouse.scale.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(SUPPORT_GESTURES_SYSTEM)
|
#if defined(SUPPORT_GESTURES_SYSTEM) // PLATFORM_RPI, PLATFORM_DRM
|
||||||
if (gestureUpdate)
|
if (gestureUpdate)
|
||||||
{
|
{
|
||||||
GestureEvent gestureEvent = { 0 };
|
GestureEvent gestureEvent = { 0 };
|
||||||
|
|
@ -6082,10 +6072,10 @@ static void *EventThread(void *arg)
|
||||||
if (CORE.Input.Touch.position[2].x >= 0) gestureEvent.pointCount++;
|
if (CORE.Input.Touch.position[2].x >= 0) gestureEvent.pointCount++;
|
||||||
if (CORE.Input.Touch.position[3].x >= 0) gestureEvent.pointCount++;
|
if (CORE.Input.Touch.position[3].x >= 0) gestureEvent.pointCount++;
|
||||||
|
|
||||||
gestureEvent.pointerId[0] = 0;
|
gestureEvent.pointId[0] = 0;
|
||||||
gestureEvent.pointerId[1] = 1;
|
gestureEvent.pointId[1] = 1;
|
||||||
gestureEvent.pointerId[2] = 2;
|
gestureEvent.pointId[2] = 2;
|
||||||
gestureEvent.pointerId[3] = 3;
|
gestureEvent.pointId[3] = 3;
|
||||||
|
|
||||||
gestureEvent.position[0] = CORE.Input.Touch.position[0];
|
gestureEvent.position[0] = CORE.Input.Touch.position[0];
|
||||||
gestureEvent.position[1] = CORE.Input.Touch.position[1];
|
gestureEvent.position[1] = CORE.Input.Touch.position[1];
|
||||||
|
|
@ -6627,7 +6617,7 @@ static void PlayAutomationEvent(unsigned int frame)
|
||||||
{
|
{
|
||||||
CORE.Input.Gamepad.axisState[events[i].params[0]][events[i].params[1]] = ((float)events[i].params[2]/32768.0f);
|
CORE.Input.Gamepad.axisState[events[i].params[0]][events[i].params[1]] = ((float)events[i].params[2]/32768.0f);
|
||||||
} break;
|
} break;
|
||||||
case INPUT_GESTURE: GESTURES.current = events[i].params[0]; break; // param[0]: gesture (enum Gesture) -> gestures.h: GESTURES.current
|
case INPUT_GESTURE: GESTURES.current = events[i].params[0]; break; // param[0]: gesture (enum Gesture) -> rgestures.h: GESTURES.current
|
||||||
|
|
||||||
// Window events
|
// Window events
|
||||||
case WINDOW_CLOSE: CORE.Window.shouldClose = true; break;
|
case WINDOW_CLOSE: CORE.Window.shouldClose = true; break;
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/**********************************************************************************************
|
/**********************************************************************************************
|
||||||
*
|
*
|
||||||
* raylib.gestures - Gestures system, gestures processing based on input events (touch/mouse)
|
* rgestures - Gestures system, gestures processing based on input events (touch/mouse)
|
||||||
*
|
*
|
||||||
* NOTE: Memory footprint of this library is aproximately 128 bytes (global variables)
|
* NOTE: Memory footprint of this library is aproximately 128 bytes (global variables)
|
||||||
*
|
*
|
||||||
|
|
@ -43,8 +43,8 @@
|
||||||
*
|
*
|
||||||
**********************************************************************************************/
|
**********************************************************************************************/
|
||||||
|
|
||||||
#ifndef GESTURES_H
|
#ifndef RGESTURES_H
|
||||||
#define GESTURES_H
|
#define RGESTURES_H
|
||||||
|
|
||||||
#ifndef PI
|
#ifndef PI
|
||||||
#define PI 3.14159265358979323846
|
#define PI 3.14159265358979323846
|
||||||
|
|
@ -53,27 +53,33 @@
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Defines and Macros
|
// Defines and Macros
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
//...
|
#ifndef MAX_TOUCH_POINTS
|
||||||
|
#define MAX_TOUCH_POINTS 8 // Maximum number of touch points supported
|
||||||
|
#endif
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Types and Structures Definition
|
// Types and Structures Definition
|
||||||
// NOTE: Below types are required for GESTURES_STANDALONE usage
|
// NOTE: Below types are required for GESTURES_STANDALONE usage
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
#if defined(GESTURES_STANDALONE)
|
// Boolean type
|
||||||
#ifndef __cplusplus
|
#if defined(__STDC__) && __STDC_VERSION__ >= 199901L
|
||||||
// Boolean type
|
#include <stdbool.h>
|
||||||
typedef enum { false, true } bool;
|
#elif !defined(__cplusplus) && !defined(bool) && !defined(RL_BOOL_TYPE)
|
||||||
#endif
|
typedef enum bool { false, true } bool;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Vector2 type
|
#if !defined(RL_VECTOR2_TYPE)
|
||||||
typedef struct Vector2 {
|
// Vector2 type
|
||||||
|
typedef struct Vector2 {
|
||||||
float x;
|
float x;
|
||||||
float y;
|
float y;
|
||||||
} Vector2;
|
} Vector2;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Gestures type
|
#if defined(GESTURES_STANDALONE)
|
||||||
// NOTE: It could be used as flags to enable only some gestures
|
// Gestures type
|
||||||
typedef enum {
|
// NOTE: It could be used as flags to enable only some gestures
|
||||||
|
typedef enum {
|
||||||
GESTURE_NONE = 0,
|
GESTURE_NONE = 0,
|
||||||
GESTURE_TAP = 1,
|
GESTURE_TAP = 1,
|
||||||
GESTURE_DOUBLETAP = 2,
|
GESTURE_DOUBLETAP = 2,
|
||||||
|
|
@ -85,18 +91,22 @@
|
||||||
GESTURE_SWIPE_DOWN = 128,
|
GESTURE_SWIPE_DOWN = 128,
|
||||||
GESTURE_PINCH_IN = 256,
|
GESTURE_PINCH_IN = 256,
|
||||||
GESTURE_PINCH_OUT = 512
|
GESTURE_PINCH_OUT = 512
|
||||||
} Gestures;
|
} Gesture;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef enum { TOUCH_UP, TOUCH_DOWN, TOUCH_MOVE } TouchAction;
|
typedef enum {
|
||||||
|
TOUCH_ACTION_UP = 0,
|
||||||
|
TOUCH_ACTION_DOWN,
|
||||||
|
TOUCH_ACTION_MOVE,
|
||||||
|
TOUCH_ACTION_CANCEL
|
||||||
|
} TouchAction;
|
||||||
|
|
||||||
// Gesture event
|
// Gesture event
|
||||||
// NOTE: MAX_TOUCH_POINTS fixed to 4
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int touchAction;
|
int touchAction;
|
||||||
int pointCount;
|
int pointCount;
|
||||||
int pointerId[4];
|
int pointId[MAX_TOUCH_POINTS];
|
||||||
Vector2 position[4];
|
Vector2 position[MAX_TOUCH_POINTS];
|
||||||
} GestureEvent;
|
} GestureEvent;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
@ -114,11 +124,12 @@ extern "C" { // Prevents name mangling of functions
|
||||||
|
|
||||||
void ProcessGestureEvent(GestureEvent event); // Process gesture event and translate it into gestures
|
void ProcessGestureEvent(GestureEvent event); // Process gesture event and translate it into gestures
|
||||||
void UpdateGestures(void); // Update gestures detected (must be called every frame)
|
void UpdateGestures(void); // Update gestures detected (must be called every frame)
|
||||||
|
|
||||||
#if defined(GESTURES_STANDALONE)
|
#if defined(GESTURES_STANDALONE)
|
||||||
void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
|
void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
|
||||||
bool IsGestureDetected(int gesture); // Check if a gesture have been detected
|
bool IsGestureDetected(int gesture); // Check if a gesture have been detected
|
||||||
int GetGestureDetected(void); // Get latest detected gesture
|
int GetGestureDetected(void); // Get latest detected gesture
|
||||||
int GetTouchPointsCount(void); // Get touch points count
|
|
||||||
float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds
|
float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds
|
||||||
Vector2 GetGestureDragVector(void); // Get gesture drag vector
|
Vector2 GetGestureDragVector(void); // Get gesture drag vector
|
||||||
float GetGestureDragAngle(void); // Get gesture drag angle
|
float GetGestureDragAngle(void); // Get gesture drag angle
|
||||||
|
|
@ -193,7 +204,7 @@ typedef struct {
|
||||||
Vector2 downDragPosition; // Touch drag position
|
Vector2 downDragPosition; // Touch drag position
|
||||||
Vector2 moveDownPositionA; // First touch down position on move
|
Vector2 moveDownPositionA; // First touch down position on move
|
||||||
Vector2 moveDownPositionB; // Second touch down position on move
|
Vector2 moveDownPositionB; // Second touch down position on move
|
||||||
int tapCounter; // TAP counter (one tap implies TOUCH_DOWN and TOUCH_UP actions)
|
int tapCounter; // TAP counter (one tap implies TOUCH_ACTION_DOWN and TOUCH_ACTION_UP actions)
|
||||||
} Touch;
|
} Touch;
|
||||||
struct {
|
struct {
|
||||||
bool resetRequired; // HOLD reset to get first touch point again
|
bool resetRequired; // HOLD reset to get first touch point again
|
||||||
|
|
@ -228,12 +239,9 @@ static GesturesData GESTURES = {
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module specific Functions Declaration
|
// Module specific Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
#if defined(GESTURES_STANDALONE)
|
static float rgVector2Angle(Vector2 initialPosition, Vector2 finalPosition);
|
||||||
// Some required math functions provided by raymath.h
|
static float rgVector2Distance(Vector2 v1, Vector2 v2);
|
||||||
static float Vector2Angle(Vector2 initialPosition, Vector2 finalPosition);
|
static double rgGetCurrentTime(void);
|
||||||
static float Vector2Distance(Vector2 v1, Vector2 v2);
|
|
||||||
#endif
|
|
||||||
static double GetCurrentTime(void);
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Functions Definition
|
// Module Functions Definition
|
||||||
|
|
@ -258,14 +266,14 @@ void ProcessGestureEvent(GestureEvent event)
|
||||||
// Reset required variables
|
// Reset required variables
|
||||||
GESTURES.Touch.pointCount = event.pointCount; // Required on UpdateGestures()
|
GESTURES.Touch.pointCount = event.pointCount; // Required on UpdateGestures()
|
||||||
|
|
||||||
if (GESTURES.Touch.pointCount < 2)
|
if (GESTURES.Touch.pointCount == 1) // One touch point
|
||||||
{
|
{
|
||||||
if (event.touchAction == TOUCH_DOWN)
|
if (event.touchAction == TOUCH_ACTION_DOWN)
|
||||||
{
|
{
|
||||||
GESTURES.Touch.tapCounter++; // Tap counter
|
GESTURES.Touch.tapCounter++; // Tap counter
|
||||||
|
|
||||||
// Detect GESTURE_DOUBLE_TAP
|
// Detect GESTURE_DOUBLE_TAP
|
||||||
if ((GESTURES.current == GESTURE_NONE) && (GESTURES.Touch.tapCounter >= 2) && ((GetCurrentTime() - GESTURES.Touch.eventTime) < TAP_TIMEOUT) && (Vector2Distance(GESTURES.Touch.downPositionA, event.position[0]) < DOUBLETAP_RANGE))
|
if ((GESTURES.current == GESTURE_NONE) && (GESTURES.Touch.tapCounter >= 2) && ((rgGetCurrentTime() - GESTURES.Touch.eventTime) < TAP_TIMEOUT) && (rgVector2Distance(GESTURES.Touch.downPositionA, event.position[0]) < DOUBLETAP_RANGE))
|
||||||
{
|
{
|
||||||
GESTURES.current = GESTURE_DOUBLETAP;
|
GESTURES.current = GESTURE_DOUBLETAP;
|
||||||
GESTURES.Touch.tapCounter = 0;
|
GESTURES.Touch.tapCounter = 0;
|
||||||
|
|
@ -280,27 +288,27 @@ void ProcessGestureEvent(GestureEvent event)
|
||||||
GESTURES.Touch.downDragPosition = event.position[0];
|
GESTURES.Touch.downDragPosition = event.position[0];
|
||||||
|
|
||||||
GESTURES.Touch.upPosition = GESTURES.Touch.downPositionA;
|
GESTURES.Touch.upPosition = GESTURES.Touch.downPositionA;
|
||||||
GESTURES.Touch.eventTime = GetCurrentTime();
|
GESTURES.Touch.eventTime = rgGetCurrentTime();
|
||||||
|
|
||||||
GESTURES.Touch.firstId = event.pointerId[0];
|
GESTURES.Touch.firstId = event.pointId[0];
|
||||||
|
|
||||||
GESTURES.Drag.vector = (Vector2){ 0.0f, 0.0f };
|
GESTURES.Drag.vector = (Vector2){ 0.0f, 0.0f };
|
||||||
}
|
}
|
||||||
else if (event.touchAction == TOUCH_UP)
|
else if (event.touchAction == TOUCH_ACTION_UP)
|
||||||
{
|
{
|
||||||
if (GESTURES.current == GESTURE_DRAG) GESTURES.Touch.upPosition = event.position[0];
|
if (GESTURES.current == GESTURE_DRAG) GESTURES.Touch.upPosition = event.position[0];
|
||||||
|
|
||||||
// NOTE: GESTURES.Drag.intensity dependend on the resolution of the screen
|
// NOTE: GESTURES.Drag.intensity dependend on the resolution of the screen
|
||||||
GESTURES.Drag.distance = Vector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.upPosition);
|
GESTURES.Drag.distance = rgVector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.upPosition);
|
||||||
GESTURES.Drag.intensity = GESTURES.Drag.distance/(float)((GetCurrentTime() - GESTURES.Swipe.timeDuration));
|
GESTURES.Drag.intensity = GESTURES.Drag.distance/(float)((rgGetCurrentTime() - GESTURES.Swipe.timeDuration));
|
||||||
|
|
||||||
GESTURES.Swipe.start = false;
|
GESTURES.Swipe.start = false;
|
||||||
|
|
||||||
// Detect GESTURE_SWIPE
|
// Detect GESTURE_SWIPE
|
||||||
if ((GESTURES.Drag.intensity > FORCE_TO_SWIPE) && (GESTURES.Touch.firstId == event.pointerId[0]))
|
if ((GESTURES.Drag.intensity > FORCE_TO_SWIPE) && (GESTURES.Touch.firstId == event.pointId[0]))
|
||||||
{
|
{
|
||||||
// NOTE: Angle should be inverted in Y
|
// NOTE: Angle should be inverted in Y
|
||||||
GESTURES.Drag.angle = 360.0f - Vector2Angle(GESTURES.Touch.downPositionA, GESTURES.Touch.upPosition);
|
GESTURES.Drag.angle = 360.0f - rgVector2Angle(GESTURES.Touch.downPositionA, GESTURES.Touch.upPosition);
|
||||||
|
|
||||||
if ((GESTURES.Drag.angle < 30) || (GESTURES.Drag.angle > 330)) GESTURES.current = GESTURE_SWIPE_RIGHT; // Right
|
if ((GESTURES.Drag.angle < 30) || (GESTURES.Drag.angle > 330)) GESTURES.current = GESTURE_SWIPE_RIGHT; // Right
|
||||||
else if ((GESTURES.Drag.angle > 30) && (GESTURES.Drag.angle < 120)) GESTURES.current = GESTURE_SWIPE_UP; // Up
|
else if ((GESTURES.Drag.angle > 30) && (GESTURES.Drag.angle < 120)) GESTURES.current = GESTURE_SWIPE_UP; // Up
|
||||||
|
|
@ -320,13 +328,13 @@ void ProcessGestureEvent(GestureEvent event)
|
||||||
GESTURES.Touch.downDragPosition = (Vector2){ 0.0f, 0.0f };
|
GESTURES.Touch.downDragPosition = (Vector2){ 0.0f, 0.0f };
|
||||||
GESTURES.Touch.pointCount = 0;
|
GESTURES.Touch.pointCount = 0;
|
||||||
}
|
}
|
||||||
else if (event.touchAction == TOUCH_MOVE)
|
else if (event.touchAction == TOUCH_ACTION_MOVE)
|
||||||
{
|
{
|
||||||
if (GESTURES.current == GESTURE_DRAG) GESTURES.Touch.eventTime = GetCurrentTime();
|
if (GESTURES.current == GESTURE_DRAG) GESTURES.Touch.eventTime = rgGetCurrentTime();
|
||||||
|
|
||||||
if (!GESTURES.Swipe.start)
|
if (!GESTURES.Swipe.start)
|
||||||
{
|
{
|
||||||
GESTURES.Swipe.timeDuration = GetCurrentTime();
|
GESTURES.Swipe.timeDuration = rgGetCurrentTime();
|
||||||
GESTURES.Swipe.start = true;
|
GESTURES.Swipe.start = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -339,9 +347,9 @@ void ProcessGestureEvent(GestureEvent event)
|
||||||
GESTURES.Hold.resetRequired = false;
|
GESTURES.Hold.resetRequired = false;
|
||||||
|
|
||||||
// Detect GESTURE_DRAG
|
// Detect GESTURE_DRAG
|
||||||
if (Vector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.moveDownPositionA) >= MINIMUM_DRAG)
|
if (rgVector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.moveDownPositionA) >= MINIMUM_DRAG)
|
||||||
{
|
{
|
||||||
GESTURES.Touch.eventTime = GetCurrentTime();
|
GESTURES.Touch.eventTime = rgGetCurrentTime();
|
||||||
GESTURES.current = GESTURE_DRAG;
|
GESTURES.current = GESTURE_DRAG;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -350,24 +358,24 @@ void ProcessGestureEvent(GestureEvent event)
|
||||||
GESTURES.Drag.vector.y = GESTURES.Touch.moveDownPositionA.y - GESTURES.Touch.downDragPosition.y;
|
GESTURES.Drag.vector.y = GESTURES.Touch.moveDownPositionA.y - GESTURES.Touch.downDragPosition.y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // Two touch points
|
else if (GESTURES.Touch.pointCount == 2) // Two touch points
|
||||||
{
|
{
|
||||||
if (event.touchAction == TOUCH_DOWN)
|
if (event.touchAction == TOUCH_ACTION_DOWN)
|
||||||
{
|
{
|
||||||
GESTURES.Touch.downPositionA = event.position[0];
|
GESTURES.Touch.downPositionA = event.position[0];
|
||||||
GESTURES.Touch.downPositionB = event.position[1];
|
GESTURES.Touch.downPositionB = event.position[1];
|
||||||
|
|
||||||
//GESTURES.Pinch.distance = Vector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.downPositionB);
|
//GESTURES.Pinch.distance = rgVector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.downPositionB);
|
||||||
|
|
||||||
GESTURES.Pinch.vector.x = GESTURES.Touch.downPositionB.x - GESTURES.Touch.downPositionA.x;
|
GESTURES.Pinch.vector.x = GESTURES.Touch.downPositionB.x - GESTURES.Touch.downPositionA.x;
|
||||||
GESTURES.Pinch.vector.y = GESTURES.Touch.downPositionB.y - GESTURES.Touch.downPositionA.y;
|
GESTURES.Pinch.vector.y = GESTURES.Touch.downPositionB.y - GESTURES.Touch.downPositionA.y;
|
||||||
|
|
||||||
GESTURES.current = GESTURE_HOLD;
|
GESTURES.current = GESTURE_HOLD;
|
||||||
GESTURES.Hold.timeDuration = GetCurrentTime();
|
GESTURES.Hold.timeDuration = rgGetCurrentTime();
|
||||||
}
|
}
|
||||||
else if (event.touchAction == TOUCH_MOVE)
|
else if (event.touchAction == TOUCH_ACTION_MOVE)
|
||||||
{
|
{
|
||||||
GESTURES.Pinch.distance = Vector2Distance(GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB);
|
GESTURES.Pinch.distance = rgVector2Distance(GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB);
|
||||||
|
|
||||||
GESTURES.Touch.downPositionA = GESTURES.Touch.moveDownPositionA;
|
GESTURES.Touch.downPositionA = GESTURES.Touch.moveDownPositionA;
|
||||||
GESTURES.Touch.downPositionB = GESTURES.Touch.moveDownPositionB;
|
GESTURES.Touch.downPositionB = GESTURES.Touch.moveDownPositionB;
|
||||||
|
|
@ -378,21 +386,21 @@ void ProcessGestureEvent(GestureEvent event)
|
||||||
GESTURES.Pinch.vector.x = GESTURES.Touch.moveDownPositionB.x - GESTURES.Touch.moveDownPositionA.x;
|
GESTURES.Pinch.vector.x = GESTURES.Touch.moveDownPositionB.x - GESTURES.Touch.moveDownPositionA.x;
|
||||||
GESTURES.Pinch.vector.y = GESTURES.Touch.moveDownPositionB.y - GESTURES.Touch.moveDownPositionA.y;
|
GESTURES.Pinch.vector.y = GESTURES.Touch.moveDownPositionB.y - GESTURES.Touch.moveDownPositionA.y;
|
||||||
|
|
||||||
if ((Vector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.moveDownPositionA) >= MINIMUM_PINCH) || (Vector2Distance(GESTURES.Touch.downPositionB, GESTURES.Touch.moveDownPositionB) >= MINIMUM_PINCH))
|
if ((rgVector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.moveDownPositionA) >= MINIMUM_PINCH) || (rgVector2Distance(GESTURES.Touch.downPositionB, GESTURES.Touch.moveDownPositionB) >= MINIMUM_PINCH))
|
||||||
{
|
{
|
||||||
if ((Vector2Distance(GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB) - GESTURES.Pinch.distance) < 0) GESTURES.current = GESTURE_PINCH_IN;
|
if ((rgVector2Distance(GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB) - GESTURES.Pinch.distance) < 0) GESTURES.current = GESTURE_PINCH_IN;
|
||||||
else GESTURES.current = GESTURE_PINCH_OUT;
|
else GESTURES.current = GESTURE_PINCH_OUT;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GESTURES.current = GESTURE_HOLD;
|
GESTURES.current = GESTURE_HOLD;
|
||||||
GESTURES.Hold.timeDuration = GetCurrentTime();
|
GESTURES.Hold.timeDuration = rgGetCurrentTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Angle should be inverted in Y
|
// NOTE: Angle should be inverted in Y
|
||||||
GESTURES.Pinch.angle = 360.0f - Vector2Angle(GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB);
|
GESTURES.Pinch.angle = 360.0f - rgVector2Angle(GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB);
|
||||||
}
|
}
|
||||||
else if (event.touchAction == TOUCH_UP)
|
else if (event.touchAction == TOUCH_ACTION_UP)
|
||||||
{
|
{
|
||||||
GESTURES.Pinch.distance = 0.0f;
|
GESTURES.Pinch.distance = 0.0f;
|
||||||
GESTURES.Pinch.angle = 0.0f;
|
GESTURES.Pinch.angle = 0.0f;
|
||||||
|
|
@ -402,6 +410,10 @@ void ProcessGestureEvent(GestureEvent event)
|
||||||
GESTURES.current = GESTURE_NONE;
|
GESTURES.current = GESTURE_NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (GESTURES.Touch.pointCount > 2) // More than two touch points
|
||||||
|
{
|
||||||
|
// TODO.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update gestures detected (must be called every frame)
|
// Update gestures detected (must be called every frame)
|
||||||
|
|
@ -413,13 +425,13 @@ void UpdateGestures(void)
|
||||||
if (((GESTURES.current == GESTURE_TAP) || (GESTURES.current == GESTURE_DOUBLETAP)) && (GESTURES.Touch.pointCount < 2))
|
if (((GESTURES.current == GESTURE_TAP) || (GESTURES.current == GESTURE_DOUBLETAP)) && (GESTURES.Touch.pointCount < 2))
|
||||||
{
|
{
|
||||||
GESTURES.current = GESTURE_HOLD;
|
GESTURES.current = GESTURE_HOLD;
|
||||||
GESTURES.Hold.timeDuration = GetCurrentTime();
|
GESTURES.Hold.timeDuration = rgGetCurrentTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((GetCurrentTime() - GESTURES.Touch.eventTime) > TAP_TIMEOUT) && (GESTURES.current == GESTURE_DRAG) && (GESTURES.Touch.pointCount < 2))
|
if (((rgGetCurrentTime() - GESTURES.Touch.eventTime) > TAP_TIMEOUT) && (GESTURES.current == GESTURE_DRAG) && (GESTURES.Touch.pointCount < 2))
|
||||||
{
|
{
|
||||||
GESTURES.current = GESTURE_HOLD;
|
GESTURES.current = GESTURE_HOLD;
|
||||||
GESTURES.Hold.timeDuration = GetCurrentTime();
|
GESTURES.Hold.timeDuration = rgGetCurrentTime();
|
||||||
GESTURES.Hold.resetRequired = true;
|
GESTURES.Hold.resetRequired = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -430,14 +442,6 @@ void UpdateGestures(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get number of touch points
|
|
||||||
int GetTouchPointsCount(void)
|
|
||||||
{
|
|
||||||
// NOTE: point count is calculated when ProcessGestureEvent(GestureEvent event) is called
|
|
||||||
|
|
||||||
return GESTURES.Touch.pointCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get latest detected gesture
|
// Get latest detected gesture
|
||||||
int GetGestureDetected(void)
|
int GetGestureDetected(void)
|
||||||
{
|
{
|
||||||
|
|
@ -452,7 +456,7 @@ float GetGestureHoldDuration(void)
|
||||||
|
|
||||||
double time = 0.0;
|
double time = 0.0;
|
||||||
|
|
||||||
if (GESTURES.current == GESTURE_HOLD) time = GetCurrentTime() - GESTURES.Hold.timeDuration;
|
if (GESTURES.current == GESTURE_HOLD) time = rgGetCurrentTime() - GESTURES.Hold.timeDuration;
|
||||||
|
|
||||||
return (float)time;
|
return (float)time;
|
||||||
}
|
}
|
||||||
|
|
@ -460,7 +464,7 @@ float GetGestureHoldDuration(void)
|
||||||
// Get drag vector (between initial touch point to current)
|
// Get drag vector (between initial touch point to current)
|
||||||
Vector2 GetGestureDragVector(void)
|
Vector2 GetGestureDragVector(void)
|
||||||
{
|
{
|
||||||
// NOTE: drag vector is calculated on one touch points TOUCH_MOVE
|
// NOTE: drag vector is calculated on one touch points TOUCH_ACTION_MOVE
|
||||||
|
|
||||||
return GESTURES.Drag.vector;
|
return GESTURES.Drag.vector;
|
||||||
}
|
}
|
||||||
|
|
@ -469,7 +473,7 @@ Vector2 GetGestureDragVector(void)
|
||||||
// NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise
|
// NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise
|
||||||
float GetGestureDragAngle(void)
|
float GetGestureDragAngle(void)
|
||||||
{
|
{
|
||||||
// NOTE: drag angle is calculated on one touch points TOUCH_UP
|
// NOTE: drag angle is calculated on one touch points TOUCH_ACTION_UP
|
||||||
|
|
||||||
return GESTURES.Drag.angle;
|
return GESTURES.Drag.angle;
|
||||||
}
|
}
|
||||||
|
|
@ -477,8 +481,7 @@ float GetGestureDragAngle(void)
|
||||||
// Get distance between two pinch points
|
// Get distance between two pinch points
|
||||||
Vector2 GetGesturePinchVector(void)
|
Vector2 GetGesturePinchVector(void)
|
||||||
{
|
{
|
||||||
// NOTE: The position values used for GESTURES.Pinch.distance are not modified like the position values of [core.c]-->GetTouchPosition(int index)
|
// NOTE: Pinch distance is calculated on two touch points TOUCH_ACTION_MOVE
|
||||||
// NOTE: pinch distance is calculated on two touch points TOUCH_MOVE
|
|
||||||
|
|
||||||
return GESTURES.Pinch.vector;
|
return GESTURES.Pinch.vector;
|
||||||
}
|
}
|
||||||
|
|
@ -487,7 +490,7 @@ Vector2 GetGesturePinchVector(void)
|
||||||
// NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise
|
// NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise
|
||||||
float GetGesturePinchAngle(void)
|
float GetGesturePinchAngle(void)
|
||||||
{
|
{
|
||||||
// NOTE: pinch angle is calculated on two touch points TOUCH_MOVE
|
// NOTE: pinch angle is calculated on two touch points TOUCH_ACTION_MOVE
|
||||||
|
|
||||||
return GESTURES.Pinch.angle;
|
return GESTURES.Pinch.angle;
|
||||||
}
|
}
|
||||||
|
|
@ -495,9 +498,8 @@ float GetGesturePinchAngle(void)
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module specific Functions Definition
|
// Module specific Functions Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
#if defined(GESTURES_STANDALONE)
|
|
||||||
// Get angle from two-points vector with X-axis
|
// Get angle from two-points vector with X-axis
|
||||||
static float Vector2Angle(Vector2 v1, Vector2 v2)
|
static float rgVector2Angle(Vector2 v1, Vector2 v2)
|
||||||
{
|
{
|
||||||
float angle = atan2f(v2.y - v1.y, v2.x - v1.x)*(180.0f/PI);
|
float angle = atan2f(v2.y - v1.y, v2.x - v1.x)*(180.0f/PI);
|
||||||
|
|
||||||
|
|
@ -507,7 +509,7 @@ static float Vector2Angle(Vector2 v1, Vector2 v2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate distance between two Vector2
|
// Calculate distance between two Vector2
|
||||||
static float Vector2Distance(Vector2 v1, Vector2 v2)
|
static float rgVector2Distance(Vector2 v1, Vector2 v2)
|
||||||
{
|
{
|
||||||
float result;
|
float result;
|
||||||
|
|
||||||
|
|
@ -518,10 +520,9 @@ static float Vector2Distance(Vector2 v1, Vector2 v2)
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// Time measure returned are milliseconds
|
// Time measure returned are milliseconds
|
||||||
static double GetCurrentTime(void)
|
static double rgGetCurrentTime(void)
|
||||||
{
|
{
|
||||||
double time = 0;
|
double time = 0;
|
||||||
|
|
||||||
108
src/rlgl.h
108
src/rlgl.h
|
|
@ -279,7 +279,7 @@ typedef enum {
|
||||||
|
|
||||||
// Dynamic vertex buffers (position + texcoords + colors + indices arrays)
|
// Dynamic vertex buffers (position + texcoords + colors + indices arrays)
|
||||||
typedef struct rlVertexBuffer {
|
typedef struct rlVertexBuffer {
|
||||||
int elementsCount; // Number of elements in the buffer (QUADS)
|
int elementCount; // Number of elements in the buffer (QUADS)
|
||||||
|
|
||||||
int vCounter; // Vertex position counter to process (and draw) from full buffer
|
int vCounter; // Vertex position counter to process (and draw) from full buffer
|
||||||
int tcCounter; // Vertex texcoord counter to process (and draw) from full buffer
|
int tcCounter; // Vertex texcoord counter to process (and draw) from full buffer
|
||||||
|
|
@ -316,12 +316,12 @@ typedef struct rlDrawCall {
|
||||||
|
|
||||||
// rlRenderBatch type
|
// rlRenderBatch type
|
||||||
typedef struct rlRenderBatch {
|
typedef struct rlRenderBatch {
|
||||||
int buffersCount; // Number of vertex buffers (multi-buffering support)
|
int bufferCount; // Number of vertex buffers (multi-buffering support)
|
||||||
int currentBuffer; // Current buffer tracking in case of multi-buffering
|
int currentBuffer; // Current buffer tracking in case of multi-buffering
|
||||||
rlVertexBuffer *vertexBuffer; // Dynamic buffer(s) for vertex data
|
rlVertexBuffer *vertexBuffer; // Dynamic buffer(s) for vertex data
|
||||||
|
|
||||||
rlDrawCall *draws; // Draw calls array, depends on textureId
|
rlDrawCall *draws; // Draw calls array, depends on textureId
|
||||||
int drawsCounter; // Draw calls counter
|
int drawCounter; // Draw calls counter
|
||||||
float currentDepth; // Current depth value for next draw
|
float currentDepth; // Current depth value for next draw
|
||||||
} rlRenderBatch;
|
} rlRenderBatch;
|
||||||
|
|
||||||
|
|
@ -1210,34 +1210,34 @@ void rlBegin(int mode)
|
||||||
{
|
{
|
||||||
// Draw mode can be RL_LINES, RL_TRIANGLES and RL_QUADS
|
// Draw mode can be RL_LINES, RL_TRIANGLES and RL_QUADS
|
||||||
// NOTE: In all three cases, vertex are accumulated over default internal vertex buffer
|
// NOTE: In all three cases, vertex are accumulated over default internal vertex buffer
|
||||||
if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode != mode)
|
if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode != mode)
|
||||||
{
|
{
|
||||||
if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount > 0)
|
if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount > 0)
|
||||||
{
|
{
|
||||||
// Make sure current RLGL.currentBatch->draws[i].vertexCount is aligned a multiple of 4,
|
// Make sure current RLGL.currentBatch->draws[i].vertexCount is aligned a multiple of 4,
|
||||||
// that way, following QUADS drawing will keep aligned with index processing
|
// that way, following QUADS drawing will keep aligned with index processing
|
||||||
// It implies adding some extra alignment vertex at the end of the draw,
|
// It implies adding some extra alignment vertex at the end of the draw,
|
||||||
// those vertex are not processed but they are considered as an additional offset
|
// those vertex are not processed but they are considered as an additional offset
|
||||||
// for the next set of vertex to be drawn
|
// for the next set of vertex to be drawn
|
||||||
if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode == RL_LINES) RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount < 4)? RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount : RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount%4);
|
if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode == RL_LINES) RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount < 4)? RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount : RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount%4);
|
||||||
else if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode == RL_TRIANGLES) RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount < 4)? 1 : (4 - (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount%4)));
|
else if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode == RL_TRIANGLES) RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount < 4)? 1 : (4 - (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount%4)));
|
||||||
else RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment = 0;
|
else RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment = 0;
|
||||||
|
|
||||||
if (!rlCheckRenderBatchLimit(RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment))
|
if (!rlCheckRenderBatchLimit(RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment))
|
||||||
{
|
{
|
||||||
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment;
|
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment;
|
||||||
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment;
|
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment;
|
||||||
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment;
|
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment;
|
||||||
|
|
||||||
RLGL.currentBatch->drawsCounter++;
|
RLGL.currentBatch->drawCounter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RLGL.currentBatch->drawsCounter >= RL_DEFAULT_BATCH_DRAWCALLS) rlDrawRenderBatch(RLGL.currentBatch);
|
if (RLGL.currentBatch->drawCounter >= RL_DEFAULT_BATCH_DRAWCALLS) rlDrawRenderBatch(RLGL.currentBatch);
|
||||||
|
|
||||||
RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode = mode;
|
RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode = mode;
|
||||||
RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount = 0;
|
RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount = 0;
|
||||||
RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].textureId = RLGL.State.defaultTextureId;
|
RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].textureId = RLGL.State.defaultTextureId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1285,7 +1285,7 @@ void rlEnd(void)
|
||||||
// Verify internal buffers limits
|
// Verify internal buffers limits
|
||||||
// NOTE: This check is combined with usage of rlCheckRenderBatchLimit()
|
// NOTE: This check is combined with usage of rlCheckRenderBatchLimit()
|
||||||
if ((RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter) >=
|
if ((RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter) >=
|
||||||
(RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementsCount*4 - 4))
|
(RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementCount*4 - 4))
|
||||||
{
|
{
|
||||||
// WARNING: If we are between rlPushMatrix() and rlPopMatrix() and we need to force a rlDrawRenderBatch(),
|
// WARNING: If we are between rlPushMatrix() and rlPopMatrix() and we need to force a rlDrawRenderBatch(),
|
||||||
// we need to call rlPopMatrix() before to recover *RLGL.State.currentMatrix (RLGL.State.modelview) for the next forced draw call!
|
// we need to call rlPopMatrix() before to recover *RLGL.State.currentMatrix (RLGL.State.modelview) for the next forced draw call!
|
||||||
|
|
@ -1312,14 +1312,14 @@ void rlVertex3f(float x, float y, float z)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that current vertex buffer elements limit has not been reached
|
// Verify that current vertex buffer elements limit has not been reached
|
||||||
if (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter < (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementsCount*4))
|
if (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter < (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementCount*4))
|
||||||
{
|
{
|
||||||
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter] = tx;
|
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter] = tx;
|
||||||
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter + 1] = ty;
|
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter + 1] = ty;
|
||||||
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter + 2] = tz;
|
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter + 2] = tz;
|
||||||
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter++;
|
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter++;
|
||||||
|
|
||||||
RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount++;
|
RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount++;
|
||||||
}
|
}
|
||||||
else TRACELOG(RL_LOG_ERROR, "RLGL: Batch elements overflow");
|
else TRACELOG(RL_LOG_ERROR, "RLGL: Batch elements overflow");
|
||||||
}
|
}
|
||||||
|
|
@ -1390,7 +1390,7 @@ void rlSetTexture(unsigned int id)
|
||||||
#else
|
#else
|
||||||
// NOTE: If quads batch limit is reached, we force a draw call and next batch starts
|
// NOTE: If quads batch limit is reached, we force a draw call and next batch starts
|
||||||
if (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter >=
|
if (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter >=
|
||||||
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementsCount*4)
|
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementCount*4)
|
||||||
{
|
{
|
||||||
rlDrawRenderBatch(RLGL.currentBatch);
|
rlDrawRenderBatch(RLGL.currentBatch);
|
||||||
}
|
}
|
||||||
|
|
@ -1401,33 +1401,33 @@ void rlSetTexture(unsigned int id)
|
||||||
#if defined(GRAPHICS_API_OPENGL_11)
|
#if defined(GRAPHICS_API_OPENGL_11)
|
||||||
rlEnableTexture(id);
|
rlEnableTexture(id);
|
||||||
#else
|
#else
|
||||||
if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].textureId != id)
|
if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].textureId != id)
|
||||||
{
|
{
|
||||||
if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount > 0)
|
if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount > 0)
|
||||||
{
|
{
|
||||||
// Make sure current RLGL.currentBatch->draws[i].vertexCount is aligned a multiple of 4,
|
// Make sure current RLGL.currentBatch->draws[i].vertexCount is aligned a multiple of 4,
|
||||||
// that way, following QUADS drawing will keep aligned with index processing
|
// that way, following QUADS drawing will keep aligned with index processing
|
||||||
// It implies adding some extra alignment vertex at the end of the draw,
|
// It implies adding some extra alignment vertex at the end of the draw,
|
||||||
// those vertex are not processed but they are considered as an additional offset
|
// those vertex are not processed but they are considered as an additional offset
|
||||||
// for the next set of vertex to be drawn
|
// for the next set of vertex to be drawn
|
||||||
if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode == RL_LINES) RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount < 4)? RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount : RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount%4);
|
if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode == RL_LINES) RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount < 4)? RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount : RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount%4);
|
||||||
else if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode == RL_TRIANGLES) RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount < 4)? 1 : (4 - (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount%4)));
|
else if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode == RL_TRIANGLES) RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount < 4)? 1 : (4 - (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount%4)));
|
||||||
else RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment = 0;
|
else RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment = 0;
|
||||||
|
|
||||||
if (!rlCheckRenderBatchLimit(RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment))
|
if (!rlCheckRenderBatchLimit(RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment))
|
||||||
{
|
{
|
||||||
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment;
|
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment;
|
||||||
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment;
|
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment;
|
||||||
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment;
|
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment;
|
||||||
|
|
||||||
RLGL.currentBatch->drawsCounter++;
|
RLGL.currentBatch->drawCounter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RLGL.currentBatch->drawsCounter >= RL_DEFAULT_BATCH_DRAWCALLS) rlDrawRenderBatch(RLGL.currentBatch);
|
if (RLGL.currentBatch->drawCounter >= RL_DEFAULT_BATCH_DRAWCALLS) rlDrawRenderBatch(RLGL.currentBatch);
|
||||||
|
|
||||||
RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].textureId = id;
|
RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].textureId = id;
|
||||||
RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount = 0;
|
RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
@ -1910,12 +1910,12 @@ void rlLoadExtensions(void *loader)
|
||||||
const char *extensions = (const char *)glGetString(GL_EXTENSIONS); // One big const string
|
const char *extensions = (const char *)glGetString(GL_EXTENSIONS); // One big const string
|
||||||
|
|
||||||
// NOTE: We have to duplicate string because glGetString() returns a const string
|
// NOTE: We have to duplicate string because glGetString() returns a const string
|
||||||
int len = strlen(extensions) + 1;
|
int size = strlen(extensions) + 1; // Get extensions string size in bytes
|
||||||
char *extensionsDup = (char *)RL_CALLOC(len, sizeof(char));
|
char *extensionsDup = (char *)RL_CALLOC(size, sizeof(char));
|
||||||
strcpy(extensionsDup, extensions);
|
strcpy(extensionsDup, extensions);
|
||||||
extList[numExt] = extensionsDup;
|
extList[numExt] = extensionsDup;
|
||||||
|
|
||||||
for (int i = 0; i < len; i++)
|
for (int i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
if (extensionsDup[i] == ' ')
|
if (extensionsDup[i] == ' ')
|
||||||
{
|
{
|
||||||
|
|
@ -2169,7 +2169,7 @@ rlRenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements)
|
||||||
|
|
||||||
for (int i = 0; i < numBuffers; i++)
|
for (int i = 0; i < numBuffers; i++)
|
||||||
{
|
{
|
||||||
batch.vertexBuffer[i].elementsCount = bufferElements;
|
batch.vertexBuffer[i].elementCount = bufferElements;
|
||||||
|
|
||||||
batch.vertexBuffer[i].vertices = (float *)RL_MALLOC(bufferElements*3*4*sizeof(float)); // 3 float by vertex, 4 vertex by quad
|
batch.vertexBuffer[i].vertices = (float *)RL_MALLOC(bufferElements*3*4*sizeof(float)); // 3 float by vertex, 4 vertex by quad
|
||||||
batch.vertexBuffer[i].texcoords = (float *)RL_MALLOC(bufferElements*2*4*sizeof(float)); // 2 float by texcoord, 4 texcoord by quad
|
batch.vertexBuffer[i].texcoords = (float *)RL_MALLOC(bufferElements*2*4*sizeof(float)); // 2 float by texcoord, 4 texcoord by quad
|
||||||
|
|
@ -2274,8 +2274,8 @@ rlRenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements)
|
||||||
//batch.draws[i].RLGL.State.modelview = rlMatrixIdentity();
|
//batch.draws[i].RLGL.State.modelview = rlMatrixIdentity();
|
||||||
}
|
}
|
||||||
|
|
||||||
batch.buffersCount = numBuffers; // Record buffer count
|
batch.bufferCount = numBuffers; // Record buffer count
|
||||||
batch.drawsCounter = 1; // Reset draws counter
|
batch.drawCounter = 1; // Reset draws counter
|
||||||
batch.currentDepth = -1.0f; // Reset depth value
|
batch.currentDepth = -1.0f; // Reset depth value
|
||||||
//--------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -2297,7 +2297,7 @@ void rlUnloadRenderBatch(rlRenderBatch batch)
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
// Unload all vertex buffers data
|
// Unload all vertex buffers data
|
||||||
for (int i = 0; i < batch.buffersCount; i++)
|
for (int i = 0; i < batch.bufferCount; i++)
|
||||||
{
|
{
|
||||||
// Delete VBOs from GPU (VRAM)
|
// Delete VBOs from GPU (VRAM)
|
||||||
glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[0]);
|
glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[0]);
|
||||||
|
|
@ -2338,17 +2338,17 @@ void rlDrawRenderBatch(rlRenderBatch *batch)
|
||||||
// Vertex positions buffer
|
// Vertex positions buffer
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[0]);
|
glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[0]);
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, batch->vertexBuffer[batch->currentBuffer].vCounter*3*sizeof(float), batch->vertexBuffer[batch->currentBuffer].vertices);
|
glBufferSubData(GL_ARRAY_BUFFER, 0, batch->vertexBuffer[batch->currentBuffer].vCounter*3*sizeof(float), batch->vertexBuffer[batch->currentBuffer].vertices);
|
||||||
//glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*batch->vertexBuffer[batch->currentBuffer].elementsCount, batch->vertexBuffer[batch->currentBuffer].vertices, GL_DYNAMIC_DRAW); // Update all buffer
|
//glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*batch->vertexBuffer[batch->currentBuffer].elementCount, batch->vertexBuffer[batch->currentBuffer].vertices, GL_DYNAMIC_DRAW); // Update all buffer
|
||||||
|
|
||||||
// Texture coordinates buffer
|
// Texture coordinates buffer
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[1]);
|
glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[1]);
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, batch->vertexBuffer[batch->currentBuffer].vCounter*2*sizeof(float), batch->vertexBuffer[batch->currentBuffer].texcoords);
|
glBufferSubData(GL_ARRAY_BUFFER, 0, batch->vertexBuffer[batch->currentBuffer].vCounter*2*sizeof(float), batch->vertexBuffer[batch->currentBuffer].texcoords);
|
||||||
//glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*batch->vertexBuffer[batch->currentBuffer].elementsCount, batch->vertexBuffer[batch->currentBuffer].texcoords, GL_DYNAMIC_DRAW); // Update all buffer
|
//glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*batch->vertexBuffer[batch->currentBuffer].elementCount, batch->vertexBuffer[batch->currentBuffer].texcoords, GL_DYNAMIC_DRAW); // Update all buffer
|
||||||
|
|
||||||
// Colors buffer
|
// Colors buffer
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[2]);
|
glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[2]);
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, batch->vertexBuffer[batch->currentBuffer].vCounter*4*sizeof(unsigned char), batch->vertexBuffer[batch->currentBuffer].colors);
|
glBufferSubData(GL_ARRAY_BUFFER, 0, batch->vertexBuffer[batch->currentBuffer].vCounter*4*sizeof(unsigned char), batch->vertexBuffer[batch->currentBuffer].colors);
|
||||||
//glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*batch->vertexBuffer[batch->currentBuffer].elementsCount, batch->vertexBuffer[batch->currentBuffer].colors, GL_DYNAMIC_DRAW); // Update all buffer
|
//glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*batch->vertexBuffer[batch->currentBuffer].elementCount, batch->vertexBuffer[batch->currentBuffer].colors, GL_DYNAMIC_DRAW); // Update all buffer
|
||||||
|
|
||||||
// NOTE: glMapBuffer() causes sync issue.
|
// NOTE: glMapBuffer() causes sync issue.
|
||||||
// If GPU is working with this buffer, glMapBuffer() will wait(stall) until GPU to finish its job.
|
// If GPU is working with this buffer, glMapBuffer() will wait(stall) until GPU to finish its job.
|
||||||
|
|
@ -2375,12 +2375,12 @@ void rlDrawRenderBatch(rlRenderBatch *batch)
|
||||||
Matrix matProjection = RLGL.State.projection;
|
Matrix matProjection = RLGL.State.projection;
|
||||||
Matrix matModelView = RLGL.State.modelview;
|
Matrix matModelView = RLGL.State.modelview;
|
||||||
|
|
||||||
int eyesCount = 1;
|
int eyeCount = 1;
|
||||||
if (RLGL.State.stereoRender) eyesCount = 2;
|
if (RLGL.State.stereoRender) eyeCount = 2;
|
||||||
|
|
||||||
for (int eye = 0; eye < eyesCount; eye++)
|
for (int eye = 0; eye < eyeCount; eye++)
|
||||||
{
|
{
|
||||||
if (eyesCount == 2)
|
if (eyeCount == 2)
|
||||||
{
|
{
|
||||||
// Setup current eye viewport (half screen width)
|
// Setup current eye viewport (half screen width)
|
||||||
rlViewport(eye*RLGL.State.framebufferWidth/2, 0, RLGL.State.framebufferWidth/2, RLGL.State.framebufferHeight);
|
rlViewport(eye*RLGL.State.framebufferWidth/2, 0, RLGL.State.framebufferWidth/2, RLGL.State.framebufferHeight);
|
||||||
|
|
@ -2447,7 +2447,7 @@ void rlDrawRenderBatch(rlRenderBatch *batch)
|
||||||
// NOTE: Batch system accumulates calls by texture0 changes, additional textures are enabled for all the draw calls
|
// NOTE: Batch system accumulates calls by texture0 changes, additional textures are enabled for all the draw calls
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
||||||
for (int i = 0, vertexOffset = 0; i < batch->drawsCounter; i++)
|
for (int i = 0, vertexOffset = 0; i < batch->drawCounter; i++)
|
||||||
{
|
{
|
||||||
// Bind current draw call texture, activated as GL_TEXTURE0 and binded to sampler2D texture0 by default
|
// Bind current draw call texture, activated as GL_TEXTURE0 and binded to sampler2D texture0 by default
|
||||||
glBindTexture(GL_TEXTURE_2D, batch->draws[i].textureId);
|
glBindTexture(GL_TEXTURE_2D, batch->draws[i].textureId);
|
||||||
|
|
@ -2456,7 +2456,7 @@ void rlDrawRenderBatch(rlRenderBatch *batch)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if defined(GRAPHICS_API_OPENGL_33)
|
#if defined(GRAPHICS_API_OPENGL_33)
|
||||||
// We need to define the number of indices to be processed: quadsCount*6
|
// We need to define the number of indices to be processed: elementCount*6
|
||||||
// NOTE: The final parameter tells the GPU the offset in bytes from the
|
// NOTE: The final parameter tells the GPU the offset in bytes from the
|
||||||
// start of the index buffer to the location of the first index to process
|
// start of the index buffer to the location of the first index to process
|
||||||
glDrawElements(GL_TRIANGLES, batch->draws[i].vertexCount/4*6, GL_UNSIGNED_INT, (GLvoid *)(vertexOffset/4*6*sizeof(GLuint)));
|
glDrawElements(GL_TRIANGLES, batch->draws[i].vertexCount/4*6, GL_UNSIGNED_INT, (GLvoid *)(vertexOffset/4*6*sizeof(GLuint)));
|
||||||
|
|
@ -2510,12 +2510,12 @@ void rlDrawRenderBatch(rlRenderBatch *batch)
|
||||||
for (int i = 0; i < RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS; i++) RLGL.State.activeTextureId[i] = 0;
|
for (int i = 0; i < RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS; i++) RLGL.State.activeTextureId[i] = 0;
|
||||||
|
|
||||||
// Reset draws counter to one draw for the batch
|
// Reset draws counter to one draw for the batch
|
||||||
batch->drawsCounter = 1;
|
batch->drawCounter = 1;
|
||||||
//------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Change to next buffer in the list (in case of multi-buffering)
|
// Change to next buffer in the list (in case of multi-buffering)
|
||||||
batch->currentBuffer++;
|
batch->currentBuffer++;
|
||||||
if (batch->currentBuffer >= batch->buffersCount) batch->currentBuffer = 0;
|
if (batch->currentBuffer >= batch->bufferCount) batch->currentBuffer = 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2546,7 +2546,7 @@ bool rlCheckRenderBatchLimit(int vCount)
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
if ((RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter + vCount) >=
|
if ((RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter + vCount) >=
|
||||||
(RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementsCount*4))
|
(RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementCount*4))
|
||||||
{
|
{
|
||||||
overflow = true;
|
overflow = true;
|
||||||
rlDrawRenderBatch(RLGL.currentBatch); // NOTE: Stereo rendering is checked inside
|
rlDrawRenderBatch(RLGL.currentBatch); // NOTE: Stereo rendering is checked inside
|
||||||
|
|
@ -3028,8 +3028,6 @@ void *rlReadTexturePixels(unsigned int id, int width, int height, int format)
|
||||||
// NOTE: This behaviour could be conditioned by graphic driver...
|
// NOTE: This behaviour could be conditioned by graphic driver...
|
||||||
unsigned int fboId = rlLoadFramebuffer(width, height);
|
unsigned int fboId = rlLoadFramebuffer(width, height);
|
||||||
|
|
||||||
// TODO: Create depth texture/renderbuffer for fbo?
|
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, fboId);
|
glBindFramebuffer(GL_FRAMEBUFFER, fboId);
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/**********************************************************************************************
|
/**********************************************************************************************
|
||||||
*
|
*
|
||||||
* raylib.models - Basic functions to deal with 3d shapes and 3d models
|
* rmodels - Basic functions to draw 3d shapes and load and draw 3d models
|
||||||
*
|
*
|
||||||
* CONFIGURATION:
|
* CONFIGURATION:
|
||||||
*
|
*
|
||||||
|
|
@ -8,6 +8,8 @@
|
||||||
* #define SUPPORT_FILEFORMAT_MTL
|
* #define SUPPORT_FILEFORMAT_MTL
|
||||||
* #define SUPPORT_FILEFORMAT_IQM
|
* #define SUPPORT_FILEFORMAT_IQM
|
||||||
* #define SUPPORT_FILEFORMAT_GLTF
|
* #define SUPPORT_FILEFORMAT_GLTF
|
||||||
|
* #define SUPPORT_FILEFORMAT_VOX
|
||||||
|
*
|
||||||
* Selected desired fileformats to be supported for model data loading.
|
* Selected desired fileformats to be supported for model data loading.
|
||||||
*
|
*
|
||||||
* #define SUPPORT_MESH_GENERATION
|
* #define SUPPORT_MESH_GENERATION
|
||||||
|
|
@ -68,7 +70,16 @@
|
||||||
|
|
||||||
#define CGLTF_IMPLEMENTATION
|
#define CGLTF_IMPLEMENTATION
|
||||||
#include "external/cgltf.h" // glTF file format loading
|
#include "external/cgltf.h" // glTF file format loading
|
||||||
#include "external/stb_image.h" // glTF texture images loading
|
#endif
|
||||||
|
|
||||||
|
#if defined(SUPPORT_FILEFORMAT_VOX)
|
||||||
|
#define VOX_MALLOC RL_MALLOC
|
||||||
|
#define VOX_CALLOC RL_CALLOC
|
||||||
|
#define VOX_REALLOC RL_REALLOC
|
||||||
|
#define VOX_FREE RL_FREE
|
||||||
|
|
||||||
|
#define VOX_LOADER_IMPLEMENTATION
|
||||||
|
#include "external/vox_loader.h" // vox file format loading (MagikaVoxel)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(SUPPORT_MESH_GENERATION)
|
#if defined(SUPPORT_MESH_GENERATION)
|
||||||
|
|
@ -117,19 +128,23 @@ static Model LoadOBJ(const char *fileName); // Load OBJ mesh data
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_IQM)
|
#if defined(SUPPORT_FILEFORMAT_IQM)
|
||||||
static Model LoadIQM(const char *fileName); // Load IQM mesh data
|
static Model LoadIQM(const char *fileName); // Load IQM mesh data
|
||||||
static ModelAnimation *LoadIQMModelAnimations(const char *fileName, int *animCount); // Load IQM animation data
|
static ModelAnimation *LoadIQMModelAnimations(const char *fileName, unsigned int *animCount); // Load IQM animation data
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_GLTF)
|
#if defined(SUPPORT_FILEFORMAT_GLTF)
|
||||||
static Model LoadGLTF(const char *fileName); // Load GLTF mesh data
|
static Model LoadGLTF(const char *fileName); // Load GLTF mesh data
|
||||||
static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCount); // Load GLTF animation data
|
static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, unsigned int *animCount); // Load GLTF animation data
|
||||||
static void LoadGLTFMaterial(Model *model, const char *fileName, const cgltf_data *data);
|
static void LoadGLTFMaterial(Model *model, const char *fileName, const cgltf_data *data);
|
||||||
static void LoadGLTFMesh(cgltf_data *data, cgltf_mesh* mesh, Model* outModel, Matrix currentTransform, int* primitiveIndex, const char *fileName);
|
static void LoadGLTFMesh(cgltf_data *data, cgltf_node *node, Model *outModel, Matrix currentTransform, int *primitiveIndex, const char *fileName);
|
||||||
static void LoadGLTFNode(cgltf_data *data, cgltf_node* node, Model* outModel, Matrix currentTransform, int* primitiveIndex, const char *fileName);
|
static void LoadGLTFNode(cgltf_data *data, cgltf_node *node, Model *outModel, Matrix currentTransform, int *primitiveIndex, const char *fileName);
|
||||||
static void InitGLTFBones(Model *model, const cgltf_data *data);
|
static void InitGLTFBones(Model *model, const cgltf_data *data);
|
||||||
static void BindGLTFPrimitiveToBones(Model *model, const cgltf_data *data, int primitiveIndex);
|
static void BindGLTFPrimitiveToBones(Model *model, cgltf_node *node, const cgltf_data *data, int primitiveIndex);
|
||||||
static void GetGLTFPrimitiveCount(cgltf_node* node, int* outCount);
|
static void GetGLTFPrimitiveCount(cgltf_node *node, int *outCount);
|
||||||
static bool ReadGLTFValue(cgltf_accessor* acc, unsigned int index, void *variable);
|
static bool ReadGLTFValue(cgltf_accessor *acc, unsigned int index, void *variable);
|
||||||
static void *ReadGLTFValuesAs(cgltf_accessor* acc, cgltf_component_type type, bool adjustOnDownCasting);
|
static void *ReadGLTFValuesAs(cgltf_accessor *acc, cgltf_component_type type, bool adjustOnDownCasting);
|
||||||
|
static Matrix GetNodeTransformationMatrix(cgltf_node *node, Matrix current);
|
||||||
|
#endif
|
||||||
|
#if defined(SUPPORT_FILEFORMAT_VOX)
|
||||||
|
static Model LoadVOX(const char *filename); // Load VOX mesh data
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
@ -201,16 +216,16 @@ void DrawTriangle3D(Vector3 v1, Vector3 v2, Vector3 v3, Color color)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a triangle strip defined by points
|
// Draw a triangle strip defined by points
|
||||||
void DrawTriangleStrip3D(Vector3 *points, int pointsCount, Color color)
|
void DrawTriangleStrip3D(Vector3 *points, int pointCount, Color color)
|
||||||
{
|
{
|
||||||
if (pointsCount >= 3)
|
if (pointCount >= 3)
|
||||||
{
|
{
|
||||||
rlCheckRenderBatchLimit(3*(pointsCount - 2));
|
rlCheckRenderBatchLimit(3*(pointCount - 2));
|
||||||
|
|
||||||
rlBegin(RL_TRIANGLES);
|
rlBegin(RL_TRIANGLES);
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
for (int i = 2; i < pointsCount; i++)
|
for (int i = 2; i < pointCount; i++)
|
||||||
{
|
{
|
||||||
if ((i%2) == 0)
|
if ((i%2) == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -449,6 +464,157 @@ void DrawCubeTexture(Texture2D texture, Vector3 position, float width, float hei
|
||||||
rlSetTexture(0);
|
rlSetTexture(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DrawCubeTextureRec(Texture2D texture, Rectangle source, Vector3 position, float width, float height, float length, Color color)
|
||||||
|
{
|
||||||
|
float x = position.x;
|
||||||
|
float y = position.y;
|
||||||
|
float z = position.z;
|
||||||
|
float texture_width = (float)texture.width;
|
||||||
|
float texture_height = (float)texture.height;
|
||||||
|
|
||||||
|
rlCheckRenderBatchLimit(36);
|
||||||
|
|
||||||
|
rlSetTexture(texture.id);
|
||||||
|
|
||||||
|
rlBegin(RL_QUADS);
|
||||||
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
|
// Front Face
|
||||||
|
{
|
||||||
|
// Normal Pointing Towards Viewer
|
||||||
|
rlNormal3f(0.0f, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
// Bottom Left Of The Texture and Quad
|
||||||
|
rlTexCoord2f(source.x / texture_width, (source.y + source.height) / texture_height);
|
||||||
|
rlVertex3f(x - width/2, y - height/2, z + length/2);
|
||||||
|
|
||||||
|
// Bottom Right Of The Texture and Quad
|
||||||
|
rlTexCoord2f((source.x + source.width) / texture_width, (source.y + source.height) / texture_height);
|
||||||
|
rlVertex3f(x + width/2, y - height/2, z + length/2);
|
||||||
|
|
||||||
|
// Top Right Of The Texture and Quad
|
||||||
|
rlTexCoord2f((source.x + source.width) / texture_width, source.y / texture_height);
|
||||||
|
rlVertex3f(x + width/2, y + height/2, z + length/2);
|
||||||
|
|
||||||
|
// Top Left Of The Texture and Quad
|
||||||
|
rlTexCoord2f(source.x / texture_width, source.y / texture_height);
|
||||||
|
rlVertex3f(x - width/2, y + height/2, z + length/2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Back Face
|
||||||
|
{
|
||||||
|
// Normal Pointing Away From Viewer
|
||||||
|
rlNormal3f(0.0f, 0.0f, - 1.0f);
|
||||||
|
|
||||||
|
// Bottom Right Of The Texture and Quad
|
||||||
|
rlTexCoord2f((source.x + source.width) / texture_width, (source.y + source.height) / texture_height);
|
||||||
|
rlVertex3f(x - width/2, y - height/2, z - length/2);
|
||||||
|
|
||||||
|
// Top Right Of The Texture and Quad
|
||||||
|
rlTexCoord2f((source.x + source.width) / texture_width, source.y / texture_height);
|
||||||
|
rlVertex3f(x - width/2, y + height/2, z - length/2);
|
||||||
|
|
||||||
|
// Top Left Of The Texture and Quad
|
||||||
|
rlTexCoord2f(source.x / texture_width, source.y / texture_height);
|
||||||
|
rlVertex3f(x + width/2, y + height/2, z - length/2);
|
||||||
|
|
||||||
|
// Bottom Left Of The Texture and Quad
|
||||||
|
rlTexCoord2f(source.x / texture_width, (source.y + source.height) / texture_height);
|
||||||
|
rlVertex3f(x + width/2, y - height/2, z - length/2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Top Face
|
||||||
|
{
|
||||||
|
// Normal Pointing Up
|
||||||
|
rlNormal3f(0.0f, 1.0f, 0.0f);
|
||||||
|
|
||||||
|
// Top Left Of The Texture and Quad
|
||||||
|
rlTexCoord2f(source.x / texture_width, source.y / texture_height);
|
||||||
|
rlVertex3f(x - width/2, y + height/2, z - length/2);
|
||||||
|
|
||||||
|
// Bottom Left Of The Texture and Quad
|
||||||
|
rlTexCoord2f(source.x / texture_width, (source.y + source.height) / texture_height);
|
||||||
|
rlVertex3f(x - width/2, y + height/2, z + length/2);
|
||||||
|
|
||||||
|
// Bottom Right Of The Texture and Quad
|
||||||
|
rlTexCoord2f((source.x + source.width) / texture_width, (source.y + source.height) / texture_height);
|
||||||
|
rlVertex3f(x + width/2, y + height/2, z + length/2);
|
||||||
|
|
||||||
|
// Top Right Of The Texture and Quad
|
||||||
|
rlTexCoord2f((source.x + source.width) / texture_width, source.y / texture_height);
|
||||||
|
rlVertex3f(x + width/2, y + height/2, z - length/2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bottom Face
|
||||||
|
{
|
||||||
|
// Normal Pointing Down
|
||||||
|
rlNormal3f(0.0f, - 1.0f, 0.0f);
|
||||||
|
|
||||||
|
// Top Right Of The Texture and Quad
|
||||||
|
rlTexCoord2f((source.x + source.width) / texture_width, source.y / texture_height);
|
||||||
|
rlVertex3f(x - width/2, y - height/2, z - length/2);
|
||||||
|
|
||||||
|
// Top Left Of The Texture and Quad
|
||||||
|
rlTexCoord2f(source.x / texture_width, source.y / texture_height);
|
||||||
|
rlVertex3f(x + width/2, y - height/2, z - length/2);
|
||||||
|
|
||||||
|
// Bottom Left Of The Texture and Quad
|
||||||
|
rlTexCoord2f(source.x / texture_width, (source.y + source.height) / texture_height);
|
||||||
|
rlVertex3f(x + width/2, y - height/2, z + length/2);
|
||||||
|
|
||||||
|
// Bottom Right Of The Texture and Quad
|
||||||
|
rlTexCoord2f((source.x + source.width) / texture_width, (source.y + source.height) / texture_height);
|
||||||
|
rlVertex3f(x - width/2, y - height/2, z + length/2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Right face
|
||||||
|
{
|
||||||
|
// Normal Pointing Right
|
||||||
|
rlNormal3f(1.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
// Bottom Right Of The Texture and Quad
|
||||||
|
rlTexCoord2f((source.x + source.width) / texture_width, (source.y + source.height) / texture_height);
|
||||||
|
rlVertex3f(x + width/2, y - height/2, z - length/2);
|
||||||
|
|
||||||
|
// Top Right Of The Texture and Quad
|
||||||
|
rlTexCoord2f((source.x + source.width) / texture_width, source.y / texture_height);
|
||||||
|
rlVertex3f(x + width/2, y + height/2, z - length/2);
|
||||||
|
|
||||||
|
// Top Left Of The Texture and Quad
|
||||||
|
rlTexCoord2f(source.x / texture_width, source.y / texture_height);
|
||||||
|
rlVertex3f(x + width/2, y + height/2, z + length/2);
|
||||||
|
|
||||||
|
// Bottom Left Of The Texture and Quad
|
||||||
|
rlTexCoord2f(source.x / texture_width, (source.y + source.height) / texture_height);
|
||||||
|
rlVertex3f(x + width/2, y - height/2, z + length/2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Left Face
|
||||||
|
{
|
||||||
|
// Normal Pointing Left
|
||||||
|
rlNormal3f( - 1.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
// Bottom Left Of The Texture and Quad
|
||||||
|
rlTexCoord2f(source.x / texture_width, (source.y + source.height) / texture_height);
|
||||||
|
rlVertex3f(x - width/2, y - height/2, z - length/2);
|
||||||
|
|
||||||
|
// Bottom Right Of The Texture and Quad
|
||||||
|
rlTexCoord2f((source.x + source.width) / texture_width, (source.y + source.height) / texture_height);
|
||||||
|
rlVertex3f(x - width/2, y - height/2, z + length/2);
|
||||||
|
|
||||||
|
// Top Right Of The Texture and Quad
|
||||||
|
rlTexCoord2f((source.x + source.width) / texture_width, source.y / texture_height);
|
||||||
|
rlVertex3f(x - width/2, y + height/2, z + length/2);
|
||||||
|
|
||||||
|
// Top Left Of The Texture and Quad
|
||||||
|
rlTexCoord2f(source.x / texture_width, source.y / texture_height);
|
||||||
|
rlVertex3f(x - width/2, y + height/2, z - length/2);
|
||||||
|
}
|
||||||
|
rlEnd();
|
||||||
|
|
||||||
|
rlSetTexture(0);
|
||||||
|
}
|
||||||
|
|
||||||
// Draw sphere
|
// Draw sphere
|
||||||
void DrawSphere(Vector3 centerPos, float radius, Color color)
|
void DrawSphere(Vector3 centerPos, float radius, Color color)
|
||||||
{
|
{
|
||||||
|
|
@ -718,6 +884,9 @@ Model LoadModel(const char *fileName)
|
||||||
#if defined(SUPPORT_FILEFORMAT_GLTF)
|
#if defined(SUPPORT_FILEFORMAT_GLTF)
|
||||||
if (IsFileExtension(fileName, ".gltf;.glb")) model = LoadGLTF(fileName);
|
if (IsFileExtension(fileName, ".gltf;.glb")) model = LoadGLTF(fileName);
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(SUPPORT_FILEFORMAT_VOX)
|
||||||
|
if (IsFileExtension(fileName, ".vox")) model = LoadVOX(fileName);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Make sure model transform is set to identity matrix!
|
// Make sure model transform is set to identity matrix!
|
||||||
model.transform = MatrixIdentity();
|
model.transform = MatrixIdentity();
|
||||||
|
|
@ -1144,14 +1313,14 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform)
|
||||||
if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[6]);
|
if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[6]);
|
||||||
}
|
}
|
||||||
|
|
||||||
int eyesCount = 1;
|
int eyeCount = 1;
|
||||||
if (rlIsStereoRenderEnabled()) eyesCount = 2;
|
if (rlIsStereoRenderEnabled()) eyeCount = 2;
|
||||||
|
|
||||||
for (int eye = 0; eye < eyesCount; eye++)
|
for (int eye = 0; eye < eyeCount; eye++)
|
||||||
{
|
{
|
||||||
// Calculate model-view-projection matrix (MVP)
|
// Calculate model-view-projection matrix (MVP)
|
||||||
Matrix matModelViewProjection = MatrixIdentity();
|
Matrix matModelViewProjection = MatrixIdentity();
|
||||||
if (eyesCount == 1) matModelViewProjection = MatrixMultiply(matModelView, matProjection);
|
if (eyeCount == 1) matModelViewProjection = MatrixMultiply(matModelView, matProjection);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Setup current eye viewport (half screen width)
|
// Setup current eye viewport (half screen width)
|
||||||
|
|
@ -1359,14 +1528,14 @@ void DrawMeshInstanced(Mesh mesh, Material material, Matrix *transforms, int ins
|
||||||
if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[6]);
|
if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[6]);
|
||||||
}
|
}
|
||||||
|
|
||||||
int eyesCount = 1;
|
int eyeCount = 1;
|
||||||
if (rlIsStereoRenderEnabled()) eyesCount = 2;
|
if (rlIsStereoRenderEnabled()) eyeCount = 2;
|
||||||
|
|
||||||
for (int eye = 0; eye < eyesCount; eye++)
|
for (int eye = 0; eye < eyeCount; eye++)
|
||||||
{
|
{
|
||||||
// Calculate model-view-projection matrix (MVP)
|
// Calculate model-view-projection matrix (MVP)
|
||||||
Matrix matModelViewProjection = MatrixIdentity();
|
Matrix matModelViewProjection = MatrixIdentity();
|
||||||
if (eyesCount == 1) matModelViewProjection = MatrixMultiply(matModelView, matProjection);
|
if (eyeCount == 1) matModelViewProjection = MatrixMultiply(matModelView, matProjection);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Setup current eye viewport (half screen width)
|
// Setup current eye viewport (half screen width)
|
||||||
|
|
@ -1448,43 +1617,43 @@ bool ExportMesh(Mesh mesh, const char *fileName)
|
||||||
// NOTE: Text data buffer size is estimated considering mesh data size
|
// NOTE: Text data buffer size is estimated considering mesh data size
|
||||||
char *txtData = (char *)RL_CALLOC(dataSize + 2000, sizeof(char));
|
char *txtData = (char *)RL_CALLOC(dataSize + 2000, sizeof(char));
|
||||||
|
|
||||||
int bytesCount = 0;
|
int byteCount = 0;
|
||||||
bytesCount += sprintf(txtData + bytesCount, "# //////////////////////////////////////////////////////////////////////////////////\n");
|
byteCount += sprintf(txtData + byteCount, "# //////////////////////////////////////////////////////////////////////////////////\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "# // //\n");
|
byteCount += sprintf(txtData + byteCount, "# // //\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "# // rMeshOBJ exporter v1.0 - Mesh exported as triangle faces and not optimized //\n");
|
byteCount += sprintf(txtData + byteCount, "# // rMeshOBJ exporter v1.0 - Mesh exported as triangle faces and not optimized //\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "# // //\n");
|
byteCount += sprintf(txtData + byteCount, "# // //\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "# // more info and bugs-report: github.com/raysan5/raylib //\n");
|
byteCount += sprintf(txtData + byteCount, "# // more info and bugs-report: github.com/raysan5/raylib //\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "# // feedback and support: ray[at]raylib.com //\n");
|
byteCount += sprintf(txtData + byteCount, "# // feedback and support: ray[at]raylib.com //\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "# // //\n");
|
byteCount += sprintf(txtData + byteCount, "# // //\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "# // Copyright (c) 2018 Ramon Santamaria (@raysan5) //\n");
|
byteCount += sprintf(txtData + byteCount, "# // Copyright (c) 2018 Ramon Santamaria (@raysan5) //\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "# // //\n");
|
byteCount += sprintf(txtData + byteCount, "# // //\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "# //////////////////////////////////////////////////////////////////////////////////\n\n");
|
byteCount += sprintf(txtData + byteCount, "# //////////////////////////////////////////////////////////////////////////////////\n\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "# Vertex Count: %i\n", mesh.vertexCount);
|
byteCount += sprintf(txtData + byteCount, "# Vertex Count: %i\n", mesh.vertexCount);
|
||||||
bytesCount += sprintf(txtData + bytesCount, "# Triangle Count: %i\n\n", mesh.triangleCount);
|
byteCount += sprintf(txtData + byteCount, "# Triangle Count: %i\n\n", mesh.triangleCount);
|
||||||
|
|
||||||
bytesCount += sprintf(txtData + bytesCount, "g mesh\n");
|
byteCount += sprintf(txtData + byteCount, "g mesh\n");
|
||||||
|
|
||||||
for (int i = 0, v = 0; i < mesh.vertexCount; i++, v += 3)
|
for (int i = 0, v = 0; i < mesh.vertexCount; i++, v += 3)
|
||||||
{
|
{
|
||||||
bytesCount += sprintf(txtData + bytesCount, "v %.2f %.2f %.2f\n", mesh.vertices[v], mesh.vertices[v + 1], mesh.vertices[v + 2]);
|
byteCount += sprintf(txtData + byteCount, "v %.2f %.2f %.2f\n", mesh.vertices[v], mesh.vertices[v + 1], mesh.vertices[v + 2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0, v = 0; i < mesh.vertexCount; i++, v += 2)
|
for (int i = 0, v = 0; i < mesh.vertexCount; i++, v += 2)
|
||||||
{
|
{
|
||||||
bytesCount += sprintf(txtData + bytesCount, "vt %.3f %.3f\n", mesh.texcoords[v], mesh.texcoords[v + 1]);
|
byteCount += sprintf(txtData + byteCount, "vt %.3f %.3f\n", mesh.texcoords[v], mesh.texcoords[v + 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0, v = 0; i < mesh.vertexCount; i++, v += 3)
|
for (int i = 0, v = 0; i < mesh.vertexCount; i++, v += 3)
|
||||||
{
|
{
|
||||||
bytesCount += sprintf(txtData + bytesCount, "vn %.3f %.3f %.3f\n", mesh.normals[v], mesh.normals[v + 1], mesh.normals[v + 2]);
|
byteCount += sprintf(txtData + byteCount, "vn %.3f %.3f %.3f\n", mesh.normals[v], mesh.normals[v + 1], mesh.normals[v + 2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < mesh.triangleCount; i += 3)
|
for (int i = 0; i < mesh.triangleCount; i += 3)
|
||||||
{
|
{
|
||||||
bytesCount += sprintf(txtData + bytesCount, "f %i/%i/%i %i/%i/%i %i/%i/%i\n", i, i, i, i + 1, i + 1, i + 1, i + 2, i + 2, i + 2);
|
byteCount += sprintf(txtData + byteCount, "f %i/%i/%i %i/%i/%i %i/%i/%i\n", i, i, i, i + 1, i + 1, i + 1, i + 2, i + 2, i + 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
bytesCount += sprintf(txtData + bytesCount, "\n");
|
byteCount += sprintf(txtData + byteCount, "\n");
|
||||||
|
|
||||||
// NOTE: Text data length exported is determined by '\0' (NULL) character
|
// NOTE: Text data length exported is determined by '\0' (NULL) character
|
||||||
success = SaveFileText(fileName, txtData);
|
success = SaveFileText(fileName, txtData);
|
||||||
|
|
@ -1590,7 +1759,7 @@ void SetModelMeshMaterial(Model *model, int meshId, int materialId)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load model animations from file
|
// Load model animations from file
|
||||||
ModelAnimation *LoadModelAnimations(const char *fileName, int *animCount)
|
ModelAnimation *LoadModelAnimations(const char *fileName, unsigned int *animCount)
|
||||||
{
|
{
|
||||||
ModelAnimation *animations = NULL;
|
ModelAnimation *animations = NULL;
|
||||||
|
|
||||||
|
|
@ -1614,72 +1783,93 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, int frame)
|
||||||
|
|
||||||
for (int m = 0; m < model.meshCount; m++)
|
for (int m = 0; m < model.meshCount; m++)
|
||||||
{
|
{
|
||||||
|
Mesh mesh = model.meshes[m];
|
||||||
|
if (mesh.boneIds == NULL || mesh.boneWeights == NULL)
|
||||||
|
{
|
||||||
|
TRACELOG(LOG_WARNING, "MODEL: UpdateModelAnimation Mesh %i has no connection to bones",m);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool updated = false; // set to true when anim vertex information is updated
|
||||||
Vector3 animVertex = { 0 };
|
Vector3 animVertex = { 0 };
|
||||||
Vector3 animNormal = { 0 };
|
Vector3 animNormal = { 0 };
|
||||||
|
|
||||||
Vector3 inTranslation = { 0 };
|
Vector3 inTranslation = { 0 };
|
||||||
Quaternion inRotation = { 0 };
|
Quaternion inRotation = { 0 };
|
||||||
//Vector3 inScale = { 0 }; // Not used...
|
// Vector3 inScale = { 0 };
|
||||||
|
|
||||||
Vector3 outTranslation = { 0 };
|
Vector3 outTranslation = { 0 };
|
||||||
Quaternion outRotation = { 0 };
|
Quaternion outRotation = { 0 };
|
||||||
Vector3 outScale = { 0 };
|
Vector3 outScale = { 0 };
|
||||||
|
|
||||||
int vCounter = 0;
|
|
||||||
int boneCounter = 0;
|
|
||||||
int boneId = 0;
|
int boneId = 0;
|
||||||
|
int boneCounter = 0;
|
||||||
float boneWeight = 0.0;
|
float boneWeight = 0.0;
|
||||||
|
|
||||||
for (int i = 0; i < model.meshes[m].vertexCount; i++)
|
const int vValues = mesh.vertexCount*3;
|
||||||
|
for (int vCounter = 0; vCounter < vValues; vCounter+=3)
|
||||||
{
|
{
|
||||||
model.meshes[m].animVertices[vCounter] = 0;
|
mesh.animVertices[vCounter] = 0;
|
||||||
model.meshes[m].animVertices[vCounter + 1] = 0;
|
mesh.animVertices[vCounter + 1] = 0;
|
||||||
model.meshes[m].animVertices[vCounter + 2] = 0;
|
mesh.animVertices[vCounter + 2] = 0;
|
||||||
|
|
||||||
model.meshes[m].animNormals[vCounter] = 0;
|
if (mesh.animNormals!=NULL)
|
||||||
model.meshes[m].animNormals[vCounter + 1] = 0;
|
|
||||||
model.meshes[m].animNormals[vCounter + 2] = 0;
|
|
||||||
|
|
||||||
for (int j = 0; j < 4; j++)
|
|
||||||
{
|
{
|
||||||
boneId = model.meshes[m].boneIds[boneCounter];
|
mesh.animNormals[vCounter] = 0;
|
||||||
boneWeight = model.meshes[m].boneWeights[boneCounter];
|
mesh.animNormals[vCounter + 1] = 0;
|
||||||
|
mesh.animNormals[vCounter + 2] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterates over 4 bones per vertex
|
||||||
|
for (int j = 0; j < 4; j++, boneCounter++)
|
||||||
|
{
|
||||||
|
boneWeight = mesh.boneWeights[boneCounter];
|
||||||
|
// early stop when no transformation will be applied
|
||||||
|
if (boneWeight == 0.0f)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
boneId = mesh.boneIds[boneCounter];
|
||||||
|
int boneIdParent = model.bones[boneId].parent;
|
||||||
inTranslation = model.bindPose[boneId].translation;
|
inTranslation = model.bindPose[boneId].translation;
|
||||||
inRotation = model.bindPose[boneId].rotation;
|
inRotation = model.bindPose[boneId].rotation;
|
||||||
//inScale = model.bindPose[boneId].scale;
|
// inScale = model.bindPose[boneId].scale;
|
||||||
outTranslation = anim.framePoses[frame][boneId].translation;
|
outTranslation = anim.framePoses[frame][boneId].translation;
|
||||||
outRotation = anim.framePoses[frame][boneId].rotation;
|
outRotation = anim.framePoses[frame][boneId].rotation;
|
||||||
outScale = anim.framePoses[frame][boneId].scale;
|
outScale = anim.framePoses[frame][boneId].scale;
|
||||||
|
|
||||||
// Vertices processing
|
// Vertices processing
|
||||||
// NOTE: We use meshes.vertices (default vertex position) to calculate meshes.animVertices (animated vertex position)
|
// NOTE: We use meshes.vertices (default vertex position) to calculate meshes.animVertices (animated vertex position)
|
||||||
animVertex = (Vector3){ model.meshes[m].vertices[vCounter], model.meshes[m].vertices[vCounter + 1], model.meshes[m].vertices[vCounter + 2] };
|
animVertex = (Vector3){ mesh.vertices[vCounter], mesh.vertices[vCounter + 1], mesh.vertices[vCounter + 2] };
|
||||||
animVertex = Vector3Multiply(animVertex, outScale);
|
animVertex = Vector3Multiply(animVertex, outScale);
|
||||||
animVertex = Vector3Subtract(animVertex, inTranslation);
|
animVertex = Vector3Subtract(animVertex, inTranslation);
|
||||||
animVertex = Vector3RotateByQuaternion(animVertex, QuaternionMultiply(outRotation, QuaternionInvert(inRotation)));
|
animVertex = Vector3RotateByQuaternion(animVertex, QuaternionMultiply(outRotation, QuaternionInvert(inRotation)));
|
||||||
animVertex = Vector3Add(animVertex, outTranslation);
|
animVertex = Vector3Add(animVertex, outTranslation);
|
||||||
model.meshes[m].animVertices[vCounter] += animVertex.x*boneWeight;
|
// animVertex = Vector3Transform(animVertex, model.transform);
|
||||||
model.meshes[m].animVertices[vCounter + 1] += animVertex.y*boneWeight;
|
mesh.animVertices[vCounter] += animVertex.x*boneWeight;
|
||||||
model.meshes[m].animVertices[vCounter + 2] += animVertex.z*boneWeight;
|
mesh.animVertices[vCounter + 1] += animVertex.y*boneWeight;
|
||||||
|
mesh.animVertices[vCounter + 2] += animVertex.z*boneWeight;
|
||||||
|
updated = true;
|
||||||
|
|
||||||
// Normals processing
|
// Normals processing
|
||||||
// NOTE: We use meshes.baseNormals (default normal) to calculate meshes.normals (animated normals)
|
// NOTE: We use meshes.baseNormals (default normal) to calculate meshes.normals (animated normals)
|
||||||
if (model.meshes[m].normals != NULL)
|
if (mesh.normals != NULL)
|
||||||
{
|
{
|
||||||
animNormal = (Vector3){ model.meshes[m].normals[vCounter], model.meshes[m].normals[vCounter + 1], model.meshes[m].normals[vCounter + 2] };
|
animNormal = (Vector3){ mesh.normals[vCounter], mesh.normals[vCounter + 1], mesh.normals[vCounter + 2] };
|
||||||
animNormal = Vector3RotateByQuaternion(animNormal, QuaternionMultiply(outRotation, QuaternionInvert(inRotation)));
|
animNormal = Vector3RotateByQuaternion(animNormal, QuaternionMultiply(outRotation, QuaternionInvert(inRotation)));
|
||||||
model.meshes[m].animNormals[vCounter] += animNormal.x*boneWeight;
|
mesh.animNormals[vCounter] += animNormal.x*boneWeight;
|
||||||
model.meshes[m].animNormals[vCounter + 1] += animNormal.y*boneWeight;
|
mesh.animNormals[vCounter + 1] += animNormal.y*boneWeight;
|
||||||
model.meshes[m].animNormals[vCounter + 2] += animNormal.z*boneWeight;
|
mesh.animNormals[vCounter + 2] += animNormal.z*boneWeight;
|
||||||
}
|
}
|
||||||
boneCounter += 1;
|
|
||||||
}
|
}
|
||||||
vCounter += 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Upload new vertex data to GPU for model drawing
|
// Upload new vertex data to GPU for model drawing
|
||||||
rlUpdateVertexBuffer(model.meshes[m].vboId[0], model.meshes[m].animVertices, model.meshes[m].vertexCount*3*sizeof(float), 0); // Update vertex position
|
// Only update data when values changed.
|
||||||
rlUpdateVertexBuffer(model.meshes[m].vboId[2], model.meshes[m].animNormals, model.meshes[m].vertexCount*3*sizeof(float), 0); // Update vertex normals
|
if (updated){
|
||||||
|
rlUpdateVertexBuffer(mesh.vboId[0], mesh.animVertices, mesh.vertexCount*3*sizeof(float), 0); // Update vertex position
|
||||||
|
rlUpdateVertexBuffer(mesh.vboId[2], mesh.animNormals, mesh.vertexCount*3*sizeof(float), 0); // Update vertex normals
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3080,10 +3270,13 @@ void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float siz
|
||||||
// Draw a billboard (part of a texture defined by a rectangle)
|
// Draw a billboard (part of a texture defined by a rectangle)
|
||||||
void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint)
|
void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint)
|
||||||
{
|
{
|
||||||
DrawBillboardPro(camera, texture, source, position, size, Vector2Zero(), 0.0f, tint);
|
// NOTE: Billboard locked on axis-Y
|
||||||
|
Vector3 up = { 0.0f, 1.0f, 0.0f };
|
||||||
|
|
||||||
|
DrawBillboardPro(camera, texture, source, position, up, size, Vector2Zero(), 0.0f, tint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Vector2 origin, float rotation, Color tint)
|
void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector3 up, Vector2 size, Vector2 origin, float rotation, Color tint)
|
||||||
{
|
{
|
||||||
// NOTE: Billboard size will maintain source rectangle aspect ratio, size will represent billboard width
|
// NOTE: Billboard size will maintain source rectangle aspect ratio, size will represent billboard width
|
||||||
Vector2 sizeRatio = { size.y, size.x*(float)source.height/source.width };
|
Vector2 sizeRatio = { size.y, size.x*(float)source.height/source.width };
|
||||||
|
|
@ -3093,9 +3286,6 @@ void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector
|
||||||
Vector3 right = { matView.m0, matView.m4, matView.m8 };
|
Vector3 right = { matView.m0, matView.m4, matView.m8 };
|
||||||
//Vector3 up = { matView.m1, matView.m5, matView.m9 };
|
//Vector3 up = { matView.m1, matView.m5, matView.m9 };
|
||||||
|
|
||||||
// NOTE: Billboard locked on axis-Y
|
|
||||||
Vector3 up = { 0.0f, 1.0f, 0.0f };
|
|
||||||
|
|
||||||
Vector3 rightScaled = Vector3Scale(right, sizeRatio.x/2);
|
Vector3 rightScaled = Vector3Scale(right, sizeRatio.x/2);
|
||||||
Vector3 upScaled = Vector3Scale(up, sizeRatio.y/2);
|
Vector3 upScaled = Vector3Scale(up, sizeRatio.y/2);
|
||||||
|
|
||||||
|
|
@ -3491,6 +3681,11 @@ RayCollision GetRayCollisionQuad(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3, Ve
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
#if defined(SUPPORT_FILEFORMAT_OBJ)
|
#if defined(SUPPORT_FILEFORMAT_OBJ)
|
||||||
// Load OBJ mesh data
|
// Load OBJ mesh data
|
||||||
|
//
|
||||||
|
// Keep the following information in mind when reading this
|
||||||
|
// - A mesh is created for every material present in the obj file
|
||||||
|
// - the model.meshCount is therefore the materialCount returned from tinyobj
|
||||||
|
// - the mesh is automatically triangulated by tinyobj
|
||||||
static Model LoadOBJ(const char *fileName)
|
static Model LoadOBJ(const char *fileName)
|
||||||
{
|
{
|
||||||
Model model = { 0 };
|
Model model = { 0 };
|
||||||
|
|
@ -3540,17 +3735,24 @@ static Model LoadOBJ(const char *fileName)
|
||||||
model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
|
model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
|
||||||
|
|
||||||
// Count the faces for each material
|
// Count the faces for each material
|
||||||
int *matFaces = RL_CALLOC(materialCount, sizeof(int));
|
int *matFaces = RL_CALLOC(model.meshCount, sizeof(int));
|
||||||
|
|
||||||
for (unsigned int mi = 0; mi < meshCount; mi++)
|
// iff no materials are present use all faces on one mesh
|
||||||
|
if (materialCount > 0)
|
||||||
{
|
{
|
||||||
for (unsigned int fi = 0; fi < meshes[mi].length; fi++)
|
for (int fi = 0; fi< attrib.num_faces; fi++)
|
||||||
{
|
{
|
||||||
int idx = attrib.material_ids[meshes[mi].face_offset + fi];
|
//tinyobj_vertex_index_t face = attrib.faces[fi];
|
||||||
if (idx == -1) idx = 0; // for no material face (which could be the whole model)
|
int idx = attrib.material_ids[fi];
|
||||||
matFaces[idx]++;
|
matFaces[idx]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
matFaces[0] = attrib.num_faces;
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------
|
//--------------------------------------
|
||||||
// Create the material meshes
|
// Create the material meshes
|
||||||
|
|
||||||
|
|
@ -4043,7 +4245,7 @@ static Model LoadIQM(const char *fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load IQM animation data
|
// Load IQM animation data
|
||||||
static ModelAnimation* LoadIQMModelAnimations(const char *fileName, int *animCount)
|
static ModelAnimation* LoadIQMModelAnimations(const char *fileName, unsigned int *animCount)
|
||||||
{
|
{
|
||||||
#define IQM_MAGIC "INTERQUAKEMODEL" // IQM file magic number
|
#define IQM_MAGIC "INTERQUAKEMODEL" // IQM file magic number
|
||||||
#define IQM_VERSION 2 // only IQM version 2 supported
|
#define IQM_VERSION 2 // only IQM version 2 supported
|
||||||
|
|
@ -4353,16 +4555,9 @@ static Image LoadImageFromCgltfImage(cgltf_image *image, const char *texPath, Co
|
||||||
int size = 0;
|
int size = 0;
|
||||||
unsigned char *data = DecodeBase64(image->uri + i + 1, &size);
|
unsigned char *data = DecodeBase64(image->uri + i + 1, &size);
|
||||||
|
|
||||||
int width, height;
|
rimage = LoadImageFromMemory(".png", data, size);
|
||||||
unsigned char *raw = stbi_load_from_memory(data, size, &width, &height, NULL, 4);
|
|
||||||
RL_FREE(data);
|
RL_FREE(data);
|
||||||
|
|
||||||
rimage.data = raw;
|
|
||||||
rimage.width = width;
|
|
||||||
rimage.height = height;
|
|
||||||
rimage.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
|
|
||||||
rimage.mipmaps = 1;
|
|
||||||
|
|
||||||
// TODO: Tint shouldn't be applied here!
|
// TODO: Tint shouldn't be applied here!
|
||||||
ImageColorTint(&rimage, tint);
|
ImageColorTint(&rimage, tint);
|
||||||
}
|
}
|
||||||
|
|
@ -4387,16 +4582,9 @@ static Image LoadImageFromCgltfImage(cgltf_image *image, const char *texPath, Co
|
||||||
n += stride;
|
n += stride;
|
||||||
}
|
}
|
||||||
|
|
||||||
int width, height;
|
rimage = LoadImageFromMemory(".png", data, (int)image->buffer_view->size);
|
||||||
unsigned char *raw = stbi_load_from_memory(data, (int)image->buffer_view->size, &width, &height, NULL, 4);
|
|
||||||
RL_FREE(data);
|
RL_FREE(data);
|
||||||
|
|
||||||
rimage.data = raw;
|
|
||||||
rimage.width = width;
|
|
||||||
rimage.height = height;
|
|
||||||
rimage.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
|
|
||||||
rimage.mipmaps = 1;
|
|
||||||
|
|
||||||
// TODO: Tint shouldn't be applied here!
|
// TODO: Tint shouldn't be applied here!
|
||||||
ImageColorTint(&rimage, tint);
|
ImageColorTint(&rimage, tint);
|
||||||
}
|
}
|
||||||
|
|
@ -4856,14 +5044,14 @@ static Model LoadGLTF(const char *fileName)
|
||||||
|
|
||||||
if (data->scenes_count > 1) TRACELOG(LOG_INFO, "MODEL: [%s] Has multiple scenes but only the first one will be loaded", fileName);
|
if (data->scenes_count > 1) TRACELOG(LOG_INFO, "MODEL: [%s] Has multiple scenes but only the first one will be loaded", fileName);
|
||||||
|
|
||||||
int primitivesCount = 0;
|
int primitiveCount = 0;
|
||||||
for (unsigned int i = 0; i < data->scene->nodes_count; i++)
|
for (unsigned int i = 0; i < data->scene->nodes_count; i++)
|
||||||
{
|
{
|
||||||
GetGLTFPrimitiveCount(data->scene->nodes[i], &primitivesCount);
|
GetGLTFPrimitiveCount(data->scene->nodes[i], &primitiveCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process glTF data and map to model
|
// Process glTF data and map to model
|
||||||
model.meshCount = primitivesCount;
|
model.meshCount = primitiveCount;
|
||||||
model.meshes = RL_CALLOC(model.meshCount, sizeof(Mesh));
|
model.meshes = RL_CALLOC(model.meshCount, sizeof(Mesh));
|
||||||
model.materialCount = (int)data->materials_count + 1;
|
model.materialCount = (int)data->materials_count + 1;
|
||||||
model.materials = RL_MALLOC(model.materialCount*sizeof(Material));
|
model.materials = RL_MALLOC(model.materialCount*sizeof(Material));
|
||||||
|
|
@ -4891,7 +5079,7 @@ static Model LoadGLTF(const char *fileName)
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void InitGLTFBones(Model* model, const cgltf_data* data)
|
static void InitGLTFBones(Model *model, const cgltf_data *data)
|
||||||
{
|
{
|
||||||
for (unsigned int j = 0; j < data->nodes_count; j++)
|
for (unsigned int j = 0; j < data->nodes_count; j++)
|
||||||
{
|
{
|
||||||
|
|
@ -4914,7 +5102,7 @@ static void InitGLTFBones(Model* model, const cgltf_data* data)
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
bool* completedBones = RL_CALLOC(model->boneCount, sizeof(bool));
|
bool *completedBones = RL_CALLOC(model->boneCount, sizeof(bool));
|
||||||
int numberCompletedBones = 0;
|
int numberCompletedBones = 0;
|
||||||
|
|
||||||
while (numberCompletedBones < model->boneCount)
|
while (numberCompletedBones < model->boneCount)
|
||||||
|
|
@ -5022,20 +5210,18 @@ static void LoadGLTFMaterial(Model *model, const char *fileName, const cgltf_dat
|
||||||
model->materials[model->materialCount - 1] = LoadMaterialDefault();
|
model->materials[model->materialCount - 1] = LoadMaterialDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void BindGLTFPrimitiveToBones(Model* model, const cgltf_data* data, int primitiveIndex)
|
static void BindGLTFPrimitiveToBones(Model *model, cgltf_node *node, const cgltf_data *data, int primitiveIndex)
|
||||||
{
|
{
|
||||||
for (unsigned int nodeId = 0; nodeId < data->nodes_count; nodeId++)
|
int nodeId = node - data->nodes;
|
||||||
{
|
|
||||||
if (data->nodes[nodeId].mesh == &(data->meshes[primitiveIndex]))
|
|
||||||
{
|
|
||||||
if (model->meshes[primitiveIndex].boneIds == NULL)
|
if (model->meshes[primitiveIndex].boneIds == NULL)
|
||||||
{
|
{
|
||||||
model->meshes[primitiveIndex].boneIds = RL_CALLOC(4*model->meshes[primitiveIndex].vertexCount, sizeof(int));
|
model->meshes[primitiveIndex].boneIds = RL_CALLOC(model->meshes[primitiveIndex].vertexCount*4, sizeof(int));
|
||||||
model->meshes[primitiveIndex].boneWeights = RL_CALLOC(4*model->meshes[primitiveIndex].vertexCount, sizeof(float));
|
model->meshes[primitiveIndex].boneWeights = RL_CALLOC(model->meshes[primitiveIndex].vertexCount*4, sizeof(float));
|
||||||
|
|
||||||
for (int b = 0; b < 4*model->meshes[primitiveIndex].vertexCount; b++)
|
for (int b = 0; b < model->meshes[primitiveIndex].vertexCount*4; b++)
|
||||||
{
|
{
|
||||||
if (b % 4 == 0)
|
if (b%4 == 0)
|
||||||
{
|
{
|
||||||
model->meshes[primitiveIndex].boneIds[b] = nodeId;
|
model->meshes[primitiveIndex].boneIds[b] = nodeId;
|
||||||
model->meshes[primitiveIndex].boneWeights[b] = 1.0f;
|
model->meshes[primitiveIndex].boneWeights[b] = 1.0f;
|
||||||
|
|
@ -5047,12 +5233,10 @@ static void BindGLTFPrimitiveToBones(Model* model, const cgltf_data* data, int p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadGLTF loads in animation data from given filename
|
// LoadGLTF loads in animation data from given filename
|
||||||
static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCount)
|
static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, unsigned int *animCount)
|
||||||
{
|
{
|
||||||
/***********************************************************************************
|
/***********************************************************************************
|
||||||
|
|
||||||
|
|
@ -5087,7 +5271,7 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo
|
||||||
result = cgltf_load_buffers(&options, data, fileName);
|
result = cgltf_load_buffers(&options, data, fileName);
|
||||||
if (result != cgltf_result_success) TRACELOG(LOG_WARNING, "MODEL: [%s] unable to load glTF animations data", fileName);
|
if (result != cgltf_result_success) TRACELOG(LOG_WARNING, "MODEL: [%s] unable to load glTF animations data", fileName);
|
||||||
animations = RL_MALLOC(data->animations_count*sizeof(ModelAnimation));
|
animations = RL_MALLOC(data->animations_count*sizeof(ModelAnimation));
|
||||||
*animCount = (int)data->animations_count;
|
*animCount = (unsigned int)data->animations_count;
|
||||||
|
|
||||||
for (unsigned int a = 0; a < data->animations_count; a++)
|
for (unsigned int a = 0; a < data->animations_count; a++)
|
||||||
{
|
{
|
||||||
|
|
@ -5112,7 +5296,7 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo
|
||||||
// Getting the max animation time to consider for animation duration
|
// Getting the max animation time to consider for animation duration
|
||||||
for (unsigned int i = 0; i < animation->channels_count; i++)
|
for (unsigned int i = 0; i < animation->channels_count; i++)
|
||||||
{
|
{
|
||||||
cgltf_animation_channel* channel = animation->channels + i;
|
cgltf_animation_channel *channel = animation->channels + i;
|
||||||
int frameCounts = (int)channel->sampler->input->count;
|
int frameCounts = (int)channel->sampler->input->count;
|
||||||
float lastFrameTime = 0.0f;
|
float lastFrameTime = 0.0f;
|
||||||
|
|
||||||
|
|
@ -5159,8 +5343,8 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo
|
||||||
// for each single transformation type on single bone
|
// for each single transformation type on single bone
|
||||||
for (unsigned int channelId = 0; channelId < animation->channels_count; channelId++)
|
for (unsigned int channelId = 0; channelId < animation->channels_count; channelId++)
|
||||||
{
|
{
|
||||||
cgltf_animation_channel* channel = animation->channels + channelId;
|
cgltf_animation_channel *channel = animation->channels + channelId;
|
||||||
cgltf_animation_sampler* sampler = channel->sampler;
|
cgltf_animation_sampler *sampler = channel->sampler;
|
||||||
|
|
||||||
int boneId = (int)(channel->target_node - data->nodes);
|
int boneId = (int)(channel->target_node - data->nodes);
|
||||||
|
|
||||||
|
|
@ -5217,13 +5401,16 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo
|
||||||
translationStart.y = values[1];
|
translationStart.y = values[1];
|
||||||
translationStart.z = values[2];
|
translationStart.z = values[2];
|
||||||
|
|
||||||
success = ReadGLTFValue(sampler->output, outputMax, values) || success;
|
success = ReadGLTFValue(sampler->output, outputMax, values) && success;
|
||||||
|
|
||||||
translationEnd.x = values[0];
|
translationEnd.x = values[0];
|
||||||
translationEnd.y = values[1];
|
translationEnd.y = values[1];
|
||||||
translationEnd.z = values[2];
|
translationEnd.z = values[2];
|
||||||
|
|
||||||
if (success) output->framePoses[frame][boneId].translation = Vector3Lerp(translationStart, translationEnd, lerpPercent);
|
if (success)
|
||||||
|
{
|
||||||
|
output->framePoses[frame][boneId].translation = Vector3Lerp(translationStart, translationEnd, lerpPercent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (channel->target_path == cgltf_animation_path_type_rotation)
|
if (channel->target_path == cgltf_animation_path_type_rotation)
|
||||||
{
|
{
|
||||||
|
|
@ -5239,7 +5426,7 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo
|
||||||
rotationStart.z = values[2];
|
rotationStart.z = values[2];
|
||||||
rotationStart.w = values[3];
|
rotationStart.w = values[3];
|
||||||
|
|
||||||
success = ReadGLTFValue(sampler->output, outputMax, &values) || success;
|
success = ReadGLTFValue(sampler->output, outputMax, &values) && success;
|
||||||
|
|
||||||
rotationEnd.x = values[0];
|
rotationEnd.x = values[0];
|
||||||
rotationEnd.y = values[1];
|
rotationEnd.y = values[1];
|
||||||
|
|
@ -5264,13 +5451,16 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo
|
||||||
scaleStart.y = values[1];
|
scaleStart.y = values[1];
|
||||||
scaleStart.z = values[2];
|
scaleStart.z = values[2];
|
||||||
|
|
||||||
success = ReadGLTFValue(sampler->output, outputMax, &values) || success;
|
success = ReadGLTFValue(sampler->output, outputMax, &values) && success;
|
||||||
|
|
||||||
scaleEnd.x = values[0];
|
scaleEnd.x = values[0];
|
||||||
scaleEnd.y = values[1];
|
scaleEnd.y = values[1];
|
||||||
scaleEnd.z = values[2];
|
scaleEnd.z = values[2];
|
||||||
|
|
||||||
if (success) output->framePoses[frame][boneId].scale = Vector3Lerp(scaleStart, scaleEnd, lerpPercent);
|
if (success)
|
||||||
|
{
|
||||||
|
output->framePoses[frame][boneId].scale = Vector3Lerp(scaleStart, scaleEnd, lerpPercent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -5285,7 +5475,10 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo
|
||||||
{
|
{
|
||||||
for (int i = 0; i < output->boneCount; i++)
|
for (int i = 0; i < output->boneCount; i++)
|
||||||
{
|
{
|
||||||
if (completedBones[i]) continue;
|
if (completedBones[i])
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (output->bones[i].parent < 0)
|
if (output->bones[i].parent < 0)
|
||||||
{
|
{
|
||||||
|
|
@ -5294,7 +5487,10 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!completedBones[output->bones[i].parent]) continue;
|
if (!completedBones[output->bones[i].parent])
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
output->framePoses[frame][i].rotation = QuaternionMultiply(output->framePoses[frame][output->bones[i].parent].rotation, output->framePoses[frame][i].rotation);
|
output->framePoses[frame][i].rotation = QuaternionMultiply(output->framePoses[frame][output->bones[i].parent].rotation, output->framePoses[frame][i].rotation);
|
||||||
output->framePoses[frame][i].translation = Vector3RotateByQuaternion(output->framePoses[frame][i].translation, output->framePoses[frame][output->bones[i].parent].rotation);
|
output->framePoses[frame][i].translation = Vector3RotateByQuaternion(output->framePoses[frame][i].translation, output->framePoses[frame][output->bones[i].parent].rotation);
|
||||||
|
|
@ -5304,7 +5500,6 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo
|
||||||
numberCompletedBones++;
|
numberCompletedBones++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RL_FREE(completedBones);
|
RL_FREE(completedBones);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -5318,8 +5513,9 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo
|
||||||
return animations;
|
return animations;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadGLTFMesh(cgltf_data* data, cgltf_mesh* mesh, Model* outModel, Matrix currentTransform, int* primitiveIndex, const char *fileName)
|
void LoadGLTFMesh(cgltf_data *data, cgltf_node *node, Model *outModel, Matrix currentTransform, int *primitiveIndex, const char *fileName)
|
||||||
{
|
{
|
||||||
|
cgltf_mesh *mesh = node->mesh;
|
||||||
for (unsigned int p = 0; p < mesh->primitives_count; p++)
|
for (unsigned int p = 0; p < mesh->primitives_count; p++)
|
||||||
{
|
{
|
||||||
for (unsigned int j = 0; j < mesh->primitives[p].attributes_count; j++)
|
for (unsigned int j = 0; j < mesh->primitives[p].attributes_count; j++)
|
||||||
|
|
@ -5386,23 +5582,16 @@ void LoadGLTFMesh(cgltf_data* data, cgltf_mesh* mesh, Model* outModel, Matrix cu
|
||||||
cgltf_accessor *acc = mesh->primitives[p].attributes[j].data;
|
cgltf_accessor *acc = mesh->primitives[p].attributes[j].data;
|
||||||
unsigned int boneCount = acc->count;
|
unsigned int boneCount = acc->count;
|
||||||
unsigned int totalBoneWeights = boneCount*4;
|
unsigned int totalBoneWeights = boneCount*4;
|
||||||
|
|
||||||
outModel->meshes[(*primitiveIndex)].boneIds = RL_MALLOC(totalBoneWeights*sizeof(int));
|
outModel->meshes[(*primitiveIndex)].boneIds = RL_MALLOC(totalBoneWeights*sizeof(int));
|
||||||
short *bones = ReadGLTFValuesAs(acc, cgltf_component_type_r_16, false);
|
short *bones = ReadGLTFValuesAs(acc, cgltf_component_type_r_16, false);
|
||||||
|
// Find skin joint
|
||||||
for (unsigned int a = 0; a < totalBoneWeights; a++)
|
for (unsigned int a = 0; a < totalBoneWeights; a++)
|
||||||
{
|
{
|
||||||
outModel->meshes[(*primitiveIndex)].boneIds[a] = 0;
|
outModel->meshes[(*primitiveIndex)].boneIds[a] = 0;
|
||||||
if (bones[a] < 0) continue;
|
if (bones[a] < 0) continue;
|
||||||
|
cgltf_node* skinJoint = node->skin->joints[bones[a]];
|
||||||
cgltf_node* skinJoint = data->skins->joints[bones[a]];
|
unsigned int skinJointId = skinJoint - data->nodes;
|
||||||
for (unsigned int k = 0; k < data->nodes_count; k++)
|
outModel->meshes[(*primitiveIndex)].boneIds[a] = skinJointId;
|
||||||
{
|
|
||||||
if (data->nodes + k == skinJoint)
|
|
||||||
{
|
|
||||||
outModel->meshes[(*primitiveIndex)].boneIds[a] = k;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
RL_FREE(bones);
|
RL_FREE(bones);
|
||||||
}
|
}
|
||||||
|
|
@ -5437,28 +5626,62 @@ void LoadGLTFMesh(cgltf_data* data, cgltf_mesh* mesh, Model* outModel, Matrix cu
|
||||||
}
|
}
|
||||||
else outModel->meshMaterial[(*primitiveIndex)] = outModel->materialCount - 1;
|
else outModel->meshMaterial[(*primitiveIndex)] = outModel->materialCount - 1;
|
||||||
|
|
||||||
BindGLTFPrimitiveToBones(outModel, data, *primitiveIndex);
|
BindGLTFPrimitiveToBones(outModel, node, data, *primitiveIndex);
|
||||||
|
|
||||||
(*primitiveIndex) = (*primitiveIndex) + 1;
|
(*primitiveIndex) = (*primitiveIndex) + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadGLTFNode(cgltf_data* data, cgltf_node* node, Model* outModel, Matrix currentTransform, int* primitiveIndex, const char *fileName)
|
static Matrix GetNodeTransformationMatrix(cgltf_node *node, Matrix current)
|
||||||
{
|
{
|
||||||
|
if (node->has_matrix)
|
||||||
|
{
|
||||||
Matrix nodeTransform = {
|
Matrix nodeTransform = {
|
||||||
node->matrix[0], node->matrix[4], node->matrix[8], node->matrix[12],
|
node->matrix[0], node->matrix[4], node->matrix[8], node->matrix[12],
|
||||||
node->matrix[1], node->matrix[5], node->matrix[9], node->matrix[13],
|
node->matrix[1], node->matrix[5], node->matrix[9], node->matrix[13],
|
||||||
node->matrix[2], node->matrix[6], node->matrix[10], node->matrix[14],
|
node->matrix[2], node->matrix[6], node->matrix[10], node->matrix[14],
|
||||||
node->matrix[3], node->matrix[7], node->matrix[11], node->matrix[15] };
|
node->matrix[3], node->matrix[7], node->matrix[11], node->matrix[15] };
|
||||||
|
current= MatrixMultiply(nodeTransform, current);
|
||||||
|
}
|
||||||
|
if (node->has_translation)
|
||||||
|
{
|
||||||
|
Matrix tl = MatrixTranslate(node->translation[0],node->translation[1],node->translation[2]);
|
||||||
|
current = MatrixMultiply(tl, current);
|
||||||
|
}
|
||||||
|
if (node->has_rotation)
|
||||||
|
{
|
||||||
|
Matrix rot = QuaternionToMatrix((Quaternion){node->rotation[0],node->rotation[1],node->rotation[2],node->rotation[3]});
|
||||||
|
current = MatrixMultiply(rot, current);
|
||||||
|
}
|
||||||
|
if (node->has_scale)
|
||||||
|
{
|
||||||
|
Matrix scale = MatrixScale(node->scale[0],node->scale[1],node->scale[2]);
|
||||||
|
current = MatrixMultiply(scale, current);
|
||||||
|
}
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
currentTransform = MatrixMultiply(nodeTransform, currentTransform);
|
void LoadGLTFNode(cgltf_data *data, cgltf_node *node, Model *outModel, Matrix currentTransform, int *primitiveIndex, const char *fileName)
|
||||||
|
{
|
||||||
if (node->mesh != NULL) LoadGLTFMesh(data, node->mesh, outModel, currentTransform, primitiveIndex, fileName);
|
// Apply the transforms if they exist (Will still be applied even if no mesh is present to support emptys and bone structures)
|
||||||
|
Matrix localTransform = GetNodeTransformationMatrix(node, MatrixIdentity());
|
||||||
|
currentTransform = MatrixMultiply(localTransform, currentTransform);
|
||||||
|
// Load mesh if it exists
|
||||||
|
if (node->mesh != NULL)
|
||||||
|
{
|
||||||
|
// Check if skinning is enabled and load Mesh accordingly
|
||||||
|
Matrix vertexTransform = currentTransform;
|
||||||
|
if ((node->skin != NULL) && (node->parent != NULL))
|
||||||
|
{
|
||||||
|
vertexTransform = localTransform;
|
||||||
|
TRACELOG(LOG_WARNING,"MODEL: GLTF Node %s is skinned but not root node! Parent transformations will be ignored (NODE_SKINNED_MESH_NON_ROOT)",node->name);
|
||||||
|
}
|
||||||
|
LoadGLTFMesh(data, node, outModel, vertexTransform, primitiveIndex, fileName);
|
||||||
|
}
|
||||||
for (unsigned int i = 0; i < node->children_count; i++) LoadGLTFNode(data, node->children[i], outModel, currentTransform, primitiveIndex, fileName);
|
for (unsigned int i = 0; i < node->children_count; i++) LoadGLTFNode(data, node->children[i], outModel, currentTransform, primitiveIndex, fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GetGLTFPrimitiveCount(cgltf_node* node, int* outCount)
|
static void GetGLTFPrimitiveCount(cgltf_node *node, int *outCount)
|
||||||
{
|
{
|
||||||
if (node->mesh != NULL) *outCount += node->mesh->primitives_count;
|
if (node->mesh != NULL) *outCount += node->mesh->primitives_count;
|
||||||
|
|
||||||
|
|
@ -5466,3 +5689,108 @@ static void GetGLTFPrimitiveCount(cgltf_node* node, int* outCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(SUPPORT_FILEFORMAT_VOX)
|
||||||
|
// Load VOX (MagicaVoxel) mesh data
|
||||||
|
static Model LoadVOX(const char *fileName)
|
||||||
|
{
|
||||||
|
Model model = { 0 };
|
||||||
|
int nbvertices = 0;
|
||||||
|
int meshescount = 0;
|
||||||
|
unsigned int readed = 0;
|
||||||
|
unsigned char* fileData;
|
||||||
|
|
||||||
|
//Read vox file into buffer
|
||||||
|
fileData = LoadFileData(fileName, &readed);
|
||||||
|
if (fileData == 0)
|
||||||
|
{
|
||||||
|
TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load VOX file", fileName);
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Read and build voxarray description
|
||||||
|
VoxArray3D voxarray = { 0 };
|
||||||
|
int ret = Vox_LoadFromMemory(fileData, readed, &voxarray);
|
||||||
|
|
||||||
|
if (ret != VOX_SUCCESS)
|
||||||
|
{
|
||||||
|
// Error
|
||||||
|
UnloadFileData(fileData);
|
||||||
|
|
||||||
|
TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load VOX data", fileName);
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Success: Compute meshes count
|
||||||
|
nbvertices = voxarray.vertices.used;
|
||||||
|
meshescount = 1 + (nbvertices/65536);
|
||||||
|
|
||||||
|
TRACELOG(LOG_INFO, "MODEL: [%s] VOX data loaded successfully : %i vertices/%i meshes", fileName, nbvertices, meshescount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build models from meshes
|
||||||
|
model.transform = MatrixIdentity();
|
||||||
|
|
||||||
|
model.meshCount = meshescount;
|
||||||
|
model.meshes = (Mesh *)MemAlloc(model.meshCount*sizeof(Mesh));
|
||||||
|
|
||||||
|
model.meshMaterial = (int *)MemAlloc(model.meshCount*sizeof(int));
|
||||||
|
|
||||||
|
model.materialCount = 1;
|
||||||
|
model.materials = (Material *)MemAlloc(model.materialCount*sizeof(Material));
|
||||||
|
model.materials[0] = LoadMaterialDefault();
|
||||||
|
|
||||||
|
// Init model meshes
|
||||||
|
int verticesRemain = voxarray.vertices.used;
|
||||||
|
int verticesMax = 65532; // 5461 voxels x 12 vertices per voxel -> 65532 (must be inf 65536)
|
||||||
|
|
||||||
|
Vector3 *pvertices = voxarray.vertices.array; // 6*4 = 12 vertices per voxel
|
||||||
|
Color *pcolors = voxarray.colors.array;
|
||||||
|
unsigned short *pindices = voxarray.indices.array; // 5461*6*6 = 196596 indices max per mesh
|
||||||
|
|
||||||
|
int size = 0;
|
||||||
|
|
||||||
|
for (int idxMesh = 0; idxMesh < meshescount; idxMesh++)
|
||||||
|
{
|
||||||
|
Mesh *pmesh = &model.meshes[idxMesh];
|
||||||
|
memset(pmesh, 0, sizeof(Mesh));
|
||||||
|
|
||||||
|
// Copy vertices
|
||||||
|
pmesh->vertexCount = (int)fmin(verticesMax, verticesRemain);
|
||||||
|
|
||||||
|
size = pmesh->vertexCount*sizeof(float)*3;
|
||||||
|
pmesh->vertices = MemAlloc(size);
|
||||||
|
memcpy(pmesh->vertices, pvertices, size);
|
||||||
|
|
||||||
|
// Copy indices
|
||||||
|
// TODO: Compute globals indices array
|
||||||
|
size = voxarray.indices.used * sizeof(unsigned short);
|
||||||
|
pmesh->indices = MemAlloc(size);
|
||||||
|
memcpy(pmesh->indices, pindices, size);
|
||||||
|
|
||||||
|
pmesh->triangleCount = (pmesh->vertexCount/4)*2;
|
||||||
|
|
||||||
|
// Copy colors
|
||||||
|
size = pmesh->vertexCount*sizeof(Color);
|
||||||
|
pmesh->colors = MemAlloc(size);
|
||||||
|
memcpy(pmesh->colors, pcolors, size);
|
||||||
|
|
||||||
|
// First material index
|
||||||
|
model.meshMaterial[idxMesh] = 0;
|
||||||
|
|
||||||
|
// Upload mesh data to GPU
|
||||||
|
UploadMesh(pmesh, false);
|
||||||
|
|
||||||
|
verticesRemain -= verticesMax;
|
||||||
|
pvertices += verticesMax;
|
||||||
|
pcolors += verticesMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Free buffers
|
||||||
|
Vox_FreeArrays(&voxarray);
|
||||||
|
UnloadFileData(fileData);
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/**********************************************************************************************
|
/**********************************************************************************************
|
||||||
*
|
*
|
||||||
* raylib.shapes - Basic functions to draw 2d Shapes and check collisions
|
* rshapes - Basic functions to draw 2d shapes and check collisions
|
||||||
*
|
*
|
||||||
* CONFIGURATION:
|
* CONFIGURATION:
|
||||||
*
|
*
|
||||||
|
|
@ -190,16 +190,16 @@ void DrawLineBezierQuad(Vector2 startPos, Vector2 endPos, Vector2 controlPos, fl
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw lines sequence
|
// Draw lines sequence
|
||||||
void DrawLineStrip(Vector2 *points, int pointsCount, Color color)
|
void DrawLineStrip(Vector2 *points, int pointCount, Color color)
|
||||||
{
|
{
|
||||||
if (pointsCount >= 2)
|
if (pointCount >= 2)
|
||||||
{
|
{
|
||||||
rlCheckRenderBatchLimit(pointsCount);
|
rlCheckRenderBatchLimit(pointCount);
|
||||||
|
|
||||||
rlBegin(RL_LINES);
|
rlBegin(RL_LINES);
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
for (int i = 0; i < pointsCount - 1; i++)
|
for (int i = 0; i < pointCount - 1; i++)
|
||||||
{
|
{
|
||||||
rlVertex2f(points[i].x, points[i].y);
|
rlVertex2f(points[i].x, points[i].y);
|
||||||
rlVertex2f(points[i + 1].x, points[i + 1].y);
|
rlVertex2f(points[i + 1].x, points[i + 1].y);
|
||||||
|
|
@ -1318,17 +1318,17 @@ void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
|
||||||
// Draw a triangle fan defined by points
|
// Draw a triangle fan defined by points
|
||||||
// NOTE: First vertex provided is the center, shared by all triangles
|
// NOTE: First vertex provided is the center, shared by all triangles
|
||||||
// By default, following vertex should be provided in counter-clockwise order
|
// By default, following vertex should be provided in counter-clockwise order
|
||||||
void DrawTriangleFan(Vector2 *points, int pointsCount, Color color)
|
void DrawTriangleFan(Vector2 *points, int pointCount, Color color)
|
||||||
{
|
{
|
||||||
if (pointsCount >= 3)
|
if (pointCount >= 3)
|
||||||
{
|
{
|
||||||
rlCheckRenderBatchLimit((pointsCount - 2)*4);
|
rlCheckRenderBatchLimit((pointCount - 2)*4);
|
||||||
|
|
||||||
rlSetTexture(texShapes.id);
|
rlSetTexture(texShapes.id);
|
||||||
rlBegin(RL_QUADS);
|
rlBegin(RL_QUADS);
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
for (int i = 1; i < pointsCount - 1; i++)
|
for (int i = 1; i < pointCount - 1; i++)
|
||||||
{
|
{
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlVertex2f(points[0].x, points[0].y);
|
rlVertex2f(points[0].x, points[0].y);
|
||||||
|
|
@ -1349,16 +1349,16 @@ void DrawTriangleFan(Vector2 *points, int pointsCount, Color color)
|
||||||
|
|
||||||
// Draw a triangle strip defined by points
|
// Draw a triangle strip defined by points
|
||||||
// NOTE: Every new vertex connects with previous two
|
// NOTE: Every new vertex connects with previous two
|
||||||
void DrawTriangleStrip(Vector2 *points, int pointsCount, Color color)
|
void DrawTriangleStrip(Vector2 *points, int pointCount, Color color)
|
||||||
{
|
{
|
||||||
if (pointsCount >= 3)
|
if (pointCount >= 3)
|
||||||
{
|
{
|
||||||
rlCheckRenderBatchLimit(3*(pointsCount - 2));
|
rlCheckRenderBatchLimit(3*(pointCount - 2));
|
||||||
|
|
||||||
rlBegin(RL_TRIANGLES);
|
rlBegin(RL_TRIANGLES);
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
for (int i = 2; i < pointsCount; i++)
|
for (int i = 2; i < pointCount; i++)
|
||||||
{
|
{
|
||||||
if ((i%2) == 0)
|
if ((i%2) == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/**********************************************************************************************
|
/**********************************************************************************************
|
||||||
*
|
*
|
||||||
* raylib.text - Basic functions to load Fonts and draw Text
|
* rtext - Basic functions to load fonts and draw text
|
||||||
*
|
*
|
||||||
* CONFIGURATION:
|
* CONFIGURATION:
|
||||||
*
|
*
|
||||||
|
|
@ -129,8 +129,8 @@ extern void LoadFontDefault(void)
|
||||||
// NOTE: Using UTF-8 encoding table for Unicode U+0000..U+00FF Basic Latin + Latin-1 Supplement
|
// NOTE: Using UTF-8 encoding table for Unicode U+0000..U+00FF Basic Latin + Latin-1 Supplement
|
||||||
// Ref: http://www.utf8-chartable.de/unicode-utf8-table.pl
|
// Ref: http://www.utf8-chartable.de/unicode-utf8-table.pl
|
||||||
|
|
||||||
defaultFont.charsCount = 224; // Number of chars included in our default font
|
defaultFont.glyphCount = 224; // Number of chars included in our default font
|
||||||
defaultFont.charsPadding = 0; // Characters padding
|
defaultFont.glyphPadding = 0; // Characters padding
|
||||||
|
|
||||||
// Default font is directly defined here (data generated from a sprite font image)
|
// Default font is directly defined here (data generated from a sprite font image)
|
||||||
// This way, we reconstruct Font without creating large global variables
|
// This way, we reconstruct Font without creating large global variables
|
||||||
|
|
@ -220,21 +220,21 @@ extern void LoadFontDefault(void)
|
||||||
|
|
||||||
defaultFont.texture = LoadTextureFromImage(imFont);
|
defaultFont.texture = LoadTextureFromImage(imFont);
|
||||||
|
|
||||||
// Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, charsCount
|
// Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, glyphCount
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Allocate space for our characters info data
|
// Allocate space for our characters info data
|
||||||
// NOTE: This memory should be freed at end! --> CloseWindow()
|
// NOTE: This memory should be freed at end! --> CloseWindow()
|
||||||
defaultFont.chars = (GlyphInfo *)RL_MALLOC(defaultFont.charsCount*sizeof(GlyphInfo));
|
defaultFont.glyphs = (GlyphInfo *)RL_MALLOC(defaultFont.glyphCount*sizeof(GlyphInfo));
|
||||||
defaultFont.recs = (Rectangle *)RL_MALLOC(defaultFont.charsCount*sizeof(Rectangle));
|
defaultFont.recs = (Rectangle *)RL_MALLOC(defaultFont.glyphCount*sizeof(Rectangle));
|
||||||
|
|
||||||
int currentLine = 0;
|
int currentLine = 0;
|
||||||
int currentPosX = charsDivisor;
|
int currentPosX = charsDivisor;
|
||||||
int testPosX = charsDivisor;
|
int testPosX = charsDivisor;
|
||||||
|
|
||||||
for (int i = 0; i < defaultFont.charsCount; i++)
|
for (int i = 0; i < defaultFont.glyphCount; i++)
|
||||||
{
|
{
|
||||||
defaultFont.chars[i].value = 32 + i; // First char is 32
|
defaultFont.glyphs[i].value = 32 + i; // First char is 32
|
||||||
|
|
||||||
defaultFont.recs[i].x = (float)currentPosX;
|
defaultFont.recs[i].x = (float)currentPosX;
|
||||||
defaultFont.recs[i].y = (float)(charsDivisor + currentLine*(charsHeight + charsDivisor));
|
defaultFont.recs[i].y = (float)(charsDivisor + currentLine*(charsHeight + charsDivisor));
|
||||||
|
|
@ -255,27 +255,27 @@ extern void LoadFontDefault(void)
|
||||||
else currentPosX = testPosX;
|
else currentPosX = testPosX;
|
||||||
|
|
||||||
// NOTE: On default font character offsets and xAdvance are not required
|
// NOTE: On default font character offsets and xAdvance are not required
|
||||||
defaultFont.chars[i].offsetX = 0;
|
defaultFont.glyphs[i].offsetX = 0;
|
||||||
defaultFont.chars[i].offsetY = 0;
|
defaultFont.glyphs[i].offsetY = 0;
|
||||||
defaultFont.chars[i].advanceX = 0;
|
defaultFont.glyphs[i].advanceX = 0;
|
||||||
|
|
||||||
// Fill character image data from fontClear data
|
// Fill character image data from fontClear data
|
||||||
defaultFont.chars[i].image = ImageFromImage(imFont, defaultFont.recs[i]);
|
defaultFont.glyphs[i].image = ImageFromImage(imFont, defaultFont.recs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
UnloadImage(imFont);
|
UnloadImage(imFont);
|
||||||
|
|
||||||
defaultFont.baseSize = (int)defaultFont.recs[0].height;
|
defaultFont.baseSize = (int)defaultFont.recs[0].height;
|
||||||
|
|
||||||
TRACELOG(LOG_INFO, "FONT: [ID %i] Default font texture loaded successfully", defaultFont.texture.id);
|
TRACELOG(LOG_INFO, "FONT: Default font loaded successfully (%i glyphs)", defaultFont.glyphCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unload raylib default font
|
// Unload raylib default font
|
||||||
extern void UnloadFontDefault(void)
|
extern void UnloadFontDefault(void)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < defaultFont.charsCount; i++) UnloadImage(defaultFont.chars[i].image);
|
for (int i = 0; i < defaultFont.glyphCount; i++) UnloadImage(defaultFont.glyphs[i].image);
|
||||||
UnloadTexture(defaultFont.texture);
|
UnloadTexture(defaultFont.texture);
|
||||||
RL_FREE(defaultFont.chars);
|
RL_FREE(defaultFont.glyphs);
|
||||||
RL_FREE(defaultFont.recs);
|
RL_FREE(defaultFont.recs);
|
||||||
}
|
}
|
||||||
#endif // SUPPORT_DEFAULT_FONT
|
#endif // SUPPORT_DEFAULT_FONT
|
||||||
|
|
@ -337,7 +337,7 @@ Font LoadFont(const char *fileName)
|
||||||
// Load Font from TTF font file with generation parameters
|
// Load Font from TTF font file with generation parameters
|
||||||
// NOTE: You can pass an array with desired characters, those characters should be available in the font
|
// NOTE: You can pass an array with desired characters, those characters should be available in the font
|
||||||
// if array is NULL, default char set is selected 32..126
|
// if array is NULL, default char set is selected 32..126
|
||||||
Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int charsCount)
|
Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int glyphCount)
|
||||||
{
|
{
|
||||||
Font font = { 0 };
|
Font font = { 0 };
|
||||||
|
|
||||||
|
|
@ -348,7 +348,7 @@ Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int charsCou
|
||||||
if (fileData != NULL)
|
if (fileData != NULL)
|
||||||
{
|
{
|
||||||
// Loading font from memory data
|
// Loading font from memory data
|
||||||
font = LoadFontFromMemory(GetFileExtension(fileName), fileData, fileSize, fontSize, fontChars, charsCount);
|
font = LoadFontFromMemory(GetFileExtension(fileName), fileData, fileSize, fontSize, fontChars, glyphCount);
|
||||||
|
|
||||||
RL_FREE(fileData);
|
RL_FREE(fileData);
|
||||||
}
|
}
|
||||||
|
|
@ -449,28 +449,28 @@ Font LoadFontFromImage(Image image, Color key, int firstChar)
|
||||||
Font font = { 0 };
|
Font font = { 0 };
|
||||||
|
|
||||||
font.texture = LoadTextureFromImage(fontClear); // Convert processed image to OpenGL texture
|
font.texture = LoadTextureFromImage(fontClear); // Convert processed image to OpenGL texture
|
||||||
font.charsCount = index;
|
font.glyphCount = index;
|
||||||
font.charsPadding = 0;
|
font.glyphPadding = 0;
|
||||||
|
|
||||||
// We got tempCharValues and tempCharsRecs populated with chars data
|
// We got tempCharValues and tempCharsRecs populated with chars data
|
||||||
// Now we move temp data to sized charValues and charRecs arrays
|
// Now we move temp data to sized charValues and charRecs arrays
|
||||||
font.chars = (GlyphInfo *)RL_MALLOC(font.charsCount*sizeof(GlyphInfo));
|
font.glyphs = (GlyphInfo *)RL_MALLOC(font.glyphCount*sizeof(GlyphInfo));
|
||||||
font.recs = (Rectangle *)RL_MALLOC(font.charsCount*sizeof(Rectangle));
|
font.recs = (Rectangle *)RL_MALLOC(font.glyphCount*sizeof(Rectangle));
|
||||||
|
|
||||||
for (int i = 0; i < font.charsCount; i++)
|
for (int i = 0; i < font.glyphCount; i++)
|
||||||
{
|
{
|
||||||
font.chars[i].value = tempCharValues[i];
|
font.glyphs[i].value = tempCharValues[i];
|
||||||
|
|
||||||
// Get character rectangle in the font atlas texture
|
// Get character rectangle in the font atlas texture
|
||||||
font.recs[i] = tempCharRecs[i];
|
font.recs[i] = tempCharRecs[i];
|
||||||
|
|
||||||
// NOTE: On image based fonts (XNA style), character offsets and xAdvance are not required (set to 0)
|
// NOTE: On image based fonts (XNA style), character offsets and xAdvance are not required (set to 0)
|
||||||
font.chars[i].offsetX = 0;
|
font.glyphs[i].offsetX = 0;
|
||||||
font.chars[i].offsetY = 0;
|
font.glyphs[i].offsetY = 0;
|
||||||
font.chars[i].advanceX = 0;
|
font.glyphs[i].advanceX = 0;
|
||||||
|
|
||||||
// Fill character image data from fontClear data
|
// Fill character image data from fontClear data
|
||||||
font.chars[i].image = ImageFromImage(fontClear, tempCharRecs[i]);
|
font.glyphs[i].image = ImageFromImage(fontClear, tempCharRecs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
UnloadImage(fontClear); // Unload processed image once converted to texture
|
UnloadImage(fontClear); // Unload processed image once converted to texture
|
||||||
|
|
@ -481,7 +481,7 @@ Font LoadFontFromImage(Image image, Color key, int firstChar)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load font from memory buffer, fileType refers to extension: i.e. ".ttf"
|
// Load font from memory buffer, fileType refers to extension: i.e. ".ttf"
|
||||||
Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int charsCount)
|
Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int glyphCount)
|
||||||
{
|
{
|
||||||
Font font = { 0 };
|
Font font = { 0 };
|
||||||
|
|
||||||
|
|
@ -493,25 +493,27 @@ Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int
|
||||||
TextIsEqual(fileExtLower, ".otf"))
|
TextIsEqual(fileExtLower, ".otf"))
|
||||||
{
|
{
|
||||||
font.baseSize = fontSize;
|
font.baseSize = fontSize;
|
||||||
font.charsCount = (charsCount > 0)? charsCount : 95;
|
font.glyphCount = (glyphCount > 0)? glyphCount : 95;
|
||||||
font.charsPadding = 0;
|
font.glyphPadding = 0;
|
||||||
font.chars = LoadFontData(fileData, dataSize, font.baseSize, fontChars, font.charsCount, FONT_DEFAULT);
|
font.glyphs = LoadFontData(fileData, dataSize, font.baseSize, fontChars, font.glyphCount, FONT_DEFAULT);
|
||||||
|
|
||||||
if (font.chars != NULL)
|
if (font.glyphs != NULL)
|
||||||
{
|
{
|
||||||
font.charsPadding = FONT_TTF_DEFAULT_CHARS_PADDING;
|
font.glyphPadding = FONT_TTF_DEFAULT_CHARS_PADDING;
|
||||||
|
|
||||||
Image atlas = GenImageFontAtlas(font.chars, &font.recs, font.charsCount, font.baseSize, font.charsPadding, 0);
|
Image atlas = GenImageFontAtlas(font.glyphs, &font.recs, font.glyphCount, font.baseSize, font.glyphPadding, 0);
|
||||||
font.texture = LoadTextureFromImage(atlas);
|
font.texture = LoadTextureFromImage(atlas);
|
||||||
|
|
||||||
// Update chars[i].image to use alpha, required to be used on ImageDrawText()
|
// Update glyphs[i].image to use alpha, required to be used on ImageDrawText()
|
||||||
for (int i = 0; i < font.charsCount; i++)
|
for (int i = 0; i < font.glyphCount; i++)
|
||||||
{
|
{
|
||||||
UnloadImage(font.chars[i].image);
|
UnloadImage(font.glyphs[i].image);
|
||||||
font.chars[i].image = ImageFromImage(atlas, font.recs[i]);
|
font.glyphs[i].image = ImageFromImage(atlas, font.recs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
UnloadImage(atlas);
|
UnloadImage(atlas);
|
||||||
|
|
||||||
|
// TRACELOG(LOG_INFO, "FONT: Font loaded successfully (%i glyphs)", font.glyphCount);
|
||||||
}
|
}
|
||||||
else font = GetFontDefault();
|
else font = GetFontDefault();
|
||||||
}
|
}
|
||||||
|
|
@ -524,7 +526,7 @@ Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int
|
||||||
|
|
||||||
// Load font data for further use
|
// Load font data for further use
|
||||||
// NOTE: Requires TTF font memory data and can generate SDF data
|
// NOTE: Requires TTF font memory data and can generate SDF data
|
||||||
GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int charsCount, int type)
|
GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int glyphCount, int type)
|
||||||
{
|
{
|
||||||
// NOTE: Using some SDF generation default values,
|
// NOTE: Using some SDF generation default values,
|
||||||
// trades off precision with ability to handle *smaller* sizes
|
// trades off precision with ability to handle *smaller* sizes
|
||||||
|
|
@ -562,22 +564,22 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
|
||||||
stbtt_GetFontVMetrics(&fontInfo, &ascent, &descent, &lineGap);
|
stbtt_GetFontVMetrics(&fontInfo, &ascent, &descent, &lineGap);
|
||||||
|
|
||||||
// In case no chars count provided, default to 95
|
// In case no chars count provided, default to 95
|
||||||
charsCount = (charsCount > 0)? charsCount : 95;
|
glyphCount = (glyphCount > 0)? glyphCount : 95;
|
||||||
|
|
||||||
// Fill fontChars in case not provided externally
|
// Fill fontChars in case not provided externally
|
||||||
// NOTE: By default we fill charsCount consecutevely, starting at 32 (Space)
|
// NOTE: By default we fill glyphCount consecutevely, starting at 32 (Space)
|
||||||
|
|
||||||
if (fontChars == NULL)
|
if (fontChars == NULL)
|
||||||
{
|
{
|
||||||
fontChars = (int *)RL_MALLOC(charsCount*sizeof(int));
|
fontChars = (int *)RL_MALLOC(glyphCount*sizeof(int));
|
||||||
for (int i = 0; i < charsCount; i++) fontChars[i] = i + 32;
|
for (int i = 0; i < glyphCount; i++) fontChars[i] = i + 32;
|
||||||
genFontChars = true;
|
genFontChars = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
chars = (GlyphInfo *)RL_MALLOC(charsCount*sizeof(GlyphInfo));
|
chars = (GlyphInfo *)RL_MALLOC(glyphCount*sizeof(GlyphInfo));
|
||||||
|
|
||||||
// NOTE: Using simple packaging, one char after another
|
// NOTE: Using simple packaging, one char after another
|
||||||
for (int i = 0; i < charsCount; i++)
|
for (int i = 0; i < glyphCount; i++)
|
||||||
{
|
{
|
||||||
int chw = 0, chh = 0; // Character width and height (on generation)
|
int chw = 0, chh = 0; // Character width and height (on generation)
|
||||||
int ch = fontChars[i]; // Character value to get info for
|
int ch = fontChars[i]; // Character value to get info for
|
||||||
|
|
@ -650,7 +652,7 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
|
||||||
// Generate image font atlas using chars info
|
// Generate image font atlas using chars info
|
||||||
// NOTE: Packing method: 0-Default, 1-Skyline
|
// NOTE: Packing method: 0-Default, 1-Skyline
|
||||||
#if defined(SUPPORT_FILEFORMAT_TTF)
|
#if defined(SUPPORT_FILEFORMAT_TTF)
|
||||||
Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int charsCount, int fontSize, int padding, int packMethod)
|
Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphCount, int fontSize, int padding, int packMethod)
|
||||||
{
|
{
|
||||||
Image atlas = { 0 };
|
Image atlas = { 0 };
|
||||||
|
|
||||||
|
|
@ -663,17 +665,17 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int charsC
|
||||||
*charRecs = NULL;
|
*charRecs = NULL;
|
||||||
|
|
||||||
// In case no chars count provided we suppose default of 95
|
// In case no chars count provided we suppose default of 95
|
||||||
charsCount = (charsCount > 0)? charsCount : 95;
|
glyphCount = (glyphCount > 0)? glyphCount : 95;
|
||||||
|
|
||||||
// NOTE: Rectangles memory is loaded here!
|
// NOTE: Rectangles memory is loaded here!
|
||||||
Rectangle *recs = (Rectangle *)RL_MALLOC(charsCount*sizeof(Rectangle));
|
Rectangle *recs = (Rectangle *)RL_MALLOC(glyphCount*sizeof(Rectangle));
|
||||||
|
|
||||||
// Calculate image size based on required pixel area
|
// Calculate image size based on required pixel area
|
||||||
// NOTE 1: Image is forced to be squared and POT... very conservative!
|
// NOTE 1: Image is forced to be squared and POT... very conservative!
|
||||||
// NOTE 2: SDF font characters already contain an internal padding,
|
// NOTE 2: SDF font characters already contain an internal padding,
|
||||||
// so image size would result bigger than default font type
|
// so image size would result bigger than default font type
|
||||||
float requiredArea = 0;
|
float requiredArea = 0;
|
||||||
for (int i = 0; i < charsCount; i++) requiredArea += ((chars[i].image.width + 2*padding)*(chars[i].image.height + 2*padding));
|
for (int i = 0; i < glyphCount; i++) requiredArea += ((chars[i].image.width + 2*padding)*(chars[i].image.height + 2*padding));
|
||||||
float guessSize = sqrtf(requiredArea)*1.3f;
|
float guessSize = sqrtf(requiredArea)*1.3f;
|
||||||
int imageSize = (int)powf(2, ceilf(logf((float)guessSize)/logf(2))); // Calculate next POT
|
int imageSize = (int)powf(2, ceilf(logf((float)guessSize)/logf(2))); // Calculate next POT
|
||||||
|
|
||||||
|
|
@ -692,7 +694,7 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int charsC
|
||||||
int offsetY = padding;
|
int offsetY = padding;
|
||||||
|
|
||||||
// NOTE: Using simple packaging, one char after another
|
// NOTE: Using simple packaging, one char after another
|
||||||
for (int i = 0; i < charsCount; i++)
|
for (int i = 0; i < glyphCount; i++)
|
||||||
{
|
{
|
||||||
// Copy pixel data from fc.data to atlas
|
// Copy pixel data from fc.data to atlas
|
||||||
for (int y = 0; y < chars[i].image.height; y++)
|
for (int y = 0; y < chars[i].image.height; y++)
|
||||||
|
|
@ -728,13 +730,13 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int charsC
|
||||||
else if (packMethod == 1) // Use Skyline rect packing algorythm (stb_pack_rect)
|
else if (packMethod == 1) // Use Skyline rect packing algorythm (stb_pack_rect)
|
||||||
{
|
{
|
||||||
stbrp_context *context = (stbrp_context *)RL_MALLOC(sizeof(*context));
|
stbrp_context *context = (stbrp_context *)RL_MALLOC(sizeof(*context));
|
||||||
stbrp_node *nodes = (stbrp_node *)RL_MALLOC(charsCount*sizeof(*nodes));
|
stbrp_node *nodes = (stbrp_node *)RL_MALLOC(glyphCount*sizeof(*nodes));
|
||||||
|
|
||||||
stbrp_init_target(context, atlas.width, atlas.height, nodes, charsCount);
|
stbrp_init_target(context, atlas.width, atlas.height, nodes, glyphCount);
|
||||||
stbrp_rect *rects = (stbrp_rect *)RL_MALLOC(charsCount*sizeof(stbrp_rect));
|
stbrp_rect *rects = (stbrp_rect *)RL_MALLOC(glyphCount*sizeof(stbrp_rect));
|
||||||
|
|
||||||
// Fill rectangles for packaging
|
// Fill rectangles for packaging
|
||||||
for (int i = 0; i < charsCount; i++)
|
for (int i = 0; i < glyphCount; i++)
|
||||||
{
|
{
|
||||||
rects[i].id = i;
|
rects[i].id = i;
|
||||||
rects[i].w = chars[i].image.width + 2*padding;
|
rects[i].w = chars[i].image.width + 2*padding;
|
||||||
|
|
@ -742,9 +744,9 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int charsC
|
||||||
}
|
}
|
||||||
|
|
||||||
// Package rectangles into atlas
|
// Package rectangles into atlas
|
||||||
stbrp_pack_rects(context, rects, charsCount);
|
stbrp_pack_rects(context, rects, glyphCount);
|
||||||
|
|
||||||
for (int i = 0; i < charsCount; i++)
|
for (int i = 0; i < glyphCount; i++)
|
||||||
{
|
{
|
||||||
// It return char rectangles in atlas
|
// It return char rectangles in atlas
|
||||||
recs[i].x = rects[i].x + (float)padding;
|
recs[i].x = rects[i].x + (float)padding;
|
||||||
|
|
@ -792,12 +794,12 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int charsC
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Unload font chars info data (RAM)
|
// Unload font glyphs info data (RAM)
|
||||||
void UnloadFontData(GlyphInfo *chars, int charsCount)
|
void UnloadFontData(GlyphInfo *glyphs, int glyphCount)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < charsCount; i++) UnloadImage(chars[i].image);
|
for (int i = 0; i < glyphCount; i++) UnloadImage(glyphs[i].image);
|
||||||
|
|
||||||
RL_FREE(chars);
|
RL_FREE(glyphs);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unload Font from GPU memory (VRAM)
|
// Unload Font from GPU memory (VRAM)
|
||||||
|
|
@ -806,7 +808,7 @@ void UnloadFont(Font font)
|
||||||
// NOTE: Make sure font is not default font (fallback)
|
// NOTE: Make sure font is not default font (fallback)
|
||||||
if (font.texture.id != GetFontDefault().texture.id)
|
if (font.texture.id != GetFontDefault().texture.id)
|
||||||
{
|
{
|
||||||
UnloadFontData(font.chars, font.charsCount);
|
UnloadFontData(font.glyphs, font.glyphCount);
|
||||||
UnloadTexture(font.texture);
|
UnloadTexture(font.texture);
|
||||||
RL_FREE(font.recs);
|
RL_FREE(font.recs);
|
||||||
|
|
||||||
|
|
@ -851,14 +853,14 @@ void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, f
|
||||||
{
|
{
|
||||||
if (font.texture.id == 0) font = GetFontDefault(); // Security check in case of not valid font
|
if (font.texture.id == 0) font = GetFontDefault(); // Security check in case of not valid font
|
||||||
|
|
||||||
int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop
|
int size = TextLength(text); // Total size in bytes of the text, scanned by codepoints in loop
|
||||||
|
|
||||||
int textOffsetY = 0; // Offset between lines (on line break '\n')
|
int textOffsetY = 0; // Offset between lines (on line break '\n')
|
||||||
float textOffsetX = 0.0f; // Offset X to next character to draw
|
float textOffsetX = 0.0f; // Offset X to next character to draw
|
||||||
|
|
||||||
float scaleFactor = fontSize/font.baseSize; // Character quad scaling factor
|
float scaleFactor = fontSize/font.baseSize; // Character quad scaling factor
|
||||||
|
|
||||||
for (int i = 0; i < length;)
|
for (int i = 0; i < size;)
|
||||||
{
|
{
|
||||||
// Get next codepoint from byte string and glyph index in font
|
// Get next codepoint from byte string and glyph index in font
|
||||||
int codepointByteCount = 0;
|
int codepointByteCount = 0;
|
||||||
|
|
@ -883,8 +885,8 @@ void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, f
|
||||||
DrawTextCodepoint(font, codepoint, (Vector2){ position.x + textOffsetX, position.y + textOffsetY }, fontSize, tint);
|
DrawTextCodepoint(font, codepoint, (Vector2){ position.x + textOffsetX, position.y + textOffsetY }, fontSize, tint);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (font.chars[index].advanceX == 0) textOffsetX += ((float)font.recs[index].width*scaleFactor + spacing);
|
if (font.glyphs[index].advanceX == 0) textOffsetX += ((float)font.recs[index].width*scaleFactor + spacing);
|
||||||
else textOffsetX += ((float)font.chars[index].advanceX*scaleFactor + spacing);
|
else textOffsetX += ((float)font.glyphs[index].advanceX*scaleFactor + spacing);
|
||||||
}
|
}
|
||||||
|
|
||||||
i += codepointByteCount; // Move text bytes counter to next codepoint
|
i += codepointByteCount; // Move text bytes counter to next codepoint
|
||||||
|
|
@ -914,16 +916,16 @@ void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSiz
|
||||||
float scaleFactor = fontSize/font.baseSize; // Character quad scaling factor
|
float scaleFactor = fontSize/font.baseSize; // Character quad scaling factor
|
||||||
|
|
||||||
// Character destination rectangle on screen
|
// Character destination rectangle on screen
|
||||||
// NOTE: We consider charsPadding on drawing
|
// NOTE: We consider glyphPadding on drawing
|
||||||
Rectangle dstRec = { position.x + font.chars[index].offsetX*scaleFactor - (float)font.charsPadding*scaleFactor,
|
Rectangle dstRec = { position.x + font.glyphs[index].offsetX*scaleFactor - (float)font.glyphPadding*scaleFactor,
|
||||||
position.y + font.chars[index].offsetY*scaleFactor - (float)font.charsPadding*scaleFactor,
|
position.y + font.glyphs[index].offsetY*scaleFactor - (float)font.glyphPadding*scaleFactor,
|
||||||
(font.recs[index].width + 2.0f*font.charsPadding)*scaleFactor,
|
(font.recs[index].width + 2.0f*font.glyphPadding)*scaleFactor,
|
||||||
(font.recs[index].height + 2.0f*font.charsPadding)*scaleFactor };
|
(font.recs[index].height + 2.0f*font.glyphPadding)*scaleFactor };
|
||||||
|
|
||||||
// Character source rectangle from font texture atlas
|
// Character source rectangle from font texture atlas
|
||||||
// NOTE: We consider chars padding when drawing, it could be required for outline/glow shader effects
|
// NOTE: We consider chars padding when drawing, it could be required for outline/glow shader effects
|
||||||
Rectangle srcRec = { font.recs[index].x - (float)font.charsPadding, font.recs[index].y - (float)font.charsPadding,
|
Rectangle srcRec = { font.recs[index].x - (float)font.glyphPadding, font.recs[index].y - (float)font.glyphPadding,
|
||||||
font.recs[index].width + 2.0f*font.charsPadding, font.recs[index].height + 2.0f*font.charsPadding };
|
font.recs[index].width + 2.0f*font.glyphPadding, font.recs[index].height + 2.0f*font.glyphPadding };
|
||||||
|
|
||||||
// Draw the character texture on the screen
|
// Draw the character texture on the screen
|
||||||
DrawTexturePro(font.texture, srcRec, dstRec, (Vector2){ 0, 0 }, 0.0f, tint);
|
DrawTexturePro(font.texture, srcRec, dstRec, (Vector2){ 0, 0 }, 0.0f, tint);
|
||||||
|
|
@ -950,9 +952,9 @@ int MeasureText(const char *text, int fontSize)
|
||||||
// Measure string size for Font
|
// Measure string size for Font
|
||||||
Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing)
|
Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing)
|
||||||
{
|
{
|
||||||
int len = TextLength(text);
|
int size = TextLength(text); // Get size in bytes of text
|
||||||
int tempLen = 0; // Used to count longer text line num chars
|
int tempByteCounter = 0; // Used to count longer text line num chars
|
||||||
int lenCounter = 0;
|
int byteCounter = 0;
|
||||||
|
|
||||||
float textWidth = 0.0f;
|
float textWidth = 0.0f;
|
||||||
float tempTextWidth = 0.0f; // Used to count longer text line width
|
float tempTextWidth = 0.0f; // Used to count longer text line width
|
||||||
|
|
@ -963,9 +965,9 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
|
||||||
int letter = 0; // Current character
|
int letter = 0; // Current character
|
||||||
int index = 0; // Index position in sprite font
|
int index = 0; // Index position in sprite font
|
||||||
|
|
||||||
for (int i = 0; i < len; i++)
|
for (int i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
lenCounter++;
|
byteCounter++;
|
||||||
|
|
||||||
int next = 0;
|
int next = 0;
|
||||||
letter = GetCodepoint(&text[i], &next);
|
letter = GetCodepoint(&text[i], &next);
|
||||||
|
|
@ -978,24 +980,24 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
|
||||||
|
|
||||||
if (letter != '\n')
|
if (letter != '\n')
|
||||||
{
|
{
|
||||||
if (font.chars[index].advanceX != 0) textWidth += font.chars[index].advanceX;
|
if (font.glyphs[index].advanceX != 0) textWidth += font.glyphs[index].advanceX;
|
||||||
else textWidth += (font.recs[index].width + font.chars[index].offsetX);
|
else textWidth += (font.recs[index].width + font.glyphs[index].offsetX);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
|
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
|
||||||
lenCounter = 0;
|
byteCounter = 0;
|
||||||
textWidth = 0;
|
textWidth = 0;
|
||||||
textHeight += ((float)font.baseSize*1.5f); // NOTE: Fixed line spacing of 1.5 lines
|
textHeight += ((float)font.baseSize*1.5f); // NOTE: Fixed line spacing of 1.5 lines
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tempLen < lenCounter) tempLen = lenCounter;
|
if (tempByteCounter < byteCounter) tempByteCounter = byteCounter;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
|
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
|
||||||
|
|
||||||
Vector2 vec = { 0 };
|
Vector2 vec = { 0 };
|
||||||
vec.x = tempTextWidth*scaleFactor + (float)((tempLen - 1)*spacing); // Adds chars spacing to measure
|
vec.x = tempTextWidth*scaleFactor + (float)((tempByteCounter - 1)*spacing); // Adds chars spacing to measure
|
||||||
vec.y = textHeight*scaleFactor;
|
vec.y = textHeight*scaleFactor;
|
||||||
|
|
||||||
return vec;
|
return vec;
|
||||||
|
|
@ -1014,9 +1016,9 @@ int GetGlyphIndex(Font font, int codepoint)
|
||||||
#if defined(SUPPORT_UNORDERED_CHARSET)
|
#if defined(SUPPORT_UNORDERED_CHARSET)
|
||||||
int index = GLYPH_NOTFOUND_CHAR_FALLBACK;
|
int index = GLYPH_NOTFOUND_CHAR_FALLBACK;
|
||||||
|
|
||||||
for (int i = 0; i < font.charsCount; i++)
|
for (int i = 0; i < font.glyphCount; i++)
|
||||||
{
|
{
|
||||||
if (font.chars[i].value == codepoint)
|
if (font.glyphs[i].value == codepoint)
|
||||||
{
|
{
|
||||||
index = i;
|
index = i;
|
||||||
break;
|
break;
|
||||||
|
|
@ -1035,7 +1037,7 @@ GlyphInfo GetGlyphInfo(Font font, int codepoint)
|
||||||
{
|
{
|
||||||
GlyphInfo info = { 0 };
|
GlyphInfo info = { 0 };
|
||||||
|
|
||||||
info = font.chars[GetGlyphIndex(font, codepoint)];
|
info = font.glyphs[GetGlyphIndex(font, codepoint)];
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
@ -1429,28 +1431,28 @@ char *TextCodepointsToUTF8(int *codepoints, int length)
|
||||||
|
|
||||||
// Encode codepoint into utf8 text (char array length returned as parameter)
|
// Encode codepoint into utf8 text (char array length returned as parameter)
|
||||||
// NOTE: It uses a static array to store UTF-8 bytes
|
// NOTE: It uses a static array to store UTF-8 bytes
|
||||||
RLAPI const char *CodepointToUTF8(int codepoint, int *byteLength)
|
RLAPI const char *CodepointToUTF8(int codepoint, int *byteSize)
|
||||||
{
|
{
|
||||||
static char utf8[6] = { 0 };
|
static char utf8[6] = { 0 };
|
||||||
int length = 0;
|
int size = 0; // Byte size of codepoint
|
||||||
|
|
||||||
if (codepoint <= 0x7f)
|
if (codepoint <= 0x7f)
|
||||||
{
|
{
|
||||||
utf8[0] = (char)codepoint;
|
utf8[0] = (char)codepoint;
|
||||||
length = 1;
|
size = 1;
|
||||||
}
|
}
|
||||||
else if (codepoint <= 0x7ff)
|
else if (codepoint <= 0x7ff)
|
||||||
{
|
{
|
||||||
utf8[0] = (char)(((codepoint >> 6) & 0x1f) | 0xc0);
|
utf8[0] = (char)(((codepoint >> 6) & 0x1f) | 0xc0);
|
||||||
utf8[1] = (char)((codepoint & 0x3f) | 0x80);
|
utf8[1] = (char)((codepoint & 0x3f) | 0x80);
|
||||||
length = 2;
|
size = 2;
|
||||||
}
|
}
|
||||||
else if (codepoint <= 0xffff)
|
else if (codepoint <= 0xffff)
|
||||||
{
|
{
|
||||||
utf8[0] = (char)(((codepoint >> 12) & 0x0f) | 0xe0);
|
utf8[0] = (char)(((codepoint >> 12) & 0x0f) | 0xe0);
|
||||||
utf8[1] = (char)(((codepoint >> 6) & 0x3f) | 0x80);
|
utf8[1] = (char)(((codepoint >> 6) & 0x3f) | 0x80);
|
||||||
utf8[2] = (char)((codepoint & 0x3f) | 0x80);
|
utf8[2] = (char)((codepoint & 0x3f) | 0x80);
|
||||||
length = 3;
|
size = 3;
|
||||||
}
|
}
|
||||||
else if (codepoint <= 0x10ffff)
|
else if (codepoint <= 0x10ffff)
|
||||||
{
|
{
|
||||||
|
|
@ -1458,10 +1460,10 @@ RLAPI const char *CodepointToUTF8(int codepoint, int *byteLength)
|
||||||
utf8[1] = (char)(((codepoint >> 12) & 0x3f) | 0x80);
|
utf8[1] = (char)(((codepoint >> 12) & 0x3f) | 0x80);
|
||||||
utf8[2] = (char)(((codepoint >> 6) & 0x3f) | 0x80);
|
utf8[2] = (char)(((codepoint >> 6) & 0x3f) | 0x80);
|
||||||
utf8[3] = (char)((codepoint & 0x3f) | 0x80);
|
utf8[3] = (char)((codepoint & 0x3f) | 0x80);
|
||||||
length = 4;
|
size = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
*byteLength = length;
|
*byteSize = size;
|
||||||
|
|
||||||
return utf8;
|
return utf8;
|
||||||
}
|
}
|
||||||
|
|
@ -1472,22 +1474,22 @@ int *LoadCodepoints(const char *text, int *count)
|
||||||
int textLength = TextLength(text);
|
int textLength = TextLength(text);
|
||||||
|
|
||||||
int bytesProcessed = 0;
|
int bytesProcessed = 0;
|
||||||
int codepointsCount = 0;
|
int codepointCount = 0;
|
||||||
|
|
||||||
// Allocate a big enough buffer to store as many codepoints as text bytes
|
// Allocate a big enough buffer to store as many codepoints as text bytes
|
||||||
int *codepoints = RL_CALLOC(textLength, sizeof(int));
|
int *codepoints = RL_CALLOC(textLength, sizeof(int));
|
||||||
|
|
||||||
for (int i = 0; i < textLength; codepointsCount++)
|
for (int i = 0; i < textLength; codepointCount++)
|
||||||
{
|
{
|
||||||
codepoints[codepointsCount] = GetCodepoint(text + i, &bytesProcessed);
|
codepoints[codepointCount] = GetCodepoint(text + i, &bytesProcessed);
|
||||||
i += bytesProcessed;
|
i += bytesProcessed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-allocate buffer to the actual number of codepoints loaded
|
// Re-allocate buffer to the actual number of codepoints loaded
|
||||||
void *temp = RL_REALLOC(codepoints, codepointsCount*sizeof(int));
|
void *temp = RL_REALLOC(codepoints, codepointCount*sizeof(int));
|
||||||
if (temp != NULL) codepoints = temp;
|
if (temp != NULL) codepoints = temp;
|
||||||
|
|
||||||
*count = codepointsCount;
|
*count = codepointCount;
|
||||||
|
|
||||||
return codepoints;
|
return codepoints;
|
||||||
}
|
}
|
||||||
|
|
@ -1500,9 +1502,9 @@ void UnloadCodepoints(int *codepoints)
|
||||||
|
|
||||||
// Get total number of characters(codepoints) in a UTF-8 encoded text, until '\0' is found
|
// Get total number of characters(codepoints) in a UTF-8 encoded text, until '\0' is found
|
||||||
// NOTE: If an invalid UTF-8 sequence is encountered a '?'(0x3f) codepoint is counted instead
|
// NOTE: If an invalid UTF-8 sequence is encountered a '?'(0x3f) codepoint is counted instead
|
||||||
int GetCodepointsCount(const char *text)
|
int GetCodepointCount(const char *text)
|
||||||
{
|
{
|
||||||
unsigned int len = 0;
|
unsigned int length = 0;
|
||||||
char *ptr = (char *)&text[0];
|
char *ptr = (char *)&text[0];
|
||||||
|
|
||||||
while (*ptr != '\0')
|
while (*ptr != '\0')
|
||||||
|
|
@ -1513,19 +1515,18 @@ int GetCodepointsCount(const char *text)
|
||||||
if (letter == 0x3f) ptr += 1;
|
if (letter == 0x3f) ptr += 1;
|
||||||
else ptr += next;
|
else ptr += next;
|
||||||
|
|
||||||
len++;
|
length++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
return length;
|
||||||
}
|
}
|
||||||
#endif // SUPPORT_TEXT_MANIPULATION
|
#endif // SUPPORT_TEXT_MANIPULATION
|
||||||
|
|
||||||
// Get next codepoint in a UTF-8 encoded text, scanning until '\0' is found
|
// Get next codepoint in a UTF-8 encoded text, scanning until '\0' is found
|
||||||
// When a invalid UTF-8 byte is encountered we exit as soon as possible and a '?'(0x3f) codepoint is returned
|
// When a invalid UTF-8 byte is encountered we exit as soon as possible and a '?'(0x3f) codepoint is returned
|
||||||
// Total number of bytes processed are returned as a parameter
|
// Total number of bytes processed are returned as a parameter
|
||||||
// NOTE: the standard says U+FFFD should be returned in case of errors
|
// NOTE: The standard says U+FFFD should be returned in case of errors
|
||||||
// but that character is not supported by the default font in raylib
|
// but that character is not supported by the default font in raylib
|
||||||
// TODO: Optimize this code for speed!!
|
|
||||||
int GetCodepoint(const char *text, int *bytesProcessed)
|
int GetCodepoint(const char *text, int *bytesProcessed)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
|
@ -1657,7 +1658,7 @@ static Font LoadBMFont(const char *fileName)
|
||||||
char *searchPoint = NULL;
|
char *searchPoint = NULL;
|
||||||
|
|
||||||
int fontSize = 0;
|
int fontSize = 0;
|
||||||
int charsCount = 0;
|
int glyphCount = 0;
|
||||||
|
|
||||||
int imWidth = 0;
|
int imWidth = 0;
|
||||||
int imHeight = 0;
|
int imHeight = 0;
|
||||||
|
|
@ -1694,10 +1695,10 @@ static Font LoadBMFont(const char *fileName)
|
||||||
|
|
||||||
lineBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
|
lineBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
|
||||||
searchPoint = strstr(buffer, "count");
|
searchPoint = strstr(buffer, "count");
|
||||||
sscanf(searchPoint, "count=%i", &charsCount);
|
sscanf(searchPoint, "count=%i", &glyphCount);
|
||||||
fileTextPtr += (lineBytes + 1);
|
fileTextPtr += (lineBytes + 1);
|
||||||
|
|
||||||
TRACELOGD(" > Chars count: %i", charsCount);
|
TRACELOGD(" > Chars count: %i", glyphCount);
|
||||||
|
|
||||||
// Compose correct path using route of .fnt file (fileName) and imFileName
|
// Compose correct path using route of .fnt file (fileName) and imFileName
|
||||||
char *imPath = NULL;
|
char *imPath = NULL;
|
||||||
|
|
@ -1746,14 +1747,14 @@ static Font LoadBMFont(const char *fileName)
|
||||||
|
|
||||||
// Fill font characters info data
|
// Fill font characters info data
|
||||||
font.baseSize = fontSize;
|
font.baseSize = fontSize;
|
||||||
font.charsCount = charsCount;
|
font.glyphCount = glyphCount;
|
||||||
font.charsPadding = 0;
|
font.glyphPadding = 0;
|
||||||
font.chars = (GlyphInfo *)RL_MALLOC(charsCount*sizeof(GlyphInfo));
|
font.glyphs = (GlyphInfo *)RL_MALLOC(glyphCount*sizeof(GlyphInfo));
|
||||||
font.recs = (Rectangle *)RL_MALLOC(charsCount*sizeof(Rectangle));
|
font.recs = (Rectangle *)RL_MALLOC(glyphCount*sizeof(Rectangle));
|
||||||
|
|
||||||
int charId, charX, charY, charWidth, charHeight, charOffsetX, charOffsetY, charAdvanceX;
|
int charId, charX, charY, charWidth, charHeight, charOffsetX, charOffsetY, charAdvanceX;
|
||||||
|
|
||||||
for (int i = 0; i < charsCount; i++)
|
for (int i = 0; i < glyphCount; i++)
|
||||||
{
|
{
|
||||||
lineBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
|
lineBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
|
||||||
sscanf(buffer, "char id=%i x=%i y=%i width=%i height=%i xoffset=%i yoffset=%i xadvance=%i",
|
sscanf(buffer, "char id=%i x=%i y=%i width=%i height=%i xoffset=%i yoffset=%i xadvance=%i",
|
||||||
|
|
@ -1764,13 +1765,13 @@ static Font LoadBMFont(const char *fileName)
|
||||||
font.recs[i] = (Rectangle){ (float)charX, (float)charY, (float)charWidth, (float)charHeight };
|
font.recs[i] = (Rectangle){ (float)charX, (float)charY, (float)charWidth, (float)charHeight };
|
||||||
|
|
||||||
// Save data properly in sprite font
|
// Save data properly in sprite font
|
||||||
font.chars[i].value = charId;
|
font.glyphs[i].value = charId;
|
||||||
font.chars[i].offsetX = charOffsetX;
|
font.glyphs[i].offsetX = charOffsetX;
|
||||||
font.chars[i].offsetY = charOffsetY;
|
font.glyphs[i].offsetY = charOffsetY;
|
||||||
font.chars[i].advanceX = charAdvanceX;
|
font.glyphs[i].advanceX = charAdvanceX;
|
||||||
|
|
||||||
// Fill character image data from imFont data
|
// Fill character image data from imFont data
|
||||||
font.chars[i].image = ImageFromImage(imFont, font.recs[i]);
|
font.glyphs[i].image = ImageFromImage(imFont, font.recs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
UnloadImage(imFont);
|
UnloadImage(imFont);
|
||||||
|
|
@ -1782,7 +1783,7 @@ static Font LoadBMFont(const char *fileName)
|
||||||
font = GetFontDefault();
|
font = GetFontDefault();
|
||||||
TRACELOG(LOG_WARNING, "FONT: [%s] Failed to load texture, reverted to default font", fileName);
|
TRACELOG(LOG_WARNING, "FONT: [%s] Failed to load texture, reverted to default font", fileName);
|
||||||
}
|
}
|
||||||
else TRACELOG(LOG_INFO, "FONT: [%s] Font loaded successfully", fileName);
|
else TRACELOG(LOG_INFO, "FONT: [%s] Font loaded successfully (%i glyphs)", fileName, font.glyphCount);
|
||||||
|
|
||||||
return font;
|
return font;
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/**********************************************************************************************
|
/**********************************************************************************************
|
||||||
*
|
*
|
||||||
* raylib.textures - Basic functions to load and draw Textures (2d)
|
* rtextures - Basic functions to load and draw textures
|
||||||
*
|
*
|
||||||
* CONFIGURATION:
|
* CONFIGURATION:
|
||||||
*
|
*
|
||||||
|
|
@ -258,7 +258,7 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int
|
||||||
Image LoadImageAnim(const char *fileName, int *frames)
|
Image LoadImageAnim(const char *fileName, int *frames)
|
||||||
{
|
{
|
||||||
Image image = { 0 };
|
Image image = { 0 };
|
||||||
int framesCount = 1;
|
int frameCount = 1;
|
||||||
|
|
||||||
#if defined(SUPPORT_FILEFORMAT_GIF)
|
#if defined(SUPPORT_FILEFORMAT_GIF)
|
||||||
if (IsFileExtension(fileName, ".gif"))
|
if (IsFileExtension(fileName, ".gif"))
|
||||||
|
|
@ -269,8 +269,8 @@ Image LoadImageAnim(const char *fileName, int *frames)
|
||||||
if (fileData != NULL)
|
if (fileData != NULL)
|
||||||
{
|
{
|
||||||
int comp = 0;
|
int comp = 0;
|
||||||
int **delays = NULL;
|
int *delays = NULL;
|
||||||
image.data = stbi_load_gif_from_memory(fileData, dataSize, delays, &image.width, &image.height, &framesCount, &comp, 4);
|
image.data = stbi_load_gif_from_memory(fileData, dataSize, &delays, &image.width, &image.height, &frameCount, &comp, 4);
|
||||||
|
|
||||||
image.mipmaps = 1;
|
image.mipmaps = 1;
|
||||||
image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
|
image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
|
||||||
|
|
@ -286,7 +286,7 @@ Image LoadImageAnim(const char *fileName, int *frames)
|
||||||
|
|
||||||
// TODO: Support APNG animated images?
|
// TODO: Support APNG animated images?
|
||||||
|
|
||||||
*frames = framesCount;
|
*frames = frameCount;
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -518,19 +518,19 @@ bool ExportImageAsCode(Image image, const char *fileName)
|
||||||
|
|
||||||
// NOTE: Text data buffer size is estimated considering image data size in bytes
|
// NOTE: Text data buffer size is estimated considering image data size in bytes
|
||||||
// and requiring 6 char bytes for every byte: "0x00, "
|
// and requiring 6 char bytes for every byte: "0x00, "
|
||||||
char *txtData = (char *)RL_CALLOC(6*dataSize + 2000, sizeof(char));
|
char *txtData = (char *)RL_CALLOC(dataSize*6 + 2000, sizeof(char));
|
||||||
|
|
||||||
int bytesCount = 0;
|
int byteCount = 0;
|
||||||
bytesCount += sprintf(txtData + bytesCount, "////////////////////////////////////////////////////////////////////////////////////////\n");
|
byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "// //\n");
|
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "// ImageAsCode exporter v1.0 - Image pixel data exported as an array of bytes //\n");
|
byteCount += sprintf(txtData + byteCount, "// ImageAsCode exporter v1.0 - Image pixel data exported as an array of bytes //\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "// //\n");
|
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "// more info and bugs-report: github.com/raysan5/raylib //\n");
|
byteCount += sprintf(txtData + byteCount, "// more info and bugs-report: github.com/raysan5/raylib //\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "// feedback and support: ray[at]raylib.com //\n");
|
byteCount += sprintf(txtData + byteCount, "// feedback and support: ray[at]raylib.com //\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "// //\n");
|
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "// Copyright (c) 2020 Ramon Santamaria (@raysan5) //\n");
|
byteCount += sprintf(txtData + byteCount, "// Copyright (c) 2018-2021 Ramon Santamaria (@raysan5) //\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "// //\n");
|
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "////////////////////////////////////////////////////////////////////////////////////////\n\n");
|
byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n\n");
|
||||||
|
|
||||||
// Get file name from path and convert variable name to uppercase
|
// Get file name from path and convert variable name to uppercase
|
||||||
char varFileName[256] = { 0 };
|
char varFileName[256] = { 0 };
|
||||||
|
|
@ -538,16 +538,16 @@ bool ExportImageAsCode(Image image, const char *fileName)
|
||||||
for (int i = 0; varFileName[i] != '\0'; i++) if ((varFileName[i] >= 'a') && (varFileName[i] <= 'z')) { varFileName[i] = varFileName[i] - 32; }
|
for (int i = 0; varFileName[i] != '\0'; i++) if ((varFileName[i] >= 'a') && (varFileName[i] <= 'z')) { varFileName[i] = varFileName[i] - 32; }
|
||||||
|
|
||||||
// Add image information
|
// Add image information
|
||||||
bytesCount += sprintf(txtData + bytesCount, "// Image data information\n");
|
byteCount += sprintf(txtData + byteCount, "// Image data information\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "#define %s_WIDTH %i\n", varFileName, image.width);
|
byteCount += sprintf(txtData + byteCount, "#define %s_WIDTH %i\n", varFileName, image.width);
|
||||||
bytesCount += sprintf(txtData + bytesCount, "#define %s_HEIGHT %i\n", varFileName, image.height);
|
byteCount += sprintf(txtData + byteCount, "#define %s_HEIGHT %i\n", varFileName, image.height);
|
||||||
bytesCount += sprintf(txtData + bytesCount, "#define %s_FORMAT %i // raylib internal pixel format\n\n", varFileName, image.format);
|
byteCount += sprintf(txtData + byteCount, "#define %s_FORMAT %i // raylib internal pixel format\n\n", varFileName, image.format);
|
||||||
|
|
||||||
bytesCount += sprintf(txtData + bytesCount, "static unsigned char %s_DATA[%i] = { ", varFileName, dataSize);
|
byteCount += sprintf(txtData + byteCount, "static unsigned char %s_DATA[%i] = { ", varFileName, dataSize);
|
||||||
for (int i = 0; i < dataSize - 1; i++) bytesCount += sprintf(txtData + bytesCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%x,\n" : "0x%x, "), ((unsigned char *)image.data)[i]);
|
for (int i = 0; i < dataSize - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%x,\n" : "0x%x, "), ((unsigned char *)image.data)[i]);
|
||||||
bytesCount += sprintf(txtData + bytesCount, "0x%x };\n", ((unsigned char *)image.data)[dataSize - 1]);
|
byteCount += sprintf(txtData + byteCount, "0x%x };\n", ((unsigned char *)image.data)[dataSize - 1]);
|
||||||
|
|
||||||
// NOTE: Text data length exported is determined by '\0' (NULL) character
|
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
||||||
success = SaveFileText(fileName, txtData);
|
success = SaveFileText(fileName, txtData);
|
||||||
|
|
||||||
RL_FREE(txtData);
|
RL_FREE(txtData);
|
||||||
|
|
@ -765,11 +765,11 @@ Image GenImageCellular(int width, int height, int tileSize)
|
||||||
|
|
||||||
int seedsPerRow = width/tileSize;
|
int seedsPerRow = width/tileSize;
|
||||||
int seedsPerCol = height/tileSize;
|
int seedsPerCol = height/tileSize;
|
||||||
int seedsCount = seedsPerRow*seedsPerCol;
|
int seedCount = seedsPerRow*seedsPerCol;
|
||||||
|
|
||||||
Vector2 *seeds = (Vector2 *)RL_MALLOC(seedsCount*sizeof(Vector2));
|
Vector2 *seeds = (Vector2 *)RL_MALLOC(seedCount*sizeof(Vector2));
|
||||||
|
|
||||||
for (int i = 0; i < seedsCount; i++)
|
for (int i = 0; i < seedCount; i++)
|
||||||
{
|
{
|
||||||
int y = (i/seedsPerRow)*tileSize + GetRandomValue(0, tileSize - 1);
|
int y = (i/seedsPerRow)*tileSize + GetRandomValue(0, tileSize - 1);
|
||||||
int x = (i%seedsPerRow)*tileSize + GetRandomValue(0, tileSize - 1);
|
int x = (i%seedsPerRow)*tileSize + GetRandomValue(0, tileSize - 1);
|
||||||
|
|
@ -871,8 +871,6 @@ Image ImageFromImage(Image image, Rectangle rec)
|
||||||
|
|
||||||
int bytesPerPixel = GetPixelDataSize(1, 1, image.format);
|
int bytesPerPixel = GetPixelDataSize(1, 1, image.format);
|
||||||
|
|
||||||
// TODO: Check rec is valid?
|
|
||||||
|
|
||||||
result.width = (int)rec.width;
|
result.width = (int)rec.width;
|
||||||
result.height = (int)rec.height;
|
result.height = (int)rec.height;
|
||||||
result.data = RL_CALLOC((int)(rec.width*rec.height)*bytesPerPixel, 1);
|
result.data = RL_CALLOC((int)(rec.width*rec.height)*bytesPerPixel, 1);
|
||||||
|
|
@ -1147,7 +1145,7 @@ Image ImageText(const char *text, int fontSize, Color color)
|
||||||
// Create an image from text (custom sprite font)
|
// Create an image from text (custom sprite font)
|
||||||
Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Color tint)
|
Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Color tint)
|
||||||
{
|
{
|
||||||
int length = (int)strlen(text);
|
int size = (int)strlen(text); // Get size in bytes of text
|
||||||
|
|
||||||
int textOffsetX = 0; // Image drawing position X
|
int textOffsetX = 0; // Image drawing position X
|
||||||
int textOffsetY = 0; // Offset between lines (on line break '\n')
|
int textOffsetY = 0; // Offset between lines (on line break '\n')
|
||||||
|
|
@ -1158,7 +1156,7 @@ Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Co
|
||||||
// Create image to store text
|
// Create image to store text
|
||||||
Image imText = GenImageColor((int)imSize.x, (int)imSize.y, BLANK);
|
Image imText = GenImageColor((int)imSize.x, (int)imSize.y, BLANK);
|
||||||
|
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
// Get next codepoint from byte string and glyph index in font
|
// Get next codepoint from byte string and glyph index in font
|
||||||
int codepointByteCount = 0;
|
int codepointByteCount = 0;
|
||||||
|
|
@ -1180,12 +1178,12 @@ Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Co
|
||||||
{
|
{
|
||||||
if ((codepoint != ' ') && (codepoint != '\t'))
|
if ((codepoint != ' ') && (codepoint != '\t'))
|
||||||
{
|
{
|
||||||
Rectangle rec = { (float)(textOffsetX + font.chars[index].offsetX), (float)(textOffsetY + font.chars[index].offsetY), (float)font.recs[index].width, (float)font.recs[index].height };
|
Rectangle rec = { (float)(textOffsetX + font.glyphs[index].offsetX), (float)(textOffsetY + font.glyphs[index].offsetY), (float)font.recs[index].width, (float)font.recs[index].height };
|
||||||
ImageDraw(&imText, font.chars[index].image, (Rectangle){ 0, 0, (float)font.chars[index].image.width, (float)font.chars[index].image.height }, rec, tint);
|
ImageDraw(&imText, font.glyphs[index].image, (Rectangle){ 0, 0, (float)font.glyphs[index].image.width, (float)font.glyphs[index].image.height }, rec, tint);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (font.chars[index].advanceX == 0) textOffsetX += (int)(font.recs[index].width + spacing);
|
if (font.glyphs[index].advanceX == 0) textOffsetX += (int)(font.recs[index].width + spacing);
|
||||||
else textOffsetX += font.chars[index].advanceX + (int)spacing;
|
else textOffsetX += font.glyphs[index].advanceX + (int)spacing;
|
||||||
}
|
}
|
||||||
|
|
||||||
i += (codepointByteCount - 1); // Move text bytes counter to next codepoint
|
i += (codepointByteCount - 1); // Move text bytes counter to next codepoint
|
||||||
|
|
@ -2185,7 +2183,7 @@ Color *LoadImageColors(Image image)
|
||||||
|
|
||||||
// Load colors palette from image as a Color array (RGBA - 32bit)
|
// Load colors palette from image as a Color array (RGBA - 32bit)
|
||||||
// NOTE: Memory allocated should be freed using UnloadImagePalette()
|
// NOTE: Memory allocated should be freed using UnloadImagePalette()
|
||||||
Color *LoadImagePalette(Image image, int maxPaletteSize, int *colorsCount)
|
Color *LoadImagePalette(Image image, int maxPaletteSize, int *colorCount)
|
||||||
{
|
{
|
||||||
#define COLOR_EQUAL(col1, col2) ((col1.r == col2.r)&&(col1.g == col2.g)&&(col1.b == col2.b)&&(col1.a == col2.a))
|
#define COLOR_EQUAL(col1, col2) ((col1.r == col2.r)&&(col1.g == col2.g)&&(col1.b == col2.b)&&(col1.a == col2.a))
|
||||||
|
|
||||||
|
|
@ -2234,7 +2232,7 @@ Color *LoadImagePalette(Image image, int maxPaletteSize, int *colorsCount)
|
||||||
UnloadImageColors(pixels);
|
UnloadImageColors(pixels);
|
||||||
}
|
}
|
||||||
|
|
||||||
*colorsCount = palCount;
|
*colorCount = palCount;
|
||||||
|
|
||||||
return palette;
|
return palette;
|
||||||
}
|
}
|
||||||
|
|
@ -3487,9 +3485,9 @@ void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle dest,
|
||||||
// Draw textured polygon, defined by vertex and texturecoordinates
|
// Draw textured polygon, defined by vertex and texturecoordinates
|
||||||
// NOTE: Polygon center must have straight line path to all points
|
// NOTE: Polygon center must have straight line path to all points
|
||||||
// without crossing perimeter, points must be in anticlockwise order
|
// without crossing perimeter, points must be in anticlockwise order
|
||||||
void DrawTexturePoly(Texture2D texture, Vector2 center, Vector2 *points, Vector2 *texcoords, int pointsCount, Color tint)
|
void DrawTexturePoly(Texture2D texture, Vector2 center, Vector2 *points, Vector2 *texcoords, int pointCount, Color tint)
|
||||||
{
|
{
|
||||||
rlCheckRenderBatchLimit((pointsCount - 1)*4);
|
rlCheckRenderBatchLimit((pointCount - 1)*4);
|
||||||
|
|
||||||
rlSetTexture(texture.id);
|
rlSetTexture(texture.id);
|
||||||
|
|
||||||
|
|
@ -3498,7 +3496,7 @@ void DrawTexturePoly(Texture2D texture, Vector2 center, Vector2 *points, Vector2
|
||||||
|
|
||||||
rlColor4ub(tint.r, tint.g, tint.b, tint.a);
|
rlColor4ub(tint.r, tint.g, tint.b, tint.a);
|
||||||
|
|
||||||
for (int i = 0; i < pointsCount - 1; i++)
|
for (int i = 0; i < pointCount - 1; i++)
|
||||||
{
|
{
|
||||||
rlTexCoord2f(0.5f, 0.5f);
|
rlTexCoord2f(0.5f, 0.5f);
|
||||||
rlVertex2f(center.x, center.y);
|
rlVertex2f(center.x, center.y);
|
||||||
|
|
@ -192,7 +192,8 @@ jwE50AGjLCVuS8Yt4H7OgZLKK5EKOsLviEWJSL/+0uMi7gLUSBseYwqEbXvSHCec1CJvZPyHCmYQffaB
|
||||||
<script type='text/javascript'>
|
<script type='text/javascript'>
|
||||||
function saveFileFromMEMFSToDisk(memoryFSname, localFSname) // This can be called by C/C++ code
|
function saveFileFromMEMFSToDisk(memoryFSname, localFSname) // This can be called by C/C++ code
|
||||||
{
|
{
|
||||||
var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
var isSafari = false; // Not supported, navigator.userAgent access is being restricted
|
||||||
|
//var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
||||||
var data = FS.readFile(memoryFSname);
|
var data = FS.readFile(memoryFSname);
|
||||||
var blob;
|
var blob;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user