Merge branch 'master' into remove_platform_rpi
|
|
@ -24,6 +24,7 @@ Some people ported raylib to other languages in form of bindings or wrappers to
|
||||||
| rayex | 3.7 | [elixir](https://elixir-lang.org/) | Apache-2.0 | https://github.com/shiryel/rayex |
|
| rayex | 3.7 | [elixir](https://elixir-lang.org/) | Apache-2.0 | https://github.com/shiryel/rayex |
|
||||||
| raylib-factor | 4.0 | [Factor](https://factorcode.org/) | BSD | https://github.com/factor/factor/blob/master/extra/raylib/raylib.factor |
|
| raylib-factor | 4.0 | [Factor](https://factorcode.org/) | BSD | https://github.com/factor/factor/blob/master/extra/raylib/raylib.factor |
|
||||||
| raylib-freebasic | **4.5** | [FreeBASIC](https://www.freebasic.net/) | MIT | https://github.com/WIITD/raylib-freebasic |
|
| raylib-freebasic | **4.5** | [FreeBASIC](https://www.freebasic.net/) | MIT | https://github.com/WIITD/raylib-freebasic |
|
||||||
|
| fortran-raylib | **4.5** | [Fortran](https://fortran-lang.org/) | ISC | https://github.com/interkosmos/fortran-raylib |
|
||||||
| raylib for Pascal | **4.5** | [Object Pascal](https://en.wikipedia.org/wiki/Object_Pascal) | Modified Zlib | https://github.com/tinyBigGAMES/raylib |
|
| raylib for Pascal | **4.5** | [Object Pascal](https://en.wikipedia.org/wiki/Object_Pascal) | Modified Zlib | https://github.com/tinyBigGAMES/raylib |
|
||||||
| raylib-go | 4.5 | [Go](https://golang.org/) | Zlib | https://github.com/gen2brain/raylib-go |
|
| raylib-go | 4.5 | [Go](https://golang.org/) | Zlib | https://github.com/gen2brain/raylib-go |
|
||||||
| raylib-guile | **auto** | [Guile](https://www.gnu.org/software/guile/) | Zlib | https://github.com/petelliott/raylib-guile |
|
| raylib-guile | **auto** | [Guile](https://www.gnu.org/software/guile/) | Zlib | https://github.com/petelliott/raylib-guile |
|
||||||
|
|
|
||||||
|
|
@ -38,14 +38,15 @@ cmake_dependent_option(SUPPORT_MODULE_RAUDIO "Include module: raudio" ON CUSTOMI
|
||||||
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_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 (rgestures.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" 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)
|
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_SCREEN_CAPTURE "Allow automatic screen capture of current screen pressing F12, defined in KeyCallback()" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_SCREEN_CAPTURE "Allow automatic screen capture of current screen pressing F12, defined in KeyCallback()" ON CUSTOMIZE_BUILD ON)
|
||||||
cmake_dependent_option(SUPPORT_GIF_RECORDING "Allow automatic gif recording of current screen pressing CTRL+F12, defined in KeyCallback()" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_GIF_RECORDING "Allow automatic gif recording of current screen pressing CTRL+F12, defined in KeyCallback()" ON CUSTOMIZE_BUILD ON)
|
||||||
cmake_dependent_option(SUPPORT_BUSY_WAIT_LOOP "Use busy wait loop for timing sync instead of a high-resolution timer" OFF CUSTOMIZE_BUILD OFF)
|
cmake_dependent_option(SUPPORT_BUSY_WAIT_LOOP "Use busy wait loop for timing sync instead of a high-resolution timer" OFF CUSTOMIZE_BUILD OFF)
|
||||||
cmake_dependent_option(SUPPORT_EVENTS_WAITING "Wait for events passively (sleeping while no events) instead of polling them actively every frame" OFF CUSTOMIZE_BUILD OFF)
|
cmake_dependent_option(SUPPORT_EVENTS_WAITING "Wait for events passively (sleeping while no events) instead of polling them actively every frame" OFF CUSTOMIZE_BUILD OFF)
|
||||||
cmake_dependent_option(SUPPORT_WINMM_HIGHRES_TIMER "Setting a higher resolution can improve the accuracy of time-out intervals in wait functions" OFF CUSTOMIZE_BUILD OFF)
|
cmake_dependent_option(SUPPORT_WINMM_HIGHRES_TIMER "Setting a higher resolution can improve the accuracy of time-out intervals in wait functions" 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)
|
||||||
|
cmake_dependent_option(SUPPORT_EVENTS_AUTOMATION "Support automatic generated events, loading and recording of those events when required" OFF CUSTOMIZE_BUILD OFF)
|
||||||
cmake_dependent_option(SUPPORT_CUSTOM_FRAME_CONTROL "Enabling this flag allows manual control of the frame processes, use at your own risk" OFF CUSTOMIZE_BUILD OFF)
|
cmake_dependent_option(SUPPORT_CUSTOM_FRAME_CONTROL "Enabling this flag allows manual control of the frame processes, use at your own risk" OFF CUSTOMIZE_BUILD OFF)
|
||||||
|
|
||||||
# rshapes.c
|
# rshapes.c
|
||||||
|
|
@ -58,17 +59,19 @@ cmake_dependent_option(SUPPORT_IMAGE_MANIPULATION "Support multiple image editin
|
||||||
cmake_dependent_option(SUPPORT_FILEFORMAT_PNG "Support loading PNG as textures" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_FILEFORMAT_PNG "Support loading PNG as textures" ON CUSTOMIZE_BUILD ON)
|
||||||
cmake_dependent_option(SUPPORT_FILEFORMAT_DDS "Support loading DDS as textures" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_FILEFORMAT_DDS "Support loading DDS as textures" ON CUSTOMIZE_BUILD ON)
|
||||||
cmake_dependent_option(SUPPORT_FILEFORMAT_HDR "Support loading HDR as textures" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_FILEFORMAT_HDR "Support loading HDR as textures" ON CUSTOMIZE_BUILD ON)
|
||||||
cmake_dependent_option(SUPPORT_FILEFORMAT_PNM "Support loading PNM as textures" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_FILEFORMAT_PIC "Support loading PIC as textures" ${OFF} CUSTOMIZE_BUILD OFF)
|
||||||
cmake_dependent_option(SUPPORT_FILEFORMAT_KTX "Support loading KTX as textures" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_FILEFORMAT_PNM "Support loading PNM as textures" ${OFF} CUSTOMIZE_BUILD OFF)
|
||||||
cmake_dependent_option(SUPPORT_FILEFORMAT_ASTC "Support loading ASTC as textures" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_FILEFORMAT_KTX "Support loading KTX as textures" ${OFF} CUSTOMIZE_BUILD OFF)
|
||||||
|
cmake_dependent_option(SUPPORT_FILEFORMAT_ASTC "Support loading ASTC as textures" ${OFF} CUSTOMIZE_BUILD OFF)
|
||||||
cmake_dependent_option(SUPPORT_FILEFORMAT_BMP "Support loading BMP as textures" ${OFF} CUSTOMIZE_BUILD OFF)
|
cmake_dependent_option(SUPPORT_FILEFORMAT_BMP "Support loading BMP as textures" ${OFF} CUSTOMIZE_BUILD OFF)
|
||||||
cmake_dependent_option(SUPPORT_FILEFORMAT_TGA "Support loading TGA as textures" ${OFF} CUSTOMIZE_BUILD OFF)
|
cmake_dependent_option(SUPPORT_FILEFORMAT_TGA "Support loading TGA as textures" ${OFF} CUSTOMIZE_BUILD OFF)
|
||||||
cmake_dependent_option(SUPPORT_FILEFORMAT_JPG "Support loading JPG as textures" ${OFF} CUSTOMIZE_BUILD OFF)
|
cmake_dependent_option(SUPPORT_FILEFORMAT_JPG "Support loading JPG as textures" ${OFF} CUSTOMIZE_BUILD OFF)
|
||||||
cmake_dependent_option(SUPPORT_FILEFORMAT_GIF "Support loading GIF as textures" ${OFF} CUSTOMIZE_BUILD OFF)
|
cmake_dependent_option(SUPPORT_FILEFORMAT_GIF "Support loading GIF as textures" ON CUSTOMIZE_BUILD ON)
|
||||||
cmake_dependent_option(SUPPORT_FILEFORMAT_QOI "Support loading QOI as textures" ${OFF} CUSTOMIZE_BUILD OFF)
|
cmake_dependent_option(SUPPORT_FILEFORMAT_QOI "Support loading QOI as textures" ON CUSTOMIZE_BUILD ON)
|
||||||
cmake_dependent_option(SUPPORT_FILEFORMAT_PSD "Support loading PSD as textures" ${OFF} CUSTOMIZE_BUILD OFF)
|
cmake_dependent_option(SUPPORT_FILEFORMAT_PSD "Support loading PSD 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_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)
|
||||||
|
cmake_dependent_option(SUPPORT_FILEFORMAT_SVG "Support loading SVG as textures" ${OFF} CUSTOMIZE_BUILD OFF)
|
||||||
|
|
||||||
# rtext.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)
|
||||||
|
|
@ -83,6 +86,7 @@ cmake_dependent_option(SUPPORT_FILEFORMAT_MTL "Support loading MTL file format"
|
||||||
cmake_dependent_option(SUPPORT_FILEFORMAT_IQM "Support loading IQM file format" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_FILEFORMAT_IQM "Support loading IQM file format" ON CUSTOMIZE_BUILD ON)
|
||||||
cmake_dependent_option(SUPPORT_FILEFORMAT_GLTF "Support loading GLTF file format" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_FILEFORMAT_GLTF "Support loading GLTF file format" ON CUSTOMIZE_BUILD ON)
|
||||||
cmake_dependent_option(SUPPORT_FILEFORMAT_VOX "Support loading VOX file format" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_FILEFORMAT_VOX "Support loading VOX file format" ON CUSTOMIZE_BUILD ON)
|
||||||
|
cmake_dependent_option(SUPPORT_FILEFORMAT_M3D "Support loading M3D file format" ON CUSTOMIZE_BUILD ON)
|
||||||
|
|
||||||
# raudio.c
|
# raudio.c
|
||||||
cmake_dependent_option(SUPPORT_FILEFORMAT_WAV "Support loading WAV for sound" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_FILEFORMAT_WAV "Support loading WAV for sound" ON CUSTOMIZE_BUILD ON)
|
||||||
|
|
@ -90,6 +94,7 @@ cmake_dependent_option(SUPPORT_FILEFORMAT_OGG "Support loading OGG for sound" O
|
||||||
cmake_dependent_option(SUPPORT_FILEFORMAT_XM "Support loading XM for sound" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_FILEFORMAT_XM "Support loading XM for sound" ON CUSTOMIZE_BUILD ON)
|
||||||
cmake_dependent_option(SUPPORT_FILEFORMAT_MOD "Support loading MOD for sound" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_FILEFORMAT_MOD "Support loading MOD for sound" ON CUSTOMIZE_BUILD ON)
|
||||||
cmake_dependent_option(SUPPORT_FILEFORMAT_MP3 "Support loading MP3 for sound" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_FILEFORMAT_MP3 "Support loading MP3 for sound" ON CUSTOMIZE_BUILD ON)
|
||||||
|
cmake_dependent_option(SUPPORT_FILEFORMAT_QOA "Support loading QOA for sound" ON CUSTOMIZE_BUILD ON)
|
||||||
cmake_dependent_option(SUPPORT_FILEFORMAT_FLAC "Support loading FLAC for sound" ${OFF} CUSTOMIZE_BUILD OFF)
|
cmake_dependent_option(SUPPORT_FILEFORMAT_FLAC "Support loading FLAC for sound" ${OFF} CUSTOMIZE_BUILD OFF)
|
||||||
|
|
||||||
# utils.c
|
# utils.c
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
**raylib is a simple and easy-to-use library to enjoy videogames programming.**
|
**raylib is a simple and easy-to-use library to enjoy videogames programming.**
|
||||||
|
|
||||||
raylib is highly inspired by Borland BGI graphics lib and by XNA framework and it's specially well suited for prototyping, tooling, graphical applications, embedded systems and education.
|
raylib is highly inspired by Borland BGI graphics lib and by XNA framework and it's especially well suited for prototyping, tooling, graphical applications, embedded systems and education.
|
||||||
|
|
||||||
*NOTE for ADVENTURERS: raylib is a programming library to enjoy videogames programming; no fancy interface, no visual helpers, no debug button... just coding in the most pure spartan-programmers way.*
|
*NOTE for ADVENTURERS: raylib is a programming library to enjoy videogames programming; no fancy interface, no visual helpers, no debug button... just coding in the most pure spartan-programmers way.*
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ if (${CUSTOMIZE_BUILD})
|
||||||
define_if("raylib" SUPPORT_EVENTS_WAITING)
|
define_if("raylib" SUPPORT_EVENTS_WAITING)
|
||||||
define_if("raylib" SUPPORT_WINMM_HIGHRES_TIMER)
|
define_if("raylib" SUPPORT_WINMM_HIGHRES_TIMER)
|
||||||
define_if("raylib" SUPPORT_COMPRESSION_API)
|
define_if("raylib" SUPPORT_COMPRESSION_API)
|
||||||
|
define_if("raylib" SUPPORT_EVENTS_AUTOMATION)
|
||||||
define_if("raylib" SUPPORT_CUSTOM_FRAME_CONTROL)
|
define_if("raylib" SUPPORT_CUSTOM_FRAME_CONTROL)
|
||||||
define_if("raylib" SUPPORT_QUADS_DRAW_MODE)
|
define_if("raylib" SUPPORT_QUADS_DRAW_MODE)
|
||||||
define_if("raylib" SUPPORT_IMAGE_EXPORT)
|
define_if("raylib" SUPPORT_IMAGE_EXPORT)
|
||||||
|
|
@ -36,6 +37,7 @@ if (${CUSTOMIZE_BUILD})
|
||||||
define_if("raylib" SUPPORT_FILEFORMAT_PNG)
|
define_if("raylib" SUPPORT_FILEFORMAT_PNG)
|
||||||
define_if("raylib" SUPPORT_FILEFORMAT_DDS)
|
define_if("raylib" SUPPORT_FILEFORMAT_DDS)
|
||||||
define_if("raylib" SUPPORT_FILEFORMAT_HDR)
|
define_if("raylib" SUPPORT_FILEFORMAT_HDR)
|
||||||
|
define_if("raylib" SUPPORT_FILEFORMAT_PIC)
|
||||||
define_if("raylib" SUPPORT_FILEFORMAT_PNM)
|
define_if("raylib" SUPPORT_FILEFORMAT_PNM)
|
||||||
define_if("raylib" SUPPORT_FILEFORMAT_KTX)
|
define_if("raylib" SUPPORT_FILEFORMAT_KTX)
|
||||||
define_if("raylib" SUPPORT_FILEFORMAT_ASTC)
|
define_if("raylib" SUPPORT_FILEFORMAT_ASTC)
|
||||||
|
|
@ -47,6 +49,7 @@ if (${CUSTOMIZE_BUILD})
|
||||||
define_if("raylib" SUPPORT_FILEFORMAT_PSD)
|
define_if("raylib" SUPPORT_FILEFORMAT_PSD)
|
||||||
define_if("raylib" SUPPORT_FILEFORMAT_PKM)
|
define_if("raylib" SUPPORT_FILEFORMAT_PKM)
|
||||||
define_if("raylib" SUPPORT_FILEFORMAT_PVR)
|
define_if("raylib" SUPPORT_FILEFORMAT_PVR)
|
||||||
|
define_if("raylib" SUPPORT_FILEFORMAT_SVG)
|
||||||
define_if("raylib" SUPPORT_FILEFORMAT_FNT)
|
define_if("raylib" SUPPORT_FILEFORMAT_FNT)
|
||||||
define_if("raylib" SUPPORT_FILEFORMAT_TTF)
|
define_if("raylib" SUPPORT_FILEFORMAT_TTF)
|
||||||
define_if("raylib" SUPPORT_TEXT_MANIPULATION)
|
define_if("raylib" SUPPORT_TEXT_MANIPULATION)
|
||||||
|
|
@ -56,11 +59,13 @@ if (${CUSTOMIZE_BUILD})
|
||||||
define_if("raylib" SUPPORT_FILEFORMAT_IQM)
|
define_if("raylib" SUPPORT_FILEFORMAT_IQM)
|
||||||
define_if("raylib" SUPPORT_FILEFORMAT_GLTF)
|
define_if("raylib" SUPPORT_FILEFORMAT_GLTF)
|
||||||
define_if("raylib" SUPPORT_FILEFORMAT_VOX)
|
define_if("raylib" SUPPORT_FILEFORMAT_VOX)
|
||||||
|
define_if("raylib" SUPPORT_FILEFORMAT_M3D)
|
||||||
define_if("raylib" SUPPORT_FILEFORMAT_WAV)
|
define_if("raylib" SUPPORT_FILEFORMAT_WAV)
|
||||||
define_if("raylib" SUPPORT_FILEFORMAT_OGG)
|
define_if("raylib" SUPPORT_FILEFORMAT_OGG)
|
||||||
define_if("raylib" SUPPORT_FILEFORMAT_XM)
|
define_if("raylib" SUPPORT_FILEFORMAT_XM)
|
||||||
define_if("raylib" SUPPORT_FILEFORMAT_MOD)
|
define_if("raylib" SUPPORT_FILEFORMAT_MOD)
|
||||||
define_if("raylib" SUPPORT_FILEFORMAT_MP3)
|
define_if("raylib" SUPPORT_FILEFORMAT_MP3)
|
||||||
|
define_if("raylib" SUPPORT_FILEFORMAT_QOA)
|
||||||
define_if("raylib" SUPPORT_FILEFORMAT_FLAC)
|
define_if("raylib" SUPPORT_FILEFORMAT_FLAC)
|
||||||
define_if("raylib" SUPPORT_STANDARD_FILEIO)
|
define_if("raylib" SUPPORT_STANDARD_FILEIO)
|
||||||
define_if("raylib" SUPPORT_TRACELOG)
|
define_if("raylib" SUPPORT_TRACELOG)
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,7 @@ install(
|
||||||
# PKG_CONFIG_LIBS_PRIVATE is used in raylib.pc.in
|
# PKG_CONFIG_LIBS_PRIVATE is used in raylib.pc.in
|
||||||
if (NOT BUILD_SHARED_LIBS)
|
if (NOT BUILD_SHARED_LIBS)
|
||||||
include(LibraryPathToLinkerFlags)
|
include(LibraryPathToLinkerFlags)
|
||||||
library_path_to_linker_flags(__PKG_CONFIG_LIBS_PRIVATE "${LIBS_PRIVATE}")
|
set(PKG_CONFIG_LIBS_PRIVATE ${GLFW_PKG_LIBS})
|
||||||
set(PKG_CONFIG_LIBS_PRIVATE ${__PKG_CONFIG_LIBS_PRIVATE} ${GLFW_PKG_LIBS})
|
|
||||||
string(REPLACE ";" " " PKG_CONFIG_LIBS_PRIVATE "${PKG_CONFIG_LIBS_PRIVATE}")
|
string(REPLACE ";" " " PKG_CONFIG_LIBS_PRIVATE "${PKG_CONFIG_LIBS_PRIVATE}")
|
||||||
elseif (BUILD_SHARED_LIBS)
|
elseif (BUILD_SHARED_LIBS)
|
||||||
set(PKG_CONFIG_LIBS_EXTRA "")
|
set(PKG_CONFIG_LIBS_EXTRA "")
|
||||||
|
|
|
||||||
|
|
@ -228,6 +228,11 @@ ifeq ($(PLATFORM),PLATFORM_DRM)
|
||||||
INCLUDE_PATHS += -I/usr/include/libdrm
|
INCLUDE_PATHS += -I/usr/include/libdrm
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Include GLFW required for examples/others/rlgl_standalone.c
|
||||||
|
ifeq ($(USE_EXTERNAL_GLFW),FALSE)
|
||||||
|
all others: INCLUDE_PATHS += -I$(RAYLIB_PATH)/src/external/glfw/include
|
||||||
|
endif
|
||||||
|
|
||||||
# Define library paths containing required libs: LDFLAGS
|
# Define library paths containing required libs: LDFLAGS
|
||||||
#------------------------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------------------------
|
||||||
LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src
|
LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src
|
||||||
|
|
@ -426,7 +431,8 @@ TEXTURES = \
|
||||||
textures/textures_draw_tiled \
|
textures/textures_draw_tiled \
|
||||||
textures/textures_polygon \
|
textures/textures_polygon \
|
||||||
textures/textures_gif_player \
|
textures/textures_gif_player \
|
||||||
textures/textures_fog_of_war
|
textures/textures_fog_of_war \
|
||||||
|
textures/textures_svg_loading
|
||||||
|
|
||||||
TEXT = \
|
TEXT = \
|
||||||
text/text_raylib_fonts \
|
text/text_raylib_fonts \
|
||||||
|
|
@ -480,6 +486,7 @@ SHADERS = \
|
||||||
shaders/shaders_simple_mask \
|
shaders/shaders_simple_mask \
|
||||||
shaders/shaders_spotlight \
|
shaders/shaders_spotlight \
|
||||||
shaders/shaders_hot_reloading \
|
shaders/shaders_hot_reloading \
|
||||||
|
shaders/shaders_lightmap \
|
||||||
shaders/shaders_mesh_instancing \
|
shaders/shaders_mesh_instancing \
|
||||||
shaders/shaders_multi_sample2d \
|
shaders/shaders_multi_sample2d \
|
||||||
shaders/shaders_write_depth \
|
shaders/shaders_write_depth \
|
||||||
|
|
|
||||||
|
|
@ -406,7 +406,8 @@ TEXTURES = \
|
||||||
textures/textures_draw_tiled \
|
textures/textures_draw_tiled \
|
||||||
textures/textures_polygon \
|
textures/textures_polygon \
|
||||||
textures/textures_gif_player \
|
textures/textures_gif_player \
|
||||||
textures/textures_fog_of_war
|
textures/textures_fog_of_war \
|
||||||
|
textures/textures_svg_loading
|
||||||
|
|
||||||
TEXT = \
|
TEXT = \
|
||||||
text/text_raylib_fonts \
|
text/text_raylib_fonts \
|
||||||
|
|
@ -460,6 +461,7 @@ SHADERS = \
|
||||||
shaders/shaders_simple_mask \
|
shaders/shaders_simple_mask \
|
||||||
shaders/shaders_spotlight \
|
shaders/shaders_spotlight \
|
||||||
shaders/shaders_hot_reloading \
|
shaders/shaders_hot_reloading \
|
||||||
|
shaders/shaders_lightmap \
|
||||||
shaders/shaders_mesh_instancing \
|
shaders/shaders_mesh_instancing \
|
||||||
shaders/shaders_multi_sample2d \
|
shaders/shaders_multi_sample2d \
|
||||||
shaders/shaders_write_depth \
|
shaders/shaders_write_depth \
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,7 @@ int main(void)
|
||||||
{
|
{
|
||||||
StopMusicStream(music);
|
StopMusicStream(music);
|
||||||
PlayMusicStream(music);
|
PlayMusicStream(music);
|
||||||
|
pause = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pause/Resume music playing
|
// Pause/Resume music playing
|
||||||
|
|
@ -134,6 +135,14 @@ int main(void)
|
||||||
DrawRectangle(20, screenHeight - 20 - 12, (int)timePlayed, 12, MAROON);
|
DrawRectangle(20, screenHeight - 20 - 12, (int)timePlayed, 12, MAROON);
|
||||||
DrawRectangleLines(20, screenHeight - 20 - 12, screenWidth - 40, 12, GRAY);
|
DrawRectangleLines(20, screenHeight - 20 - 12, screenWidth - 40, 12, GRAY);
|
||||||
|
|
||||||
|
// Draw help instructions
|
||||||
|
DrawRectangle(20, 20, 425, 145, WHITE);
|
||||||
|
DrawRectangleLines(20, 20, 425, 145, GRAY);
|
||||||
|
DrawText("PRESS SPACE TO RESTART MUSIC", 40, 40, 20, BLACK);
|
||||||
|
DrawText("PRESS P TO PAUSE/RESUME", 40, 70, 20, BLACK);
|
||||||
|
DrawText("PRESS UP/DOWN TO CHANGE SPEED", 40, 100, 20, BLACK);
|
||||||
|
DrawText(TextFormat("SPEED: %f", pitch), 40, 130, 20, MAROON);
|
||||||
|
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 44 KiB |
BIN
examples/audio/audio_sound_multi.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
|
@ -63,8 +63,8 @@ int main(void)
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
UpdateCamera(&camera, CAMERA_THIRD_PERSON);
|
UpdateCamera(&camera, CAMERA_THIRD_PERSON);
|
||||||
// Select current animation
|
// Select current animation
|
||||||
if (IsKeyPressed(KEY_UP)) animIndex = (animIndex + 1)%animsCount;
|
if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT)) animIndex = (animIndex + 1)%animsCount;
|
||||||
else if (IsKeyPressed(KEY_DOWN)) animIndex = (animIndex + animsCount - 1)%animsCount;
|
else if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) animIndex = (animIndex + animsCount - 1)%animsCount;
|
||||||
|
|
||||||
// Update model animation
|
// Update model animation
|
||||||
ModelAnimation anim = modelAnimations[animIndex];
|
ModelAnimation anim = modelAnimations[animIndex];
|
||||||
|
|
@ -85,7 +85,7 @@ int main(void)
|
||||||
|
|
||||||
EndMode3D();
|
EndMode3D();
|
||||||
|
|
||||||
DrawText("Use the UP/DOWN arrow keys to switch animation", 10, 10, 20, GRAY);
|
DrawText("Use the LEFT/RIGHT mouse buttons to switch animation", 10, 10, 20, GRAY);
|
||||||
DrawText(TextFormat("Animation: %s", anim.name), 10, GetScreenHeight() - 20, 10, DARKGRAY);
|
DrawText(TextFormat("Animation: %s", anim.name), 10, GetScreenHeight() - 20, 10, DARKGRAY);
|
||||||
|
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 26 KiB |
|
|
@ -79,8 +79,8 @@ int main(void)
|
||||||
animPlaying = true;
|
animPlaying = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select animation by pressing A
|
// Select animation by pressing C
|
||||||
if (IsKeyPressed(KEY_A))
|
if (IsKeyPressed(KEY_C))
|
||||||
{
|
{
|
||||||
animFrameCounter = 0;
|
animFrameCounter = 0;
|
||||||
animId++;
|
animId++;
|
||||||
|
|
@ -92,7 +92,7 @@ int main(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle skeleton drawing
|
// Toggle skeleton drawing
|
||||||
if (IsKeyPressed(KEY_S)) drawSkeleton ^= 1;
|
if (IsKeyPressed(KEY_B)) drawSkeleton ^= 1;
|
||||||
|
|
||||||
// Toggle mesh drawing
|
// Toggle mesh drawing
|
||||||
if (IsKeyPressed(KEY_M)) drawMesh ^= 1;
|
if (IsKeyPressed(KEY_M)) drawMesh ^= 1;
|
||||||
|
|
@ -149,9 +149,10 @@ int main(void)
|
||||||
|
|
||||||
EndMode3D();
|
EndMode3D();
|
||||||
|
|
||||||
DrawText("PRESS SPACE to PLAY MODEL ANIMATION", 10, GetScreenHeight() - 60, 10, MAROON);
|
DrawText("PRESS SPACE to PLAY MODEL ANIMATION", 10, GetScreenHeight() - 80, 10, MAROON);
|
||||||
DrawText("PRESS A to CYCLE THROUGH ANIMATIONS", 10, GetScreenHeight() - 40, 10, DARKGRAY);
|
DrawText("PRESS N to STEP ONE ANIMATION FRAME", 10, GetScreenHeight() - 60, 10, DARKGRAY);
|
||||||
DrawText("PRESS M to toggle MESH, S to toggle SKELETON DRAWING", 10, GetScreenHeight() - 20, 10, DARKGRAY);
|
DrawText("PRESS C to CYCLE THROUGH ANIMATIONS", 10, GetScreenHeight() - 40, 10, DARKGRAY);
|
||||||
|
DrawText("PRESS M to toggle MESH, B to toggle SKELETON DRAWING", 10, GetScreenHeight() - 20, 10, DARKGRAY);
|
||||||
DrawText("(c) CesiumMan model by KhronosGroup", GetScreenWidth() - 210, GetScreenHeight() - 20, 10, GRAY);
|
DrawText("(c) CesiumMan model by KhronosGroup", GetScreenWidth() - 210, GetScreenHeight() - 20, 10, GRAY);
|
||||||
|
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 25 KiB |
|
|
@ -108,7 +108,7 @@ int main(void)
|
||||||
|
|
||||||
InitWindow(screenWidth, screenHeight, "raylib [easings] example - easings testbed");
|
InitWindow(screenWidth, screenHeight, "raylib [easings] example - easings testbed");
|
||||||
|
|
||||||
Vector2 ballPosition = { 100.0f, 200.0f };
|
Vector2 ballPosition = { 100.0f, 100.0f };
|
||||||
|
|
||||||
float t = 0.0f; // Current time (in any unit measure, but same unit as duration)
|
float t = 0.0f; // Current time (in any unit measure, but same unit as duration)
|
||||||
float d = 300.0f; // Total time it should take to complete (duration)
|
float d = 300.0f; // Total time it should take to complete (duration)
|
||||||
|
|
@ -180,8 +180,8 @@ int main(void)
|
||||||
// Movement computation
|
// Movement computation
|
||||||
if (!paused && ((boundedT && t < d) || !boundedT))
|
if (!paused && ((boundedT && t < d) || !boundedT))
|
||||||
{
|
{
|
||||||
ballPosition.x = Easings[easingX].func(t, 100.0f, 700.0f - 100.0f, d);
|
ballPosition.x = Easings[easingX].func(t, 100.0f, 700.0f - 170.0f, d);
|
||||||
ballPosition.y = Easings[easingY].func(t, 100.0f, 400.0f - 100.0f, d);
|
ballPosition.y = Easings[easingY].func(t, 100.0f, 400.0f - 170.0f, d);
|
||||||
t += 1.0f;
|
t += 1.0f;
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
@ -193,15 +193,15 @@ int main(void)
|
||||||
ClearBackground(RAYWHITE);
|
ClearBackground(RAYWHITE);
|
||||||
|
|
||||||
// Draw information text
|
// Draw information text
|
||||||
DrawText(TextFormat("Easing x: %s", Easings[easingX].name), 0, FONT_SIZE*2, FONT_SIZE, LIGHTGRAY);
|
DrawText(TextFormat("Easing x: %s", Easings[easingX].name), 20, FONT_SIZE, FONT_SIZE, LIGHTGRAY);
|
||||||
DrawText(TextFormat("Easing y: %s", Easings[easingY].name), 0, FONT_SIZE*3, FONT_SIZE, LIGHTGRAY);
|
DrawText(TextFormat("Easing y: %s", Easings[easingY].name), 20, FONT_SIZE*2, FONT_SIZE, LIGHTGRAY);
|
||||||
DrawText(TextFormat("t (%c) = %.2f d = %.2f", (boundedT == true)? 'b' : 'u', t, d), 0, FONT_SIZE*4, FONT_SIZE, LIGHTGRAY);
|
DrawText(TextFormat("t (%c) = %.2f d = %.2f", (boundedT == true)? 'b' : 'u', t, d), 20, FONT_SIZE*3, FONT_SIZE, LIGHTGRAY);
|
||||||
|
|
||||||
// Draw instructions text
|
// Draw instructions text
|
||||||
DrawText("Use ENTER to play or pause movement, use SPACE to restart", 0, GetScreenHeight() - FONT_SIZE*2, FONT_SIZE, LIGHTGRAY);
|
DrawText("Use ENTER to play or pause movement, use SPACE to restart", 20, GetScreenHeight() - FONT_SIZE*2, FONT_SIZE, LIGHTGRAY);
|
||||||
DrawText("Use D and W or A and S keys to change duration", 0, GetScreenHeight() - FONT_SIZE*3, FONT_SIZE, LIGHTGRAY);
|
DrawText("Use Q and W or A and S keys to change duration", 20, GetScreenHeight() - FONT_SIZE*3, FONT_SIZE, LIGHTGRAY);
|
||||||
DrawText("Use LEFT or RIGHT keys to choose easing for the x axis", 0, GetScreenHeight() - FONT_SIZE*4, FONT_SIZE, LIGHTGRAY);
|
DrawText("Use LEFT or RIGHT keys to choose easing for the x axis", 20, GetScreenHeight() - FONT_SIZE*4, FONT_SIZE, LIGHTGRAY);
|
||||||
DrawText("Use UP or DOWN keys to choose easing for the y axis", 0, GetScreenHeight() - FONT_SIZE*5, FONT_SIZE, LIGHTGRAY);
|
DrawText("Use UP or DOWN keys to choose easing for the y axis", 20, GetScreenHeight() - FONT_SIZE*5, FONT_SIZE, LIGHTGRAY);
|
||||||
|
|
||||||
// Draw ball
|
// Draw ball
|
||||||
DrawCircleV(ballPosition, 16.0f, MAROON);
|
DrawCircleV(ballPosition, 16.0f, MAROON);
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
|
@ -10,7 +10,7 @@ varying vec4 fragColor;
|
||||||
uniform sampler2D texture0;
|
uniform sampler2D texture0;
|
||||||
uniform vec4 colDiffuse;
|
uniform vec4 colDiffuse;
|
||||||
|
|
||||||
uniform float secondes;
|
uniform float seconds;
|
||||||
|
|
||||||
uniform vec2 size;
|
uniform vec2 size;
|
||||||
|
|
||||||
|
|
@ -29,8 +29,8 @@ void main() {
|
||||||
float boxTop = 0.0;
|
float boxTop = 0.0;
|
||||||
|
|
||||||
vec2 p = fragTexCoord;
|
vec2 p = fragTexCoord;
|
||||||
p.x += cos((fragTexCoord.y - boxTop) * freqX / ( pixelWidth * 750.0) + (secondes * speedX)) * ampX * pixelWidth;
|
p.x += cos((fragTexCoord.y - boxTop) * freqX / ( pixelWidth * 750.0) + (seconds * speedX)) * ampX * pixelWidth;
|
||||||
p.y += sin((fragTexCoord.x - boxLeft) * freqY * aspect / ( pixelHeight * 750.0) + (secondes * speedY)) * ampY * pixelHeight;
|
p.y += sin((fragTexCoord.x - boxLeft) * freqY * aspect / ( pixelHeight * 750.0) + (seconds * speedY)) * ampY * pixelHeight;
|
||||||
|
|
||||||
gl_FragColor = texture2D(texture0, p)*colDiffuse*fragColor;
|
gl_FragColor = texture2D(texture0, p)*colDiffuse*fragColor;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ uniform vec4 colDiffuse;
|
||||||
// Output fragment color
|
// Output fragment color
|
||||||
out vec4 finalColor;
|
out vec4 finalColor;
|
||||||
|
|
||||||
uniform float secondes;
|
uniform float seconds;
|
||||||
|
|
||||||
uniform vec2 size;
|
uniform vec2 size;
|
||||||
|
|
||||||
|
|
@ -30,8 +30,8 @@ void main() {
|
||||||
float boxTop = 0.0;
|
float boxTop = 0.0;
|
||||||
|
|
||||||
vec2 p = fragTexCoord;
|
vec2 p = fragTexCoord;
|
||||||
p.x += cos((fragTexCoord.y - boxTop) * freqX / ( pixelWidth * 750.0) + (secondes * speedX)) * ampX * pixelWidth;
|
p.x += cos((fragTexCoord.y - boxTop) * freqX / ( pixelWidth * 750.0) + (seconds * speedX)) * ampX * pixelWidth;
|
||||||
p.y += sin((fragTexCoord.x - boxLeft) * freqY * aspect / ( pixelHeight * 750.0) + (secondes * speedY)) * ampY * pixelHeight;
|
p.y += sin((fragTexCoord.x - boxLeft) * freqY * aspect / ( pixelHeight * 750.0) + (seconds * speedY)) * ampY * pixelHeight;
|
||||||
|
|
||||||
finalColor = texture(texture0, p)*colDiffuse*fragColor;
|
finalColor = texture(texture0, p)*colDiffuse*fragColor;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ int main(void)
|
||||||
EndShaderMode();
|
EndShaderMode();
|
||||||
|
|
||||||
DrawText("Shader-based\ntexture\noutline", 10, 10, 20, GRAY);
|
DrawText("Shader-based\ntexture\noutline", 10, 10, 20, GRAY);
|
||||||
|
DrawText("Scroll mouse wheel to\nchange outline size", 10, 72, 20, GRAY);
|
||||||
DrawText(TextFormat("Outline size: %i px", (int)outlineSize), 10, 120, 20, MAROON);
|
DrawText(TextFormat("Outline size: %i px", (int)outlineSize), 10, 120, 20, MAROON);
|
||||||
|
|
||||||
DrawFPS(710, 10);
|
DrawFPS(710, 10);
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 258 KiB After Width: | Height: | Size: 258 KiB |
|
|
@ -46,7 +46,7 @@ int main(void)
|
||||||
// Load shader and setup location points and values
|
// Load shader and setup location points and values
|
||||||
Shader shader = LoadShader(0, TextFormat("resources/shaders/glsl%i/wave.fs", GLSL_VERSION));
|
Shader shader = LoadShader(0, TextFormat("resources/shaders/glsl%i/wave.fs", GLSL_VERSION));
|
||||||
|
|
||||||
int secondsLoc = GetShaderLocation(shader, "secondes");
|
int secondsLoc = GetShaderLocation(shader, "seconds");
|
||||||
int freqXLoc = GetShaderLocation(shader, "freqX");
|
int freqXLoc = GetShaderLocation(shader, "freqX");
|
||||||
int freqYLoc = GetShaderLocation(shader, "freqY");
|
int freqYLoc = GetShaderLocation(shader, "freqY");
|
||||||
int ampXLoc = GetShaderLocation(shader, "ampX");
|
int ampXLoc = GetShaderLocation(shader, "ampX");
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,9 @@ int main(void)
|
||||||
DrawText(TextFormat("Collision Area: %i", (int)boxCollision.width*(int)boxCollision.height), GetScreenWidth()/2 - 100, screenUpperLimit + 10, 20, BLACK);
|
DrawText(TextFormat("Collision Area: %i", (int)boxCollision.width*(int)boxCollision.height), GetScreenWidth()/2 - 100, screenUpperLimit + 10, 20, BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw help instructions
|
||||||
|
DrawText("Press SPACE to PAUSE/RESUME", 20, screenHeight - 35, 20, LIGHTGRAY);
|
||||||
|
|
||||||
DrawFPS(10, 10);
|
DrawFPS(10, 10);
|
||||||
|
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
|
@ -52,6 +52,8 @@ int main(void)
|
||||||
// Set bilinear scale filter for better font scaling
|
// Set bilinear scale filter for better font scaling
|
||||||
SetTextureFilter(font.texture, TEXTURE_FILTER_BILINEAR);
|
SetTextureFilter(font.texture, TEXTURE_FILTER_BILINEAR);
|
||||||
|
|
||||||
|
SetTextLineSpacing(54); // Set line spacing for multiline text (when line breaks are included '\n')
|
||||||
|
|
||||||
// Free codepoints, atlas has already been generated
|
// Free codepoints, atlas has already been generated
|
||||||
free(codepointsNoDups);
|
free(codepointsNoDups);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,8 @@ int main(void)
|
||||||
// NOTE: We define a font base size of 32 pixels tall and up-to 250 characters
|
// NOTE: We define a font base size of 32 pixels tall and up-to 250 characters
|
||||||
Font fontTtf = LoadFontEx("resources/pixantiqua.ttf", 32, 0, 250);
|
Font fontTtf = LoadFontEx("resources/pixantiqua.ttf", 32, 0, 250);
|
||||||
|
|
||||||
|
SetTextLineSpacing(48); // Set line spacing for multiline text (when line breaks are included '\n')
|
||||||
|
|
||||||
bool useTtf = false;
|
bool useTtf = false;
|
||||||
|
|
||||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||||
|
|
|
||||||
|
|
@ -187,12 +187,11 @@ int main(void)
|
||||||
// Add a new set of emojis when SPACE is pressed
|
// Add a new set of emojis when SPACE is pressed
|
||||||
if (IsKeyPressed(KEY_SPACE)) RandomizeEmoji();
|
if (IsKeyPressed(KEY_SPACE)) RandomizeEmoji();
|
||||||
|
|
||||||
// Set the selected emoji and copy its text to clipboard
|
// Set the selected emoji
|
||||||
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && (hovered != -1) && (hovered != selected))
|
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && (hovered != -1) && (hovered != selected))
|
||||||
{
|
{
|
||||||
selected = hovered;
|
selected = hovered;
|
||||||
selectedPos = hoveredPos;
|
selectedPos = hoveredPos;
|
||||||
SetClipboardText(messages[emoji[selected].message].text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2 mouse = GetMousePosition();
|
Vector2 mouse = GetMousePosition();
|
||||||
|
|
@ -342,7 +341,7 @@ static void DrawTextBoxedSelectable(Font font, const char *text, Rectangle rec,
|
||||||
{
|
{
|
||||||
int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop
|
int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop
|
||||||
|
|
||||||
float textOffsetY = 0; // Offset between lines (on line break '\n')
|
float textOffsetY = 0.0f; // 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/(float)font.baseSize; // Character rectangle scaling factor
|
float scaleFactor = fontSize/(float)font.baseSize; // Character rectangle scaling factor
|
||||||
|
|
|
||||||
1
examples/textures/resources/test.svg
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
|
|
@ -134,7 +134,8 @@ int main(void)
|
||||||
(Vector2){ 0, 0 }, 0.0f, WHITE);
|
(Vector2){ 0, 0 }, 0.0f, WHITE);
|
||||||
|
|
||||||
// Draw player current tile
|
// Draw player current tile
|
||||||
DrawText(TextFormat("Current tile: [%i,%i]", playerTileX, playerTileY), 10, 10, 20, LIME);
|
DrawText(TextFormat("Current tile: [%i,%i]", playerTileX, playerTileY), 10, 10, 20, RAYWHITE);
|
||||||
|
DrawText("ARROW KEYS to move", 10, screenHeight-25, 20, RAYWHITE);
|
||||||
|
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 37 KiB |
|
|
@ -64,6 +64,8 @@ int main(void)
|
||||||
|
|
||||||
DrawTexture(textures[currentTexture], screenWidth/2 - textures[currentTexture].width/2, screenHeight/2 - textures[currentTexture].height/2, WHITE);
|
DrawTexture(textures[currentTexture], screenWidth/2 - textures[currentTexture].width/2, screenHeight/2 - textures[currentTexture].height/2, WHITE);
|
||||||
|
|
||||||
|
DrawText("Press LEFT MOUSE BUTTON to rotate the image clockwise", 250, 420, 10, DARKGRAY);
|
||||||
|
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 35 KiB |
72
examples/textures/textures_svg_loading.c
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*******************************************************************************************
|
||||||
|
*
|
||||||
|
* raylib [textures] example - SVG loading and texture creation
|
||||||
|
*
|
||||||
|
* NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM)
|
||||||
|
*
|
||||||
|
* Example originally created with raylib 4.2, last time updated with raylib 4.2
|
||||||
|
*
|
||||||
|
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||||
|
* BSD-like license that allows static linking with closed source software
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 Dennis Meinen (@bixxy#4258 on Discord)
|
||||||
|
*
|
||||||
|
********************************************************************************************/
|
||||||
|
|
||||||
|
#include "raylib.h"
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Program main entry point
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
// Initialization
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
const int screenWidth = 800;
|
||||||
|
const int screenHeight = 450;
|
||||||
|
|
||||||
|
InitWindow(screenWidth, screenHeight, "raylib [textures] example - svg loading");
|
||||||
|
|
||||||
|
// NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required)
|
||||||
|
|
||||||
|
Image image = LoadImageSvg("resources/test.svg", 400, 350); // Loaded in CPU memory (RAM)
|
||||||
|
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
|
||||||
|
|
||||||
|
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||||
|
//---------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Main game loop
|
||||||
|
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||||
|
{
|
||||||
|
// Update
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// TODO: Update your variables here
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Draw
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
BeginDrawing();
|
||||||
|
|
||||||
|
ClearBackground(RAYWHITE);
|
||||||
|
|
||||||
|
DrawTexture(texture, screenWidth/2 - texture.width/2, screenHeight/2 - texture.height/2, WHITE);
|
||||||
|
|
||||||
|
//Red border to illustrate how the SVG is centered within the specified dimensions
|
||||||
|
DrawRectangleLines((screenWidth / 2 - texture.width / 2) - 1, (screenHeight / 2 - texture.height / 2) - 1, texture.width + 2, texture.height + 2, RED);
|
||||||
|
|
||||||
|
DrawText("this IS a texture loaded from an SVG file!", 300, 410, 10, GRAY);
|
||||||
|
|
||||||
|
EndDrawing();
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
}
|
||||||
|
|
||||||
|
// De-Initialization
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
UnloadTexture(texture); // Texture unloading
|
||||||
|
|
||||||
|
CloseWindow(); // Close window and OpenGL context
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
BIN
examples/textures/textures_svg_loading.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
|
|
@ -776,7 +776,7 @@ clean: clean_shell_$(PLATFORM_SHELL)
|
||||||
@echo "removed all generated files!"
|
@echo "removed all generated files!"
|
||||||
|
|
||||||
clean_shell_sh:
|
clean_shell_sh:
|
||||||
rm -fv *.o $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).a $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).bc $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).so*
|
rm -fv *.o $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).a $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).bc $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).so* raygui.c physac.c
|
||||||
ifeq ($(PLATFORM),PLATFORM_ANDROID)
|
ifeq ($(PLATFORM),PLATFORM_ANDROID)
|
||||||
rm -fv $(NATIVE_APP_GLUE)/android_native_app_glue.o
|
rm -fv $(NATIVE_APP_GLUE)/android_native_app_glue.o
|
||||||
endif
|
endif
|
||||||
|
|
@ -788,4 +788,6 @@ clean_shell_cmd:
|
||||||
cd $(RAYLIB_RELEASE_PATH) & \
|
cd $(RAYLIB_RELEASE_PATH) & \
|
||||||
del lib$(RAYLIB_LIB_NAME).a /s & \
|
del lib$(RAYLIB_LIB_NAME).a /s & \
|
||||||
del lib$(RAYLIB_LIB_NAME)dll.a /s & \
|
del lib$(RAYLIB_LIB_NAME)dll.a /s & \
|
||||||
del $(RAYLIB_LIB_NAME).dll /s
|
del $(RAYLIB_LIB_NAME).dll /s & \
|
||||||
|
del raygui.c /s & \
|
||||||
|
del physac.c /s
|
||||||
|
|
|
||||||
|
|
@ -22,15 +22,38 @@ pub fn addRaylib(b: *std.Build, target: std.zig.CrossTarget, optimize: std.built
|
||||||
}
|
}
|
||||||
|
|
||||||
raylib.addCSourceFiles(&.{
|
raylib.addCSourceFiles(&.{
|
||||||
srcdir ++ "/raudio.c",
|
|
||||||
srcdir ++ "/rcore.c",
|
srcdir ++ "/rcore.c",
|
||||||
srcdir ++ "/rmodels.c",
|
|
||||||
srcdir ++ "/rshapes.c",
|
|
||||||
srcdir ++ "/rtext.c",
|
|
||||||
srcdir ++ "/rtextures.c",
|
|
||||||
srcdir ++ "/utils.c",
|
srcdir ++ "/utils.c",
|
||||||
}, raylib_flags);
|
}, raylib_flags);
|
||||||
|
|
||||||
|
if (options.raudio) {
|
||||||
|
raylib.addCSourceFiles(&.{
|
||||||
|
srcdir ++ "/raudio.c",
|
||||||
|
}, raylib_flags);
|
||||||
|
}
|
||||||
|
if (options.rmodels) {
|
||||||
|
raylib.addCSourceFiles(&.{
|
||||||
|
srcdir ++ "/rmodels.c",
|
||||||
|
}, &[_][]const u8{
|
||||||
|
"-fno-sanitize=undefined", // https://github.com/raysan5/raylib/issues/1891
|
||||||
|
} ++ raylib_flags);
|
||||||
|
}
|
||||||
|
if (options.rshapes) {
|
||||||
|
raylib.addCSourceFiles(&.{
|
||||||
|
srcdir ++ "/rshapes.c",
|
||||||
|
}, raylib_flags);
|
||||||
|
}
|
||||||
|
if (options.rtext) {
|
||||||
|
raylib.addCSourceFiles(&.{
|
||||||
|
srcdir ++ "/rtext.c",
|
||||||
|
}, raylib_flags);
|
||||||
|
}
|
||||||
|
if (options.rtextures) {
|
||||||
|
raylib.addCSourceFiles(&.{
|
||||||
|
srcdir ++ "/rtextures.c",
|
||||||
|
}, raylib_flags);
|
||||||
|
}
|
||||||
|
|
||||||
var gen_step = std.build.Step.WriteFile.create(b);
|
var gen_step = std.build.Step.WriteFile.create(b);
|
||||||
raylib.step.dependOn(&gen_step.step);
|
raylib.step.dependOn(&gen_step.step);
|
||||||
|
|
||||||
|
|
@ -137,6 +160,11 @@ pub fn addRaylib(b: *std.Build, target: std.zig.CrossTarget, optimize: std.built
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const Options = struct {
|
pub const Options = struct {
|
||||||
|
raudio: bool = true,
|
||||||
|
rmodels: bool = true,
|
||||||
|
rshapes: bool = true,
|
||||||
|
rtext: bool = true,
|
||||||
|
rtextures: bool = true,
|
||||||
raygui: bool = false,
|
raygui: bool = false,
|
||||||
platform_drm: bool = false,
|
platform_drm: bool = false,
|
||||||
};
|
};
|
||||||
|
|
@ -152,19 +180,24 @@ pub fn build(b: *std.Build) void {
|
||||||
// set a preferred release mode, allowing the user to decide how to optimize.
|
// set a preferred release mode, allowing the user to decide how to optimize.
|
||||||
const optimize = b.standardOptimizeOption(.{});
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
|
||||||
const raygui = b.option(bool, "raygui", "Compile with raygui support");
|
const defaults = Options{};
|
||||||
const platform_drm = b.option(bool, "platform_drm", "Compile raylib in native mode (no X11)");
|
const options = Options{
|
||||||
|
.platform_drm = b.option(bool, "platform_drm", "Compile raylib in native mode (no X11)") orelse defaults.platform_drm,
|
||||||
|
.raudio = b.option(bool, "raudio", "Compile with audio support") orelse defaults.raudio,
|
||||||
|
.rmodels = b.option(bool, "rmodels", "Compile with models support") orelse defaults.rmodels,
|
||||||
|
.rtext = b.option(bool, "rtext", "Compile with text support") orelse defaults.rtext,
|
||||||
|
.rtextures = b.option(bool, "rtextures", "Compile with textures support") orelse defaults.rtextures,
|
||||||
|
.rshapes = b.option(bool, "rshapes", "Compile with shapes support") orelse defaults.rshapes,
|
||||||
|
.raygui = b.option(bool, "raygui", "Compile with raygui support") orelse defaults.raygui,
|
||||||
|
};
|
||||||
|
|
||||||
const lib = addRaylib(b, target, optimize, .{
|
const lib = addRaylib(b, target, optimize, options);
|
||||||
.raygui = raygui orelse false,
|
|
||||||
.platform_drm = platform_drm orelse false,
|
|
||||||
});
|
|
||||||
|
|
||||||
lib.installHeader("src/raylib.h", "raylib.h");
|
lib.installHeader("src/raylib.h", "raylib.h");
|
||||||
lib.installHeader("src/raymath.h", "raymath.h");
|
lib.installHeader("src/raymath.h", "raymath.h");
|
||||||
lib.installHeader("src/rlgl.h", "rlgl.h");
|
lib.installHeader("src/rlgl.h", "rlgl.h");
|
||||||
|
|
||||||
if (raygui orelse false) {
|
if (options.raygui) {
|
||||||
lib.installHeader("../raygui/src/raygui.h", "raygui.h");
|
lib.installHeader("../raygui/src/raygui.h", "raygui.h");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
30
src/config.h
|
|
@ -141,22 +141,22 @@
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Module: rtextures - Configuration Flags
|
// Module: rtextures - Configuration Flags
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Select the desired fileformats to be supported for image data loading
|
// Selecte desired fileformats to be supported for image data loading
|
||||||
#define SUPPORT_FILEFORMAT_PNG 1
|
#define SUPPORT_FILEFORMAT_PNG 1
|
||||||
//#define SUPPORT_FILEFORMAT_BMP 1
|
//#define SUPPORT_FILEFORMAT_BMP 1
|
||||||
//#define SUPPORT_FILEFORMAT_TGA 1
|
//#define SUPPORT_FILEFORMAT_TGA 1
|
||||||
//#define SUPPORT_FILEFORMAT_JPG 1
|
//#define SUPPORT_FILEFORMAT_JPG 1
|
||||||
#define SUPPORT_FILEFORMAT_GIF 1
|
#define SUPPORT_FILEFORMAT_GIF 1
|
||||||
#define SUPPORT_FILEFORMAT_QOI 1
|
#define SUPPORT_FILEFORMAT_QOI 1
|
||||||
//#define SUPPORT_FILEFORMAT_PSD 1
|
//#define SUPPORT_FILEFORMAT_PSD 1
|
||||||
#define SUPPORT_FILEFORMAT_DDS 1
|
#define SUPPORT_FILEFORMAT_DDS 1
|
||||||
#define SUPPORT_FILEFORMAT_HDR 1
|
//#define SUPPORT_FILEFORMAT_HDR 1
|
||||||
//#define SUPPORT_FILEFORMAT_PIC 1
|
//#define SUPPORT_FILEFORMAT_PIC 1
|
||||||
//#define SUPPORT_FILEFORMAT_PNM 1
|
//#define SUPPORT_FILEFORMAT_KTX 1
|
||||||
//#define SUPPORT_FILEFORMAT_KTX 1
|
//#define SUPPORT_FILEFORMAT_ASTC 1
|
||||||
//#define SUPPORT_FILEFORMAT_ASTC 1
|
//#define SUPPORT_FILEFORMAT_PKM 1
|
||||||
//#define SUPPORT_FILEFORMAT_PKM 1
|
//#define SUPPORT_FILEFORMAT_PVR 1
|
||||||
//#define SUPPORT_FILEFORMAT_PVR 1
|
//#define SUPPORT_FILEFORMAT_SVG 1
|
||||||
|
|
||||||
// Support image export functionality (.png, .bmp, .tga, .jpg, .qoi)
|
// Support image export functionality (.png, .bmp, .tga, .jpg, .qoi)
|
||||||
#define SUPPORT_IMAGE_EXPORT 1
|
#define SUPPORT_IMAGE_EXPORT 1
|
||||||
|
|
|
||||||
3053
src/external/nanosvg.h
vendored
Normal file
1458
src/external/nanosvgrast.h
vendored
Normal file
49
src/raudio.c
|
|
@ -227,17 +227,20 @@ typedef struct tagBITMAPINFOHEADER {
|
||||||
#define QOA_MALLOC RL_MALLOC
|
#define QOA_MALLOC RL_MALLOC
|
||||||
#define QOA_FREE RL_FREE
|
#define QOA_FREE RL_FREE
|
||||||
|
|
||||||
#if defined(_MSC_VER ) // par shapes has 2 warnings on windows, so disable them just fof this file
|
#if defined(_MSC_VER) // Disable some MSVC warning
|
||||||
#pragma warning( push )
|
#pragma warning(push)
|
||||||
#pragma warning( disable : 4018)
|
#pragma warning(disable : 4018)
|
||||||
#pragma warning( disable : 4267)
|
#pragma warning(disable : 4267)
|
||||||
#pragma warning( disable : 4244)
|
#pragma warning(disable : 4244)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define QOA_IMPLEMENTATION
|
#define QOA_IMPLEMENTATION
|
||||||
#include "external/qoa.h" // QOA loading and saving functions
|
#include "external/qoa.h" // QOA loading and saving functions
|
||||||
#include "external/qoaplay.c" // QOA stream playing helper functions
|
#include "external/qoaplay.c" // QOA stream playing helper functions
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(pop) // Disable MSVC warning suppression
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(SUPPORT_FILEFORMAT_FLAC)
|
#if defined(SUPPORT_FILEFORMAT_FLAC)
|
||||||
|
|
@ -254,16 +257,16 @@ typedef struct tagBITMAPINFOHEADER {
|
||||||
#define JARXM_MALLOC RL_MALLOC
|
#define JARXM_MALLOC RL_MALLOC
|
||||||
#define JARXM_FREE RL_FREE
|
#define JARXM_FREE RL_FREE
|
||||||
|
|
||||||
#if defined(_MSC_VER ) // jar_xm has warnings on windows, so disable them just for this file
|
#if defined(_MSC_VER) // Disable some MSVC warning
|
||||||
#pragma warning( push )
|
#pragma warning(push)
|
||||||
#pragma warning( disable : 4244)
|
#pragma warning(disable : 4244)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define JAR_XM_IMPLEMENTATION
|
#define JAR_XM_IMPLEMENTATION
|
||||||
#include "external/jar_xm.h" // XM loading functions
|
#include "external/jar_xm.h" // XM loading functions
|
||||||
|
|
||||||
#if defined(_MSC_VER )
|
#if defined(_MSC_VER)
|
||||||
#pragma warning( pop )
|
#pragma warning(pop) // Disable MSVC warning suppression
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -410,8 +413,8 @@ static void MixAudioFrames(float *framesOut, const float *framesIn, ma_uint32 fr
|
||||||
static bool IsFileExtension(const char *fileName, const char *ext); // Check file extension
|
static bool IsFileExtension(const char *fileName, const char *ext); // Check file extension
|
||||||
static const char *GetFileExtension(const char *fileName); // Get pointer to extension for a filename string (includes the dot: .png)
|
static const char *GetFileExtension(const char *fileName); // Get pointer to extension for a filename string (includes the dot: .png)
|
||||||
|
|
||||||
static unsigned char *LoadFileData(const char *fileName, unsigned int *bytesRead); // Load file data as byte array (read)
|
static unsigned char *LoadFileData(const char *fileName, int *dataSize); // Load file data as byte array (read)
|
||||||
static bool SaveFileData(const char *fileName, void *data, unsigned int bytesToWrite); // Save data to file from byte array (write)
|
static bool SaveFileData(const char *fileName, void *data, int dataSize); // Save data to file from byte array (write)
|
||||||
static bool SaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated
|
static bool SaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -729,11 +732,11 @@ Wave LoadWave(const char *fileName)
|
||||||
Wave wave = { 0 };
|
Wave wave = { 0 };
|
||||||
|
|
||||||
// Loading file to memory
|
// Loading file to memory
|
||||||
unsigned int fileSize = 0;
|
int dataSize = 0;
|
||||||
unsigned char *fileData = LoadFileData(fileName, &fileSize);
|
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
||||||
|
|
||||||
// Loading wave from memory data
|
// Loading wave from memory data
|
||||||
if (fileData != NULL) wave = LoadWaveFromMemory(GetFileExtension(fileName), fileData, fileSize);
|
if (fileData != NULL) wave = LoadWaveFromMemory(GetFileExtension(fileName), fileData, dataSize);
|
||||||
|
|
||||||
RL_FREE(fileData);
|
RL_FREE(fileData);
|
||||||
|
|
||||||
|
|
@ -2616,10 +2619,10 @@ static const char *GetFileExtension(const char *fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load data from file into a buffer
|
// Load data from file into a buffer
|
||||||
static unsigned char *LoadFileData(const char *fileName, unsigned int *bytesRead)
|
static unsigned char *LoadFileData(const char *fileName, int *dataSize)
|
||||||
{
|
{
|
||||||
unsigned char *data = NULL;
|
unsigned char *data = NULL;
|
||||||
*bytesRead = 0;
|
*dataSize = 0;
|
||||||
|
|
||||||
if (fileName != NULL)
|
if (fileName != NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -2639,7 +2642,7 @@ static unsigned char *LoadFileData(const char *fileName, unsigned int *bytesRead
|
||||||
|
|
||||||
// NOTE: fread() returns number of read elements instead of bytes, so we read [1 byte, size elements]
|
// NOTE: fread() returns number of read elements instead of bytes, so we read [1 byte, size elements]
|
||||||
unsigned int count = (unsigned int)fread(data, sizeof(unsigned char), size, file);
|
unsigned int count = (unsigned int)fread(data, sizeof(unsigned char), size, file);
|
||||||
*bytesRead = count;
|
*dataSize = count;
|
||||||
|
|
||||||
if (count != size) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially loaded", fileName);
|
if (count != size) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially loaded", fileName);
|
||||||
else TRACELOG(LOG_INFO, "FILEIO: [%s] File loaded successfully", fileName);
|
else TRACELOG(LOG_INFO, "FILEIO: [%s] File loaded successfully", fileName);
|
||||||
|
|
@ -2656,7 +2659,7 @@ static unsigned char *LoadFileData(const char *fileName, unsigned int *bytesRead
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save data to file from buffer
|
// Save data to file from buffer
|
||||||
static bool SaveFileData(const char *fileName, void *data, unsigned int bytesToWrite)
|
static bool SaveFileData(const char *fileName, void *data, int dataSize)
|
||||||
{
|
{
|
||||||
if (fileName != NULL)
|
if (fileName != NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -2664,10 +2667,10 @@ static bool SaveFileData(const char *fileName, void *data, unsigned int bytesToW
|
||||||
|
|
||||||
if (file != NULL)
|
if (file != NULL)
|
||||||
{
|
{
|
||||||
unsigned int count = (unsigned int)fwrite(data, sizeof(unsigned char), bytesToWrite, file);
|
unsigned int count = (unsigned int)fwrite(data, sizeof(unsigned char), dataSize, file);
|
||||||
|
|
||||||
if (count == 0) TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to write file", fileName);
|
if (count == 0) TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to write file", fileName);
|
||||||
else if (count != bytesToWrite) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially written", fileName);
|
else if (count != dataSize) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially written", fileName);
|
||||||
else TRACELOG(LOG_INFO, "FILEIO: [%s] File saved successfully", fileName);
|
else TRACELOG(LOG_INFO, "FILEIO: [%s] File saved successfully", fileName);
|
||||||
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
|
|
||||||
26
src/raylib.h
|
|
@ -1075,10 +1075,10 @@ RLAPI void SetLoadFileTextCallback(LoadFileTextCallback callback); // Set custom
|
||||||
RLAPI void SetSaveFileTextCallback(SaveFileTextCallback callback); // Set custom file text data saver
|
RLAPI void SetSaveFileTextCallback(SaveFileTextCallback callback); // Set custom file text data saver
|
||||||
|
|
||||||
// Files management functions
|
// Files management functions
|
||||||
RLAPI unsigned char *LoadFileData(const char *fileName, unsigned int *bytesRead); // Load file data as byte array (read)
|
RLAPI unsigned char *LoadFileData(const char *fileName, int *dataSize); // Load file data as byte array (read)
|
||||||
RLAPI void UnloadFileData(unsigned char *data); // Unload file data allocated by LoadFileData()
|
RLAPI void UnloadFileData(unsigned char *data); // Unload file data allocated by LoadFileData()
|
||||||
RLAPI bool SaveFileData(const char *fileName, void *data, unsigned int bytesToWrite); // Save data to file from byte array (write), returns true on success
|
RLAPI bool SaveFileData(const char *fileName, void *data, int dataSize); // Save data to file from byte array (write), returns true on success
|
||||||
RLAPI bool ExportDataAsCode(const unsigned char *data, unsigned int size, const char *fileName); // Export data to code (.h), returns true on success
|
RLAPI bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileName); // Export data to code (.h), returns true on success
|
||||||
RLAPI char *LoadFileText(const char *fileName); // Load text data from file (read), returns a '\0' terminated string
|
RLAPI char *LoadFileText(const char *fileName); // Load text data from file (read), returns a '\0' terminated string
|
||||||
RLAPI void UnloadFileText(char *text); // Unload file text data allocated by LoadFileText()
|
RLAPI void UnloadFileText(char *text); // Unload file text data allocated by LoadFileText()
|
||||||
RLAPI bool SaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated, returns true on success
|
RLAPI bool SaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated, returns true on success
|
||||||
|
|
@ -1115,6 +1115,7 @@ RLAPI unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize
|
||||||
|
|
||||||
// Input-related functions: keyboard
|
// Input-related functions: keyboard
|
||||||
RLAPI bool IsKeyPressed(int key); // Check if a key has been pressed once
|
RLAPI bool IsKeyPressed(int key); // Check if a key has been pressed once
|
||||||
|
RLAPI bool IsKeyPressedRepeat(int key); // Check if a key has been pressed again (Only PLATFORM_DESKTOP)
|
||||||
RLAPI bool IsKeyDown(int key); // Check if a key is being pressed
|
RLAPI bool IsKeyDown(int key); // Check if a key is being pressed
|
||||||
RLAPI bool IsKeyReleased(int key); // Check if a key has been released once
|
RLAPI bool IsKeyReleased(int key); // Check if a key has been released once
|
||||||
RLAPI bool IsKeyUp(int key); // Check if a key is NOT being pressed
|
RLAPI bool IsKeyUp(int key); // Check if a key is NOT being pressed
|
||||||
|
|
@ -1192,6 +1193,8 @@ RLAPI void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color
|
||||||
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 DrawLineBezierCubic(Vector2 startPos, Vector2 endPos, Vector2 startControlPos, Vector2 endControlPos, float thick, Color color); // Draw line using cubic bezier curves with 2 control points
|
RLAPI void DrawLineBezierCubic(Vector2 startPos, Vector2 endPos, Vector2 startControlPos, Vector2 endControlPos, float thick, Color color); // Draw line using cubic bezier curves with 2 control points
|
||||||
|
RLAPI void DrawLineBSpline(Vector2 *points, int pointCount, float thick, Color color); // Draw a B-Spline line, minimum 4 points
|
||||||
|
RLAPI void DrawLineCatmullRom(Vector2 *points, int pointCount, float thick, Color color); // Draw a Catmull Rom spline line, minimum 4 points
|
||||||
RLAPI void DrawLineStrip(Vector2 *points, int pointCount, 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
|
||||||
|
|
@ -1242,6 +1245,7 @@ RLAPI Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2);
|
||||||
// NOTE: These functions do not require GPU access
|
// NOTE: These functions do not require GPU access
|
||||||
RLAPI Image LoadImage(const char *fileName); // Load image from file into CPU memory (RAM)
|
RLAPI Image LoadImage(const char *fileName); // Load image from file into CPU memory (RAM)
|
||||||
RLAPI Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize); // Load image from RAW file data
|
RLAPI Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize); // Load image from RAW file data
|
||||||
|
RLAPI Image LoadImageSvg(const char *fileNameOrString, int width, int height); // Load image from SVG file data or string with specified size
|
||||||
RLAPI Image LoadImageAnim(const char *fileName, int *frames); // Load image sequence from file (frames appended to image.data)
|
RLAPI Image LoadImageAnim(const char *fileName, int *frames); // Load image sequence from file (frames appended to image.data)
|
||||||
RLAPI Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load image from memory buffer, fileType refers to extension: i.e. '.png'
|
RLAPI Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load image from memory buffer, fileType refers to extension: i.e. '.png'
|
||||||
RLAPI Image LoadImageFromTexture(Texture2D texture); // Load image from GPU texture data
|
RLAPI Image LoadImageFromTexture(Texture2D texture); // Load image from GPU texture data
|
||||||
|
|
@ -1368,13 +1372,13 @@ 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 glyphCount); // Load font from file with extended parameters, use NULL for fontChars and 0 for glyphCount to load the default character set
|
RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set
|
||||||
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 glyphCount); // 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 *codepoints, int codepointCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf'
|
||||||
RLAPI bool IsFontReady(Font font); // Check if a font is ready
|
RLAPI bool IsFontReady(Font font); // Check if a font is ready
|
||||||
RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int glyphCount, int type); // Load font data for further use
|
RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount, int type); // Load font data for further use
|
||||||
RLAPI Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **recs, int glyphCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info
|
RLAPI Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyphCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info
|
||||||
RLAPI void UnloadFontData(GlyphInfo *chars, int glyphCount); // Unload font chars info data (RAM)
|
RLAPI void UnloadFontData(GlyphInfo *glyphs, int glyphCount); // Unload font chars info data (RAM)
|
||||||
RLAPI void UnloadFont(Font font); // Unload font from GPU memory (VRAM)
|
RLAPI void UnloadFont(Font font); // Unload font from GPU memory (VRAM)
|
||||||
RLAPI bool ExportFontAsCode(Font font, const char *fileName); // Export font as code file, returns true on success
|
RLAPI bool ExportFontAsCode(Font font, const char *fileName); // Export font as code file, returns true on success
|
||||||
|
|
||||||
|
|
@ -1384,7 +1388,7 @@ RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color co
|
||||||
RLAPI void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters
|
RLAPI void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters
|
||||||
RLAPI void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint); // Draw text using Font and pro parameters (rotation)
|
RLAPI void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint); // Draw text using Font and pro parameters (rotation)
|
||||||
RLAPI void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSize, Color tint); // Draw one character (codepoint)
|
RLAPI void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSize, Color tint); // Draw one character (codepoint)
|
||||||
RLAPI void DrawTextCodepoints(Font font, const int *codepoints, int count, Vector2 position, float fontSize, float spacing, Color tint); // Draw multiple character (codepoint)
|
RLAPI void DrawTextCodepoints(Font font, const int *codepoints, int codepointCount, Vector2 position, float fontSize, float spacing, Color tint); // Draw multiple character (codepoint)
|
||||||
|
|
||||||
// Text font info functions
|
// Text font info functions
|
||||||
RLAPI void SetTextLineSpacing(int spacing); // Set vertical line spacing when drawing with line-breaks
|
RLAPI void SetTextLineSpacing(int spacing); // Set vertical line spacing when drawing with line-breaks
|
||||||
|
|
@ -1503,10 +1507,10 @@ 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, unsigned int *animCount); // Load model animations from file
|
RLAPI ModelAnimation *LoadModelAnimations(const char *fileName, int *animCount); // Load model animations from file
|
||||||
RLAPI void UpdateModelAnimation(Model model, ModelAnimation anim, int frame); // Update model animation pose
|
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, int animCount); // Unload animation array data
|
||||||
RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match
|
RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match
|
||||||
|
|
||||||
// Collision detection functions
|
// Collision detection functions
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
* - Functions use always a "result" variable for return
|
* - Functions use always a "result" variable for return
|
||||||
* - Functions are always defined inline
|
* - Functions are always defined inline
|
||||||
* - Angles are always in radians (DEG2RAD/RAD2DEG macros provided for convenience)
|
* - Angles are always in radians (DEG2RAD/RAD2DEG macros provided for convenience)
|
||||||
|
* - No compound literals used to make sure libray is compatible with C++
|
||||||
*
|
*
|
||||||
* CONFIGURATION:
|
* CONFIGURATION:
|
||||||
* #define RAYMATH_IMPLEMENTATION
|
* #define RAYMATH_IMPLEMENTATION
|
||||||
|
|
@ -713,6 +714,40 @@ RMAPI Vector3 Vector3Normalize(Vector3 v)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Calculate the projection of the vector v1 on to v2
|
||||||
|
RMAPI Vector3 Vector3Project(Vector3 v1, Vector3 v2)
|
||||||
|
{
|
||||||
|
Vector3 result = { 0 };
|
||||||
|
|
||||||
|
float v1dv2 = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z);
|
||||||
|
float v2dv2 = (v2.x*v2.x + v2.y*v2.y + v2.z*v2.z);
|
||||||
|
|
||||||
|
float mag = v1dv2/v2dv2;
|
||||||
|
|
||||||
|
result.x = v2.x*mag;
|
||||||
|
result.y = v2.y*mag;
|
||||||
|
result.z = v2.z*mag;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Calculate the rejection of the vector v1 on to v2
|
||||||
|
RMAPI Vector3 Vector3Reject(Vector3 v1, Vector3 v2)
|
||||||
|
{
|
||||||
|
Vector3 result = { 0 };
|
||||||
|
|
||||||
|
float v1dv2 = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z);
|
||||||
|
float v2dv2 = (v2.x*v2.x + v2.y*v2.y + v2.z*v2.z);
|
||||||
|
|
||||||
|
float mag = v1dv2/v2dv2;
|
||||||
|
|
||||||
|
result.x = v1.x - (v2.x*mag);
|
||||||
|
result.y = v1.y - (v2.y*mag);
|
||||||
|
result.z = v1.z - (v2.z*mag);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// Orthonormalize provided vectors
|
// Orthonormalize provided vectors
|
||||||
// Makes vectors normalized and orthogonal to each other
|
// Makes vectors normalized and orthogonal to each other
|
||||||
// Gram-Schmidt function implementation
|
// Gram-Schmidt function implementation
|
||||||
|
|
|
||||||
|
|
@ -184,9 +184,10 @@ RLAPI Matrix GetCameraProjectionMatrix(Camera* camera, float aspect);
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
#define CAMERA_MOVE_SPEED 0.09f
|
#define CAMERA_MOVE_SPEED 0.09f
|
||||||
#define CAMERA_ROTATION_SPEED 0.03f
|
#define CAMERA_ROTATION_SPEED 0.03f
|
||||||
|
#define CAMERA_PAN_SPEED 0.2f
|
||||||
|
|
||||||
// Camera mouse movement sensitivity
|
// Camera mouse movement sensitivity
|
||||||
#define CAMERA_MOUSE_MOVE_SENSITIVITY 0.003f // TODO: it should be independant of framerate
|
#define CAMERA_MOUSE_MOVE_SENSITIVITY 0.003f // TODO: it should be independant of framerate
|
||||||
#define CAMERA_MOUSE_SCROLL_SENSITIVITY 1.5f
|
#define CAMERA_MOUSE_SCROLL_SENSITIVITY 1.5f
|
||||||
|
|
||||||
#define CAMERA_ORBITAL_SPEED 0.5f // Radians per second
|
#define CAMERA_ORBITAL_SPEED 0.5f // Radians per second
|
||||||
|
|
@ -435,7 +436,7 @@ void UpdateCamera(Camera *camera, int mode)
|
||||||
bool moveInWorldPlane = ((mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON));
|
bool moveInWorldPlane = ((mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON));
|
||||||
bool rotateAroundTarget = ((mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL));
|
bool rotateAroundTarget = ((mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL));
|
||||||
bool lockView = ((mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL));
|
bool lockView = ((mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL));
|
||||||
bool rotateUp = (mode == CAMERA_FREE);
|
bool rotateUp = false;
|
||||||
|
|
||||||
if (mode == CAMERA_ORBITAL)
|
if (mode == CAMERA_ORBITAL)
|
||||||
{
|
{
|
||||||
|
|
@ -458,10 +459,23 @@ void UpdateCamera(Camera *camera, int mode)
|
||||||
// Camera movement
|
// Camera movement
|
||||||
if (!IsGamepadAvailable(0))
|
if (!IsGamepadAvailable(0))
|
||||||
{
|
{
|
||||||
// Mouse/Keyboard support
|
// Camera pan (for CAMERA_FREE)
|
||||||
CameraYaw(camera, -mousePositionDelta.x*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget);
|
if ((mode == CAMERA_FREE) && (IsMouseButtonDown(MOUSE_BUTTON_MIDDLE)))
|
||||||
CameraPitch(camera, -mousePositionDelta.y*CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp);
|
{
|
||||||
|
const Vector2 mouseDelta = GetMouseDelta();
|
||||||
|
if (mouseDelta.x > 0.0f) CameraMoveRight(camera, CAMERA_PAN_SPEED, moveInWorldPlane);
|
||||||
|
if (mouseDelta.x < 0.0f) CameraMoveRight(camera, -CAMERA_PAN_SPEED, moveInWorldPlane);
|
||||||
|
if (mouseDelta.y > 0.0f) CameraMoveUp(camera, -CAMERA_PAN_SPEED);
|
||||||
|
if (mouseDelta.y < 0.0f) CameraMoveUp(camera, CAMERA_PAN_SPEED);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Mouse support
|
||||||
|
CameraYaw(camera, -mousePositionDelta.x*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget);
|
||||||
|
CameraPitch(camera, -mousePositionDelta.y*CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keyboard support
|
||||||
if (IsKeyDown(KEY_W)) CameraMoveForward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
|
if (IsKeyDown(KEY_W)) CameraMoveForward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
|
||||||
if (IsKeyDown(KEY_A)) CameraMoveRight(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
|
if (IsKeyDown(KEY_A)) CameraMoveRight(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
|
||||||
if (IsKeyDown(KEY_S)) CameraMoveForward(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
|
if (IsKeyDown(KEY_S)) CameraMoveForward(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
|
||||||
|
|
@ -479,11 +493,14 @@ void UpdateCamera(Camera *camera, int mode)
|
||||||
if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) >= 0.25f) CameraMoveRight(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
|
if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) >= 0.25f) CameraMoveRight(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (IsKeyDown(KEY_SPACE)) CameraMoveUp(camera, CAMERA_MOVE_SPEED);
|
if (mode == CAMERA_FREE)
|
||||||
//if (IsKeyDown(KEY_LEFT_CONTROL)) CameraMoveUp(camera, -CAMERA_MOVE_SPEED);
|
{
|
||||||
|
if (IsKeyDown(KEY_SPACE)) CameraMoveUp(camera, CAMERA_MOVE_SPEED);
|
||||||
|
if (IsKeyDown(KEY_LEFT_CONTROL)) CameraMoveUp(camera, -CAMERA_MOVE_SPEED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL))
|
if ((mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL) || (mode == CAMERA_FREE))
|
||||||
{
|
{
|
||||||
// Zoom target distance
|
// Zoom target distance
|
||||||
CameraMoveToTarget(camera, -GetMouseWheelMove());
|
CameraMoveToTarget(camera, -GetMouseWheelMove());
|
||||||
|
|
|
||||||
131
src/rcore.c
|
|
@ -42,9 +42,6 @@
|
||||||
* #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.
|
||||||
*
|
*
|
||||||
* #define SUPPORT_TOUCH_AS_MOUSE
|
|
||||||
* Touch input and mouse input are shared. Mouse functions also return touch information.
|
|
||||||
*
|
|
||||||
* #define SUPPORT_SSH_KEYBOARD_RPI (Raspberry Pi only)
|
* #define SUPPORT_SSH_KEYBOARD_RPI (Raspberry Pi only)
|
||||||
* Reconfigure standard input to receive key inputs, works with SSH connection.
|
* Reconfigure standard input to receive key inputs, works with SSH connection.
|
||||||
* WARNING: Reconfiguring standard input could lead to undesired effects, like breaking other
|
* WARNING: Reconfiguring standard input could lead to undesired effects, like breaking other
|
||||||
|
|
@ -425,6 +422,8 @@ typedef struct CoreData {
|
||||||
int exitKey; // Default exit key
|
int exitKey; // Default exit key
|
||||||
char currentKeyState[MAX_KEYBOARD_KEYS]; // Registers current frame key state
|
char currentKeyState[MAX_KEYBOARD_KEYS]; // Registers current frame key state
|
||||||
char previousKeyState[MAX_KEYBOARD_KEYS]; // Registers previous frame key state
|
char previousKeyState[MAX_KEYBOARD_KEYS]; // Registers previous frame key state
|
||||||
|
// NOTE: Since key press logic involves comparing prev vs cur key state, we need to handle key repeats specially
|
||||||
|
char keyRepeatInFrame[MAX_KEYBOARD_KEYS]; // Registers key repeats for current frame.
|
||||||
|
|
||||||
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
|
||||||
|
|
@ -491,7 +490,7 @@ typedef struct CoreData {
|
||||||
double frame; // Time measure for one frame
|
double frame; // Time measure for one frame
|
||||||
double target; // Desired time for one frame, if 0 not applied
|
double target; // Desired time for one frame, if 0 not applied
|
||||||
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_DRM)
|
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_DRM)
|
||||||
unsigned long long base; // Base time measure for hi-res timer
|
unsigned long long int base; // Base time measure for hi-res timer
|
||||||
#endif
|
#endif
|
||||||
unsigned int frameCounter; // Frame counter
|
unsigned int frameCounter; // Frame counter
|
||||||
} Time;
|
} Time;
|
||||||
|
|
@ -586,7 +585,7 @@ static const char *autoEventTypeName[] = {
|
||||||
"ACTION_SETTARGETFPS"
|
"ACTION_SETTARGETFPS"
|
||||||
};
|
};
|
||||||
|
|
||||||
// Automation Event (24 bytes)
|
// Automation event (24 bytes)
|
||||||
typedef struct AutomationEvent {
|
typedef struct AutomationEvent {
|
||||||
unsigned int frame; // Event frame
|
unsigned int frame; // Event frame
|
||||||
unsigned int type; // Event type (AutomationEventType)
|
unsigned int type; // Event type (AutomationEventType)
|
||||||
|
|
@ -870,9 +869,19 @@ void InitWindow(int width, int height, const char *title)
|
||||||
// WARNING: External function: Module required: rtext
|
// WARNING: External function: Module required: rtext
|
||||||
LoadFontDefault();
|
LoadFontDefault();
|
||||||
#if defined(SUPPORT_MODULE_RSHAPES)
|
#if defined(SUPPORT_MODULE_RSHAPES)
|
||||||
|
// Set font white rectangle for shapes drawing, so shapes and text can be batched together
|
||||||
|
// WARNING: rshapes module is required, if not available, default internal white rectangle is used
|
||||||
Rectangle rec = GetFontDefault().recs[95];
|
Rectangle rec = GetFontDefault().recs[95];
|
||||||
// NOTE: We set up a 1px padding on char rectangle to avoid pixel bleeding on MSAA filtering
|
if (CORE.Window.flags & FLAG_MSAA_4X_HINT)
|
||||||
SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 }); // WARNING: Module required: rshapes
|
{
|
||||||
|
// NOTE: We try to maxime rec padding to avoid pixel bleeding on MSAA filtering
|
||||||
|
SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 2, rec.y + 2, 1, 1 });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// NOTE: We set up a 1px padding on char rectangle to avoid pixel bleeding
|
||||||
|
SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 });
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#if defined(SUPPORT_MODULE_RSHAPES)
|
#if defined(SUPPORT_MODULE_RSHAPES)
|
||||||
|
|
@ -2133,7 +2142,7 @@ void SetClipboardText(const char *text)
|
||||||
#if defined(PLATFORM_WEB)
|
#if defined(PLATFORM_WEB)
|
||||||
// Security check to (partially) avoid malicious code
|
// Security check to (partially) avoid malicious code
|
||||||
if (strchr(text, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided Clipboard could be potentially malicious, avoid [\'] character");
|
if (strchr(text, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided Clipboard could be potentially malicious, avoid [\'] character");
|
||||||
else emscripten_run_script(TextFormat("navigator.clipboard.writeText('%s')", text));
|
else EM_ASM( { navigator.clipboard.writeText(UTF8ToString($0)); }, text);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2982,7 +2991,7 @@ int GetFPS(void)
|
||||||
|
|
||||||
#if !defined(SUPPORT_CUSTOM_FRAME_CONTROL)
|
#if !defined(SUPPORT_CUSTOM_FRAME_CONTROL)
|
||||||
#define FPS_CAPTURE_FRAMES_COUNT 30 // 30 captures
|
#define FPS_CAPTURE_FRAMES_COUNT 30 // 30 captures
|
||||||
#define FPS_AVERAGE_TIME_SECONDS 0.5f // 500 millisecondes
|
#define FPS_AVERAGE_TIME_SECONDS 0.5f // 500 milliseconds
|
||||||
#define FPS_STEP (FPS_AVERAGE_TIME_SECONDS/FPS_CAPTURE_FRAMES_COUNT)
|
#define FPS_STEP (FPS_AVERAGE_TIME_SECONDS/FPS_CAPTURE_FRAMES_COUNT)
|
||||||
|
|
||||||
static int index = 0;
|
static int index = 0;
|
||||||
|
|
@ -3176,12 +3185,23 @@ int GetFileLength(const char *fileName)
|
||||||
{
|
{
|
||||||
int size = 0;
|
int size = 0;
|
||||||
|
|
||||||
|
// NOTE: On Unix-like systems, it can by used the POSIX system call: stat(),
|
||||||
|
// but depending on the platform that call could not be available
|
||||||
|
//struct stat result = { 0 };
|
||||||
|
//stat(fileName, &result);
|
||||||
|
//return result.st_size;
|
||||||
|
|
||||||
FILE *file = fopen(fileName, "rb");
|
FILE *file = fopen(fileName, "rb");
|
||||||
|
|
||||||
if (file != NULL)
|
if (file != NULL)
|
||||||
{
|
{
|
||||||
fseek(file, 0L, SEEK_END);
|
fseek(file, 0L, SEEK_END);
|
||||||
size = (int)ftell(file);
|
long int fileSize = ftell(file);
|
||||||
|
|
||||||
|
// Check for size overflow (INT_MAX)
|
||||||
|
if (fileSize > 2147483647) TRACELOG(LOG_WARNING, "[%s] File size overflows expected limit, do not use GetFileLength()", fileName);
|
||||||
|
else size = (int)fileSize;
|
||||||
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3478,10 +3498,10 @@ bool ChangeDirectory(const char *dir)
|
||||||
// Check if a given path point to a file
|
// Check if a given path point to a file
|
||||||
bool IsPathFile(const char *path)
|
bool IsPathFile(const char *path)
|
||||||
{
|
{
|
||||||
struct stat pathStat = { 0 };
|
struct stat result = { 0 };
|
||||||
stat(path, &pathStat);
|
stat(path, &result);
|
||||||
|
|
||||||
return S_ISREG(pathStat.st_mode);
|
return S_ISREG(result.st_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if a file has been dropped into window
|
// Check if a file has been dropped into window
|
||||||
|
|
@ -3679,7 +3699,7 @@ unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize)
|
||||||
// Ref: https://github.com/raysan5/raylib/issues/686
|
// Ref: https://github.com/raysan5/raylib/issues/686
|
||||||
void OpenURL(const char *url)
|
void OpenURL(const char *url)
|
||||||
{
|
{
|
||||||
// Security check to (aprtially) avoid malicious code on PLATFORM_WEB
|
// Security check to (partially) avoid malicious code on PLATFORM_WEB
|
||||||
if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character");
|
if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -3733,6 +3753,7 @@ void OpenURL(const char *url)
|
||||||
// Check if a key has been pressed once
|
// Check if a key has been pressed once
|
||||||
bool IsKeyPressed(int key)
|
bool IsKeyPressed(int key)
|
||||||
{
|
{
|
||||||
|
if ((key < 0) || (key >= MAX_KEYBOARD_KEYS)) return false;
|
||||||
bool pressed = false;
|
bool pressed = false;
|
||||||
|
|
||||||
if ((CORE.Input.Keyboard.previousKeyState[key] == 0) && (CORE.Input.Keyboard.currentKeyState[key] == 1)) pressed = true;
|
if ((CORE.Input.Keyboard.previousKeyState[key] == 0) && (CORE.Input.Keyboard.currentKeyState[key] == 1)) pressed = true;
|
||||||
|
|
@ -3740,9 +3761,18 @@ bool IsKeyPressed(int key)
|
||||||
return pressed;
|
return pressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if a key has been pressed again (only PLATFORM_DESKTOP)
|
||||||
|
bool IsKeyPressedRepeat(int key)
|
||||||
|
{
|
||||||
|
if ((key < 0) || (key >= MAX_KEYBOARD_KEYS)) return false;
|
||||||
|
if (CORE.Input.Keyboard.keyRepeatInFrame[key] == 1) return true;
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if a key is being pressed (key held down)
|
// Check if a key is being pressed (key held down)
|
||||||
bool IsKeyDown(int key)
|
bool IsKeyDown(int key)
|
||||||
{
|
{
|
||||||
|
if ((key < 0) || (key >= MAX_KEYBOARD_KEYS)) return false;
|
||||||
if (CORE.Input.Keyboard.currentKeyState[key] == 1) return true;
|
if (CORE.Input.Keyboard.currentKeyState[key] == 1) return true;
|
||||||
else return false;
|
else return false;
|
||||||
}
|
}
|
||||||
|
|
@ -3750,6 +3780,7 @@ bool IsKeyDown(int key)
|
||||||
// Check if a key has been released once
|
// Check if a key has been released once
|
||||||
bool IsKeyReleased(int key)
|
bool IsKeyReleased(int key)
|
||||||
{
|
{
|
||||||
|
if ((key < 0) || (key >= MAX_KEYBOARD_KEYS)) return false;
|
||||||
bool released = false;
|
bool released = false;
|
||||||
|
|
||||||
if ((CORE.Input.Keyboard.previousKeyState[key] == 1) && (CORE.Input.Keyboard.currentKeyState[key] == 0)) released = true;
|
if ((CORE.Input.Keyboard.previousKeyState[key] == 1) && (CORE.Input.Keyboard.currentKeyState[key] == 0)) released = true;
|
||||||
|
|
@ -3760,6 +3791,7 @@ bool IsKeyReleased(int key)
|
||||||
// Check if a key is NOT being pressed (key not held down)
|
// Check if a key is NOT being pressed (key not held down)
|
||||||
bool IsKeyUp(int key)
|
bool IsKeyUp(int key)
|
||||||
{
|
{
|
||||||
|
if ((key < 0) || (key >= MAX_KEYBOARD_KEYS)) return false;
|
||||||
if (CORE.Input.Keyboard.currentKeyState[key] == 0) return true;
|
if (CORE.Input.Keyboard.currentKeyState[key] == 0) return true;
|
||||||
else return false;
|
else return false;
|
||||||
}
|
}
|
||||||
|
|
@ -4001,7 +4033,7 @@ Vector2 GetMousePosition(void)
|
||||||
{
|
{
|
||||||
Vector2 position = { 0 };
|
Vector2 position = { 0 };
|
||||||
|
|
||||||
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB)
|
#if defined(PLATFORM_ANDROID) //|| defined(PLATFORM_WEB)
|
||||||
position = GetTouchPosition(0);
|
position = GetTouchPosition(0);
|
||||||
#else
|
#else
|
||||||
position.x = (CORE.Input.Mouse.currentPosition.x + CORE.Input.Mouse.offset.x)*CORE.Input.Mouse.scale.x;
|
position.x = (CORE.Input.Mouse.currentPosition.x + CORE.Input.Mouse.offset.x)*CORE.Input.Mouse.scale.x;
|
||||||
|
|
@ -4262,9 +4294,9 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Profiles Hint: Only 3.3 and above!
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Profiles Hint: Only 3.3 and above!
|
||||||
// Values: GLFW_OPENGL_CORE_PROFILE, GLFW_OPENGL_ANY_PROFILE, GLFW_OPENGL_COMPAT_PROFILE
|
// Values: GLFW_OPENGL_CORE_PROFILE, GLFW_OPENGL_ANY_PROFILE, GLFW_OPENGL_COMPAT_PROFILE
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE); // OSX Requires fordward compatibility
|
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE); // OSX Requires forward compatibility
|
||||||
#else
|
#else
|
||||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_FALSE); // Fordward Compatibility Hint: Only 3.3 and above!
|
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_FALSE); // Forward Compatibility Hint: Only 3.3 and above!
|
||||||
#endif
|
#endif
|
||||||
//glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE); // Request OpenGL DEBUG context
|
//glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE); // Request OpenGL DEBUG context
|
||||||
}
|
}
|
||||||
|
|
@ -4446,13 +4478,16 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Try to enable GPU V-Sync, so frames are limited to screen refresh rate (60Hz -> 60 FPS)
|
// Try to enable GPU V-Sync, so frames are limited to screen refresh rate (60Hz -> 60 FPS)
|
||||||
// NOTE: V-Sync can be enabled by graphic driver configuration
|
// NOTE: V-Sync can be enabled by graphic driver configuration, it doesn't need
|
||||||
|
// to be activated on web platforms since VSync is enforced there.
|
||||||
|
#if !defined(PLATFORM_WEB)
|
||||||
if (CORE.Window.flags & FLAG_VSYNC_HINT)
|
if (CORE.Window.flags & FLAG_VSYNC_HINT)
|
||||||
{
|
{
|
||||||
// WARNING: It seems to hit a critical render path in Intel HD Graphics
|
// WARNING: It seems to hit a critical render path in Intel HD Graphics
|
||||||
glfwSwapInterval(1);
|
glfwSwapInterval(1);
|
||||||
TRACELOG(LOG_INFO, "DISPLAY: Trying to enable VSYNC");
|
TRACELOG(LOG_INFO, "DISPLAY: Trying to enable VSYNC");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int fbWidth = CORE.Window.screen.width;
|
int fbWidth = CORE.Window.screen.width;
|
||||||
int fbHeight = CORE.Window.screen.height;
|
int fbHeight = CORE.Window.screen.height;
|
||||||
|
|
@ -5092,6 +5127,8 @@ void PollInputEvents(void)
|
||||||
// Reset keys/chars pressed registered
|
// Reset keys/chars pressed registered
|
||||||
CORE.Input.Keyboard.keyPressedQueueCount = 0;
|
CORE.Input.Keyboard.keyPressedQueueCount = 0;
|
||||||
CORE.Input.Keyboard.charPressedQueueCount = 0;
|
CORE.Input.Keyboard.charPressedQueueCount = 0;
|
||||||
|
// Reset key repeats
|
||||||
|
for (int i = 0; i < MAX_KEYBOARD_KEYS; i++) CORE.Input.Keyboard.keyRepeatInFrame[i] = 0;
|
||||||
|
|
||||||
// Reset last gamepad button/axis registered state
|
// Reset last gamepad button/axis registered state
|
||||||
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
|
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
|
||||||
|
|
@ -5099,7 +5136,11 @@ void PollInputEvents(void)
|
||||||
|
|
||||||
#if defined(PLATFORM_DRM)
|
#if defined(PLATFORM_DRM)
|
||||||
// Register previous keys states
|
// Register previous keys states
|
||||||
for (int i = 0; i < MAX_KEYBOARD_KEYS; i++) CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i];
|
for (int i = 0; i < MAX_KEYBOARD_KEYS; i++)
|
||||||
|
{
|
||||||
|
CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i];
|
||||||
|
CORE.Input.Keyboard.keyRepeatInFrame[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
PollKeyboardEvents();
|
PollKeyboardEvents();
|
||||||
|
|
||||||
|
|
@ -5128,7 +5169,11 @@ void PollInputEvents(void)
|
||||||
// Keyboard/Mouse input polling (automatically managed by GLFW3 through callback)
|
// Keyboard/Mouse input polling (automatically managed by GLFW3 through callback)
|
||||||
|
|
||||||
// Register previous keys states
|
// Register previous keys states
|
||||||
for (int i = 0; i < MAX_KEYBOARD_KEYS; i++) CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i];
|
for (int i = 0; i < MAX_KEYBOARD_KEYS; i++)
|
||||||
|
{
|
||||||
|
CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i];
|
||||||
|
CORE.Input.Keyboard.keyRepeatInFrame[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Register previous mouse states
|
// Register previous mouse states
|
||||||
for (int i = 0; i < MAX_MOUSE_BUTTONS; i++) CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i];
|
for (int i = 0; i < MAX_MOUSE_BUTTONS; i++) CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i];
|
||||||
|
|
@ -5310,7 +5355,11 @@ void PollInputEvents(void)
|
||||||
#if defined(PLATFORM_ANDROID)
|
#if defined(PLATFORM_ANDROID)
|
||||||
// Register previous keys states
|
// Register previous keys states
|
||||||
// NOTE: Android supports up to 260 keys
|
// NOTE: Android supports up to 260 keys
|
||||||
for (int i = 0; i < 260; i++) CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i];
|
for (int i = 0; i < 260; i++)
|
||||||
|
{
|
||||||
|
CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i];
|
||||||
|
CORE.Input.Keyboard.keyRepeatInFrame[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Android ALooper_pollAll() variables
|
// Android ALooper_pollAll() variables
|
||||||
int pollResult = 0;
|
int pollResult = 0;
|
||||||
|
|
@ -5506,7 +5555,8 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
|
||||||
// WARNING: GLFW could return GLFW_REPEAT, we need to consider it as 1
|
// WARNING: GLFW could return GLFW_REPEAT, we need to consider it as 1
|
||||||
// to work properly with our implementation (IsKeyDown/IsKeyUp checks)
|
// to work properly with our implementation (IsKeyDown/IsKeyUp checks)
|
||||||
if (action == GLFW_RELEASE) CORE.Input.Keyboard.currentKeyState[key] = 0;
|
if (action == GLFW_RELEASE) CORE.Input.Keyboard.currentKeyState[key] = 0;
|
||||||
else CORE.Input.Keyboard.currentKeyState[key] = 1;
|
else if(action == GLFW_PRESS) CORE.Input.Keyboard.currentKeyState[key] = 1;
|
||||||
|
else if(action == GLFW_REPEAT) CORE.Input.Keyboard.keyRepeatInFrame[key] = 1;
|
||||||
|
|
||||||
#if !defined(PLATFORM_WEB)
|
#if !defined(PLATFORM_WEB)
|
||||||
// WARNING: Check if CAPS/NUM key modifiers are enabled and force down state for those keys
|
// WARNING: Check if CAPS/NUM key modifiers are enabled and force down state for those keys
|
||||||
|
|
@ -5810,7 +5860,7 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
|
||||||
} break;
|
} break;
|
||||||
case APP_CMD_TERM_WINDOW:
|
case APP_CMD_TERM_WINDOW:
|
||||||
{
|
{
|
||||||
// Dettach OpenGL context and destroy display surface
|
// Detach OpenGL context and destroy display surface
|
||||||
// NOTE 1: This case is used when the user exits the app without closing it. We detach the context to ensure everything is recoverable upon resuming.
|
// NOTE 1: This case is used when the user exits the app without closing it. We detach the context to ensure everything is recoverable upon resuming.
|
||||||
// NOTE 2: Detaching context before destroying display surface avoids losing our resources (textures, shaders, VBOs...)
|
// NOTE 2: Detaching context before destroying display surface avoids losing our resources (textures, shaders, VBOs...)
|
||||||
// NOTE 3: In some cases (too many context loaded), OS could unload context automatically... :(
|
// NOTE 3: In some cases (too many context loaded), OS could unload context automatically... :(
|
||||||
|
|
@ -5974,6 +6024,7 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
||||||
CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = keycode;
|
CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = keycode;
|
||||||
CORE.Input.Keyboard.keyPressedQueueCount++;
|
CORE.Input.Keyboard.keyPressedQueueCount++;
|
||||||
}
|
}
|
||||||
|
else if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_MULTIPLE) CORE.Input.Keyboard.keyRepeatInFrame[keycode] = 1;
|
||||||
else CORE.Input.Keyboard.currentKeyState[keycode] = 0; // Key up
|
else CORE.Input.Keyboard.currentKeyState[keycode] = 0; // Key up
|
||||||
|
|
||||||
if (keycode == AKEYCODE_POWER)
|
if (keycode == AKEYCODE_POWER)
|
||||||
|
|
@ -6277,7 +6328,11 @@ static void ProcessKeyboard(void)
|
||||||
bufferByteCount = read(STDIN_FILENO, keysBuffer, MAX_KEYBUFFER_SIZE); // POSIX system call
|
bufferByteCount = read(STDIN_FILENO, keysBuffer, MAX_KEYBUFFER_SIZE); // POSIX system call
|
||||||
|
|
||||||
// Reset pressed keys array (it will be filled below)
|
// Reset pressed keys array (it will be filled below)
|
||||||
for (int i = 0; i < MAX_KEYBOARD_KEYS; i++) CORE.Input.Keyboard.currentKeyState[i] = 0;
|
for (int i = 0; i < MAX_KEYBOARD_KEYS; i++)
|
||||||
|
{
|
||||||
|
CORE.Input.Keyboard.currentKeyState[i] = 0;
|
||||||
|
CORE.Input.Keyboard.keyRepeatInFrame[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Fill all read bytes (looking for keys)
|
// Fill all read bytes (looking for keys)
|
||||||
for (int i = 0; i < bufferByteCount; i++)
|
for (int i = 0; i < bufferByteCount; i++)
|
||||||
|
|
@ -6393,7 +6448,11 @@ static void InitEvdevInput(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset keyboard key state
|
// Reset keyboard key state
|
||||||
for (int i = 0; i < MAX_KEYBOARD_KEYS; i++) CORE.Input.Keyboard.currentKeyState[i] = 0;
|
for (int i = 0; i < MAX_KEYBOARD_KEYS; i++)
|
||||||
|
{
|
||||||
|
CORE.Input.Keyboard.currentKeyState[i] = 0;
|
||||||
|
CORE.Input.Keyboard.keyRepeatInFrame[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Open the linux directory of "/dev/input"
|
// Open the linux directory of "/dev/input"
|
||||||
directory = opendir(DEFAULT_EVDEV_PATH);
|
directory = opendir(DEFAULT_EVDEV_PATH);
|
||||||
|
|
@ -6495,7 +6554,7 @@ static void ConfigureEvdevDevice(char *device)
|
||||||
{
|
{
|
||||||
ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absBits)), absBits);
|
ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absBits)), absBits);
|
||||||
|
|
||||||
// Check for absolute movement support (usualy touchscreens, but also joysticks)
|
// Check for absolute movement support (usually touchscreens, but also joysticks)
|
||||||
if (TEST_BIT(absBits, ABS_X) && TEST_BIT(absBits, ABS_Y))
|
if (TEST_BIT(absBits, ABS_X) && TEST_BIT(absBits, ABS_Y))
|
||||||
{
|
{
|
||||||
hasAbs = true;
|
hasAbs = true;
|
||||||
|
|
@ -6509,7 +6568,7 @@ static void ConfigureEvdevDevice(char *device)
|
||||||
worker->absRange.height = absinfo.maximum - absinfo.minimum;
|
worker->absRange.height = absinfo.maximum - absinfo.minimum;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for multiple absolute movement support (usualy multitouch touchscreens)
|
// Check for multiple absolute movement support (usually multitouch touchscreens)
|
||||||
if (TEST_BIT(absBits, ABS_MT_POSITION_X) && TEST_BIT(absBits, ABS_MT_POSITION_Y))
|
if (TEST_BIT(absBits, ABS_MT_POSITION_X) && TEST_BIT(absBits, ABS_MT_POSITION_Y))
|
||||||
{
|
{
|
||||||
hasAbsMulti = true;
|
hasAbsMulti = true;
|
||||||
|
|
@ -6524,7 +6583,7 @@ static void ConfigureEvdevDevice(char *device)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for relative movement support (usualy mouse)
|
// Check for relative movement support (usually mouse)
|
||||||
if (TEST_BIT(evBits, EV_REL))
|
if (TEST_BIT(evBits, EV_REL))
|
||||||
{
|
{
|
||||||
ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relBits)), relBits);
|
ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relBits)), relBits);
|
||||||
|
|
@ -6532,7 +6591,7 @@ static void ConfigureEvdevDevice(char *device)
|
||||||
if (TEST_BIT(relBits, REL_X) && TEST_BIT(relBits, REL_Y)) hasRel = true;
|
if (TEST_BIT(relBits, REL_X) && TEST_BIT(relBits, REL_Y)) hasRel = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for button support to determine the device type(usualy on all input devices)
|
// Check for button support to determine the device type(usually on all input devices)
|
||||||
if (TEST_BIT(evBits, EV_KEY))
|
if (TEST_BIT(evBits, EV_KEY))
|
||||||
{
|
{
|
||||||
ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keyBits)), keyBits);
|
ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keyBits)), keyBits);
|
||||||
|
|
@ -6660,7 +6719,7 @@ static void PollKeyboardEvents(void)
|
||||||
// Keyboard button parsing
|
// Keyboard button parsing
|
||||||
if ((event.code >= 1) && (event.code <= 255)) //Keyboard keys appear for codes 1 to 255
|
if ((event.code >= 1) && (event.code <= 255)) //Keyboard keys appear for codes 1 to 255
|
||||||
{
|
{
|
||||||
keycode = keymapUS[event.code & 0xFF]; // The code we get is a scancode so we look up the apropriate keycode
|
keycode = keymapUS[event.code & 0xFF]; // The code we get is a scancode so we look up the appropriate keycode
|
||||||
|
|
||||||
// Make sure we got a valid keycode
|
// Make sure we got a valid keycode
|
||||||
if ((keycode > 0) && (keycode < sizeof(CORE.Input.Keyboard.currentKeyState)))
|
if ((keycode > 0) && (keycode < sizeof(CORE.Input.Keyboard.currentKeyState)))
|
||||||
|
|
@ -6737,8 +6796,8 @@ static void *EventThread(void *arg)
|
||||||
// Basic movement
|
// Basic movement
|
||||||
if (event.code == ABS_X)
|
if (event.code == ABS_X)
|
||||||
{
|
{
|
||||||
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 according 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 according to absRange
|
||||||
|
|
||||||
touchAction = 2; // TOUCH_ACTION_MOVE
|
touchAction = 2; // TOUCH_ACTION_MOVE
|
||||||
gestureUpdate = true;
|
gestureUpdate = true;
|
||||||
|
|
@ -6746,8 +6805,8 @@ static void *EventThread(void *arg)
|
||||||
|
|
||||||
if (event.code == ABS_Y)
|
if (event.code == ABS_Y)
|
||||||
{
|
{
|
||||||
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 according 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 according to absRange
|
||||||
|
|
||||||
touchAction = 2; // TOUCH_ACTION_MOVE
|
touchAction = 2; // TOUCH_ACTION_MOVE
|
||||||
gestureUpdate = true;
|
gestureUpdate = true;
|
||||||
|
|
@ -6758,12 +6817,12 @@ static void *EventThread(void *arg)
|
||||||
|
|
||||||
if (event.code == ABS_MT_POSITION_X)
|
if (event.code == ABS_MT_POSITION_X)
|
||||||
{
|
{
|
||||||
if (worker->touchSlot < MAX_TOUCH_POINTS) CORE.Input.Touch.position[worker->touchSlot].x = (event.value - worker->absRange.x)*CORE.Window.screen.width/worker->absRange.width; // Scale acording to absRange
|
if (worker->touchSlot < MAX_TOUCH_POINTS) CORE.Input.Touch.position[worker->touchSlot].x = (event.value - worker->absRange.x)*CORE.Window.screen.width/worker->absRange.width; // Scale according to absRange
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.code == ABS_MT_POSITION_Y)
|
if (event.code == ABS_MT_POSITION_Y)
|
||||||
{
|
{
|
||||||
if (worker->touchSlot < MAX_TOUCH_POINTS) CORE.Input.Touch.position[worker->touchSlot].y = (event.value - worker->absRange.y)*CORE.Window.screen.height/worker->absRange.height; // Scale acording to absRange
|
if (worker->touchSlot < MAX_TOUCH_POINTS) CORE.Input.Touch.position[worker->touchSlot].y = (event.value - worker->absRange.y)*CORE.Window.screen.height/worker->absRange.height; // Scale according to absRange
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.code == ABS_MT_TRACKING_ID)
|
if (event.code == ABS_MT_TRACKING_ID)
|
||||||
|
|
|
||||||
|
|
@ -3267,11 +3267,17 @@ void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned
|
||||||
case RL_PIXELFORMAT_UNCOMPRESSED_R32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
|
case RL_PIXELFORMAT_UNCOMPRESSED_R32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
|
||||||
case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
|
case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
|
||||||
case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
|
case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_21)
|
||||||
|
case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_HALF_FLOAT_ARB; break;
|
||||||
|
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT_ARB; break;
|
||||||
|
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT_ARB; break;
|
||||||
|
#else // defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
|
case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
|
||||||
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
|
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
|
||||||
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
|
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#elif defined(GRAPHICS_API_OPENGL_33)
|
#elif defined(GRAPHICS_API_OPENGL_33)
|
||||||
case RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: *glInternalFormat = GL_R8; *glFormat = GL_RED; *glType = GL_UNSIGNED_BYTE; break;
|
case RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: *glInternalFormat = GL_R8; *glFormat = GL_RED; *glType = GL_UNSIGNED_BYTE; break;
|
||||||
case RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: *glInternalFormat = GL_RG8; *glFormat = GL_RG; *glType = GL_UNSIGNED_BYTE; break;
|
case RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: *glInternalFormat = GL_RG8; *glFormat = GL_RG; *glType = GL_UNSIGNED_BYTE; break;
|
||||||
|
|
@ -4544,6 +4550,7 @@ static void rlLoadShaderDefault(void)
|
||||||
#endif
|
#endif
|
||||||
#if defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
"#version 100 \n"
|
"#version 100 \n"
|
||||||
|
"precision mediump float; \n" // Precision required for OpenGL ES2 (WebGL) (on some browsers)
|
||||||
"attribute vec3 vertexPosition; \n"
|
"attribute vec3 vertexPosition; \n"
|
||||||
"attribute vec2 vertexTexCoord; \n"
|
"attribute vec2 vertexTexCoord; \n"
|
||||||
"attribute vec4 vertexColor; \n"
|
"attribute vec4 vertexColor; \n"
|
||||||
|
|
|
||||||
107
src/rmodels.c
|
|
@ -101,19 +101,18 @@
|
||||||
#define PAR_REALLOC(T, BUF, N) ((T*)RL_REALLOC(BUF, sizeof(T)*(N)))
|
#define PAR_REALLOC(T, BUF, N) ((T*)RL_REALLOC(BUF, sizeof(T)*(N)))
|
||||||
#define PAR_FREE RL_FREE
|
#define PAR_FREE RL_FREE
|
||||||
|
|
||||||
#if defined(_MSC_VER ) // par shapes has 2 warnings on windows, so disable them just fof this file
|
#if defined(_MSC_VER) // Disable some MSVC warning
|
||||||
#pragma warning( push )
|
#pragma warning(push)
|
||||||
#pragma warning( disable : 4244)
|
#pragma warning(disable : 4244)
|
||||||
#pragma warning( disable : 4305)
|
#pragma warning(disable : 4305)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PAR_SHAPES_IMPLEMENTATION
|
#define PAR_SHAPES_IMPLEMENTATION
|
||||||
#include "external/par_shapes.h" // Shapes 3d parametric generation
|
#include "external/par_shapes.h" // Shapes 3d parametric generation
|
||||||
|
|
||||||
#if defined(_MSC_VER ) // disable MSVC warning suppression for par shapes
|
#if defined(_MSC_VER)
|
||||||
#pragma warning( pop )
|
#pragma warning(pop) // Disable MSVC warning suppression
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
|
@ -152,18 +151,18 @@ 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 *LoadModelAnimationsIQM(const char *fileName, unsigned int *animCount); // Load IQM animation data
|
static ModelAnimation *LoadModelAnimationsIQM(const char *fileName, 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 *LoadModelAnimationsGLTF(const char *fileName, unsigned int *animCount); // Load GLTF animation data
|
static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCount); // Load GLTF animation data
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_VOX)
|
#if defined(SUPPORT_FILEFORMAT_VOX)
|
||||||
static Model LoadVOX(const char *filename); // Load VOX mesh data
|
static Model LoadVOX(const char *filename); // Load VOX mesh data
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_M3D)
|
#if defined(SUPPORT_FILEFORMAT_M3D)
|
||||||
static Model LoadM3D(const char *filename); // Load M3D mesh data
|
static Model LoadM3D(const char *filename); // Load M3D mesh data
|
||||||
static ModelAnimation *LoadModelAnimationsM3D(const char *fileName, unsigned int *animCount); // Load M3D animation data
|
static ModelAnimation *LoadModelAnimationsM3D(const char *fileName, int *animCount); // Load M3D animation data
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_OBJ) || defined(SUPPORT_FILEFORMAT_MTL)
|
#if defined(SUPPORT_FILEFORMAT_OBJ) || defined(SUPPORT_FILEFORMAT_MTL)
|
||||||
static void ProcessMaterialsOBJ(Material *rayMaterials, tinyobj_material_t *materials, int materialCount); // Process obj materials
|
static void ProcessMaterialsOBJ(Material *rayMaterials, tinyobj_material_t *materials, int materialCount); // Process obj materials
|
||||||
|
|
@ -1905,7 +1904,7 @@ Material *LoadMaterials(const char *fileName, int *materialCount)
|
||||||
int result = tinyobj_parse_mtl_file(&mats, &count, fileName);
|
int result = tinyobj_parse_mtl_file(&mats, &count, fileName);
|
||||||
if (result != TINYOBJ_SUCCESS) TRACELOG(LOG_WARNING, "MATERIAL: [%s] Failed to parse materials file", fileName);
|
if (result != TINYOBJ_SUCCESS) TRACELOG(LOG_WARNING, "MATERIAL: [%s] Failed to parse materials file", fileName);
|
||||||
|
|
||||||
materials = MemAlloc(count*sizeof(Material));
|
materials = RL_MALLOC(count*sizeof(Material));
|
||||||
ProcessMaterialsOBJ(materials, mats, count);
|
ProcessMaterialsOBJ(materials, mats, count);
|
||||||
|
|
||||||
tinyobj_materials_free(mats, count);
|
tinyobj_materials_free(mats, count);
|
||||||
|
|
@ -1980,7 +1979,7 @@ void SetModelMeshMaterial(Model *model, int meshId, int materialId)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load model animations from file
|
// Load model animations from file
|
||||||
ModelAnimation *LoadModelAnimations(const char *fileName, unsigned int *animCount)
|
ModelAnimation *LoadModelAnimations(const char *fileName, int *animCount)
|
||||||
{
|
{
|
||||||
ModelAnimation *animations = NULL;
|
ModelAnimation *animations = NULL;
|
||||||
|
|
||||||
|
|
@ -2100,9 +2099,9 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, int frame)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unload animation array data
|
// Unload animation array data
|
||||||
void UnloadModelAnimations(ModelAnimation *animations, unsigned int count)
|
void UnloadModelAnimations(ModelAnimation *animations, int animCount)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < count; i++) UnloadModelAnimation(animations[i]);
|
for (int i = 0; i < animCount; i++) UnloadModelAnimation(animations[i]);
|
||||||
RL_FREE(animations);
|
RL_FREE(animations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2458,7 +2457,7 @@ Mesh GenMeshCube(float width, float height, float length)
|
||||||
// Platonic solids:
|
// Platonic solids:
|
||||||
par_shapes_mesh* par_shapes_create_tetrahedron(); // 4 sides polyhedron (pyramid)
|
par_shapes_mesh* par_shapes_create_tetrahedron(); // 4 sides polyhedron (pyramid)
|
||||||
par_shapes_mesh* par_shapes_create_cube(); // 6 sides polyhedron (cube)
|
par_shapes_mesh* par_shapes_create_cube(); // 6 sides polyhedron (cube)
|
||||||
par_shapes_mesh* par_shapes_create_octahedron(); // 8 sides polyhedron (dyamond)
|
par_shapes_mesh* par_shapes_create_octahedron(); // 8 sides polyhedron (diamond)
|
||||||
par_shapes_mesh* par_shapes_create_dodecahedron(); // 12 sides polyhedron
|
par_shapes_mesh* par_shapes_create_dodecahedron(); // 12 sides polyhedron
|
||||||
par_shapes_mesh* par_shapes_create_icosahedron(); // 20 sides polyhedron
|
par_shapes_mesh* par_shapes_create_icosahedron(); // 20 sides polyhedron
|
||||||
*/
|
*/
|
||||||
|
|
@ -4082,8 +4081,8 @@ static Model LoadIQM(const char *fileName)
|
||||||
#define MESH_NAME_LENGTH 32 // Mesh name string length
|
#define MESH_NAME_LENGTH 32 // Mesh name string length
|
||||||
#define MATERIAL_NAME_LENGTH 32 // Material name string length
|
#define MATERIAL_NAME_LENGTH 32 // Material name string length
|
||||||
|
|
||||||
unsigned int fileSize = 0;
|
int dataSize = 0;
|
||||||
unsigned char *fileData = LoadFileData(fileName, &fileSize);
|
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
||||||
unsigned char *fileDataPtr = fileData;
|
unsigned char *fileDataPtr = fileData;
|
||||||
|
|
||||||
// IQM file structs
|
// IQM file structs
|
||||||
|
|
@ -4091,7 +4090,7 @@ static Model LoadIQM(const char *fileName)
|
||||||
typedef struct IQMHeader {
|
typedef struct IQMHeader {
|
||||||
char magic[16];
|
char magic[16];
|
||||||
unsigned int version;
|
unsigned int version;
|
||||||
unsigned int filesize;
|
unsigned int dataSize;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
unsigned int num_text, ofs_text;
|
unsigned int num_text, ofs_text;
|
||||||
unsigned int num_meshes, ofs_meshes;
|
unsigned int num_meshes, ofs_meshes;
|
||||||
|
|
@ -4245,7 +4244,7 @@ static Model LoadIQM(const char *fileName)
|
||||||
model.meshes[i].triangleCount = imesh[i].num_triangles;
|
model.meshes[i].triangleCount = imesh[i].num_triangles;
|
||||||
model.meshes[i].indices = RL_CALLOC(model.meshes[i].triangleCount*3, sizeof(unsigned short));
|
model.meshes[i].indices = RL_CALLOC(model.meshes[i].triangleCount*3, sizeof(unsigned short));
|
||||||
|
|
||||||
// Animated verted data, what we actually process for rendering
|
// Animated vertex data, what we actually process for rendering
|
||||||
// NOTE: Animated vertex should be re-uploaded to GPU (if not using GPU skinning)
|
// NOTE: Animated vertex should be re-uploaded to GPU (if not using GPU skinning)
|
||||||
model.meshes[i].animVertices = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));
|
model.meshes[i].animVertices = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));
|
||||||
model.meshes[i].animNormals = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));
|
model.meshes[i].animNormals = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));
|
||||||
|
|
@ -4444,19 +4443,19 @@ static Model LoadIQM(const char *fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load IQM animation data
|
// Load IQM animation data
|
||||||
static ModelAnimation *LoadModelAnimationsIQM(const char *fileName, unsigned int *animCount)
|
static ModelAnimation *LoadModelAnimationsIQM(const char *fileName, 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
|
||||||
|
|
||||||
unsigned int fileSize = 0;
|
int dataSize = 0;
|
||||||
unsigned char *fileData = LoadFileData(fileName, &fileSize);
|
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
||||||
unsigned char *fileDataPtr = fileData;
|
unsigned char *fileDataPtr = fileData;
|
||||||
|
|
||||||
typedef struct IQMHeader {
|
typedef struct IQMHeader {
|
||||||
char magic[16];
|
char magic[16];
|
||||||
unsigned int version;
|
unsigned int version;
|
||||||
unsigned int filesize;
|
unsigned int dataSize;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
unsigned int num_text, ofs_text;
|
unsigned int num_text, ofs_text;
|
||||||
unsigned int num_meshes, ofs_meshes;
|
unsigned int num_meshes, ofs_meshes;
|
||||||
|
|
@ -4705,7 +4704,7 @@ static Image LoadImageFromCgltfImage(cgltf_image *cgltfImage, const char *texPat
|
||||||
if (result == cgltf_result_success)
|
if (result == cgltf_result_success)
|
||||||
{
|
{
|
||||||
image = LoadImageFromMemory(".png", (unsigned char *)data, outSize);
|
image = LoadImageFromMemory(".png", (unsigned char *)data, outSize);
|
||||||
MemFree(data);
|
RL_FREE(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4788,7 +4787,7 @@ static Model LoadGLTF(const char *fileName)
|
||||||
|
|
||||||
RESTRICTIONS:
|
RESTRICTIONS:
|
||||||
- Only triangle meshes supported
|
- Only triangle meshes supported
|
||||||
- Vertex attibute types and formats supported:
|
- Vertex attribute types and formats supported:
|
||||||
> Vertices (position): vec3: float
|
> Vertices (position): vec3: float
|
||||||
> Normals: vec3: float
|
> Normals: vec3: float
|
||||||
> Texcoords: vec2: float
|
> Texcoords: vec2: float
|
||||||
|
|
@ -4816,7 +4815,7 @@ static Model LoadGLTF(const char *fileName)
|
||||||
Model model = { 0 };
|
Model model = { 0 };
|
||||||
|
|
||||||
// glTF file loading
|
// glTF file loading
|
||||||
unsigned int dataSize = 0;
|
int dataSize = 0;
|
||||||
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
||||||
|
|
||||||
if (fileData == NULL) return model;
|
if (fileData == NULL) return model;
|
||||||
|
|
@ -5287,7 +5286,7 @@ static bool GetPoseAtTimeGLTF(cgltf_accessor *input, cgltf_accessor *output, flo
|
||||||
Vector4 v2 = {tmp[0], tmp[1], tmp[2], tmp[3]};
|
Vector4 v2 = {tmp[0], tmp[1], tmp[2], tmp[3]};
|
||||||
Vector4 *r = data;
|
Vector4 *r = data;
|
||||||
|
|
||||||
// Only v4 is for rotations, so we know it's a quat
|
// Only v4 is for rotations, so we know it's a quaternion
|
||||||
*r = QuaternionSlerp(v1, v2, t);
|
*r = QuaternionSlerp(v1, v2, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5296,10 +5295,10 @@ static bool GetPoseAtTimeGLTF(cgltf_accessor *input, cgltf_accessor *output, flo
|
||||||
|
|
||||||
#define GLTF_ANIMDELAY 17 // Animation frames delay, (~1000 ms/60 FPS = 16.666666* ms)
|
#define GLTF_ANIMDELAY 17 // Animation frames delay, (~1000 ms/60 FPS = 16.666666* ms)
|
||||||
|
|
||||||
static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, unsigned int *animCount)
|
static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCount)
|
||||||
{
|
{
|
||||||
// glTF file loading
|
// glTF file loading
|
||||||
unsigned int dataSize = 0;
|
int dataSize = 0;
|
||||||
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
||||||
|
|
||||||
ModelAnimation *animations = NULL;
|
ModelAnimation *animations = NULL;
|
||||||
|
|
@ -5467,11 +5466,11 @@ static Model LoadVOX(const char *fileName)
|
||||||
|
|
||||||
int nbvertices = 0;
|
int nbvertices = 0;
|
||||||
int meshescount = 0;
|
int meshescount = 0;
|
||||||
unsigned int fileSize = 0;
|
|
||||||
unsigned char *fileData = NULL;
|
|
||||||
|
|
||||||
// Read vox file into buffer
|
// Read vox file into buffer
|
||||||
fileData = LoadFileData(fileName, &fileSize);
|
int dataSize = 0;
|
||||||
|
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
||||||
|
|
||||||
if (fileData == 0)
|
if (fileData == 0)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load VOX file", fileName);
|
TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load VOX file", fileName);
|
||||||
|
|
@ -5480,7 +5479,7 @@ static Model LoadVOX(const char *fileName)
|
||||||
|
|
||||||
// Read and build voxarray description
|
// Read and build voxarray description
|
||||||
VoxArray3D voxarray = { 0 };
|
VoxArray3D voxarray = { 0 };
|
||||||
int ret = Vox_LoadFromMemory(fileData, fileSize, &voxarray);
|
int ret = Vox_LoadFromMemory(fileData, dataSize, &voxarray);
|
||||||
|
|
||||||
if (ret != VOX_SUCCESS)
|
if (ret != VOX_SUCCESS)
|
||||||
{
|
{
|
||||||
|
|
@ -5575,9 +5574,10 @@ static Model LoadM3D(const char *fileName)
|
||||||
|
|
||||||
m3d_t *m3d = NULL;
|
m3d_t *m3d = NULL;
|
||||||
m3dp_t *prop = NULL;
|
m3dp_t *prop = NULL;
|
||||||
unsigned int bytesRead = 0;
|
int i, j, k, l, n, mi = -2, vcolor = 0;
|
||||||
unsigned char *fileData = LoadFileData(fileName, &bytesRead);
|
|
||||||
int i, j, k, l, n, mi = -2;
|
int dataSize = 0;
|
||||||
|
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
||||||
|
|
||||||
if (fileData != NULL)
|
if (fileData != NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -5607,10 +5607,13 @@ static Model LoadM3D(const char *fileName)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
model.meshCount = model.materialCount = 1;
|
model.meshCount = 1; model.materialCount = 0;
|
||||||
TRACELOG(LOG_INFO, "MODEL: No materials, putting all meshes in a default material");
|
TRACELOG(LOG_INFO, "MODEL: No materials, putting all meshes in a default material");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We always need a default material, so we add +1
|
||||||
|
model.materialCount++;
|
||||||
|
|
||||||
model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));
|
model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));
|
||||||
model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
|
model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
|
||||||
model.materials = (Material *)RL_CALLOC(model.materialCount + 1, sizeof(Material));
|
model.materials = (Material *)RL_CALLOC(model.materialCount + 1, sizeof(Material));
|
||||||
|
|
@ -5635,7 +5638,14 @@ static Model LoadM3D(const char *fileName)
|
||||||
k++;
|
k++;
|
||||||
mi = m3d->face[i].materialid;
|
mi = m3d->face[i].materialid;
|
||||||
|
|
||||||
for (j = i, l = 0; (j < (int)m3d->numface) && (mi == m3d->face[j].materialid); j++, l++);
|
// Only allocate colors VertexBuffer if there's a color vertex in the model for this material batch
|
||||||
|
// if all colors are fully transparent black for all verteces of this materal, then we assume no vertex colors
|
||||||
|
for (j = i, l = vcolor = 0; (j < (int)m3d->numface) && (mi == m3d->face[j].materialid); j++, l++)
|
||||||
|
{
|
||||||
|
if (!m3d->vertex[m3d->face[j].vertex[0]].color ||
|
||||||
|
!m3d->vertex[m3d->face[j].vertex[1]].color ||
|
||||||
|
!m3d->vertex[m3d->face[j].vertex[2]].color) vcolor = 1;
|
||||||
|
}
|
||||||
|
|
||||||
model.meshes[k].vertexCount = l*3;
|
model.meshes[k].vertexCount = l*3;
|
||||||
model.meshes[k].triangleCount = l;
|
model.meshes[k].triangleCount = l;
|
||||||
|
|
@ -5643,9 +5653,9 @@ static Model LoadM3D(const char *fileName)
|
||||||
model.meshes[k].texcoords = (float *)RL_CALLOC(model.meshes[k].vertexCount*2, sizeof(float));
|
model.meshes[k].texcoords = (float *)RL_CALLOC(model.meshes[k].vertexCount*2, sizeof(float));
|
||||||
model.meshes[k].normals = (float *)RL_CALLOC(model.meshes[k].vertexCount*3, sizeof(float));
|
model.meshes[k].normals = (float *)RL_CALLOC(model.meshes[k].vertexCount*3, sizeof(float));
|
||||||
|
|
||||||
// If no map is provided, we allocate storage for vertex colors
|
// If no map is provided, or we have colors defined, we allocate storage for vertex colors
|
||||||
// M3D specs only consider vertex colors if no material is provided
|
// M3D specs only consider vertex colors if no material is provided, however raylib uses both and mixes the colors
|
||||||
if (mi != M3D_UNDEF) model.meshes[k].colors = RL_CALLOC(model.meshes[k].vertexCount*4, sizeof(unsigned char));
|
if ((mi == M3D_UNDEF) || vcolor) model.meshes[k].colors = RL_CALLOC(model.meshes[k].vertexCount*4, sizeof(unsigned char));
|
||||||
|
|
||||||
if (m3d->numbone && m3d->numskin)
|
if (m3d->numbone && m3d->numskin)
|
||||||
{
|
{
|
||||||
|
|
@ -5869,16 +5879,17 @@ static Model LoadM3D(const char *fileName)
|
||||||
#define M3D_ANIMDELAY 17 // Animation frames delay, (~1000 ms/60 FPS = 16.666666* ms)
|
#define M3D_ANIMDELAY 17 // Animation frames delay, (~1000 ms/60 FPS = 16.666666* ms)
|
||||||
|
|
||||||
// Load M3D animation data
|
// Load M3D animation data
|
||||||
static ModelAnimation *LoadModelAnimationsM3D(const char *fileName, unsigned int *animCount)
|
static ModelAnimation *LoadModelAnimationsM3D(const char *fileName, int *animCount)
|
||||||
{
|
{
|
||||||
m3d_t *m3d = NULL;
|
|
||||||
unsigned int bytesRead = 0;
|
|
||||||
unsigned char *fileData = LoadFileData(fileName, &bytesRead);
|
|
||||||
ModelAnimation *animations = NULL;
|
ModelAnimation *animations = NULL;
|
||||||
int i = 0, j = 0;
|
|
||||||
|
|
||||||
|
m3d_t *m3d = NULL;
|
||||||
|
int i = 0, j = 0;
|
||||||
*animCount = 0;
|
*animCount = 0;
|
||||||
|
|
||||||
|
int dataSize = 0;
|
||||||
|
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
||||||
|
|
||||||
if (fileData != NULL)
|
if (fileData != NULL)
|
||||||
{
|
{
|
||||||
m3d = m3d_load(fileData, m3d_loaderhook, m3d_freehook, NULL);
|
m3d = m3d_load(fileData, m3d_loaderhook, m3d_freehook, NULL);
|
||||||
|
|
|
||||||
275
src/rshapes.c
|
|
@ -67,8 +67,8 @@
|
||||||
#ifndef SMOOTH_CIRCLE_ERROR_RATE
|
#ifndef SMOOTH_CIRCLE_ERROR_RATE
|
||||||
#define SMOOTH_CIRCLE_ERROR_RATE 0.5f // Circle error rate
|
#define SMOOTH_CIRCLE_ERROR_RATE 0.5f // Circle error rate
|
||||||
#endif
|
#endif
|
||||||
#ifndef BEZIER_LINE_DIVISIONS
|
#ifndef SPLINE_LINE_DIVISIONS
|
||||||
#define BEZIER_LINE_DIVISIONS 24 // Bezier line divisions
|
#define SPLINE_LINE_DIVISIONS 24 // Spline lines segment divisions
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -99,7 +99,7 @@ void SetShapesTexture(Texture2D texture, Rectangle source)
|
||||||
{
|
{
|
||||||
// Reset texture to default pixel if required
|
// Reset texture to default pixel if required
|
||||||
// WARNING: Shapes texture should be probably better validated,
|
// WARNING: Shapes texture should be probably better validated,
|
||||||
// it can break the rendering of all shapes if missused
|
// it can break the rendering of all shapes if misused
|
||||||
if ((texture.id == 0) || (source.width == 0) || (source.height == 0))
|
if ((texture.id == 0) || (source.width == 0) || (source.height == 0))
|
||||||
{
|
{
|
||||||
texShapes = (Texture2D){ 1, 1, 1, 1, 7 };
|
texShapes = (Texture2D){ 1, 1, 1, 1, 7 };
|
||||||
|
|
@ -190,6 +190,7 @@ void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color)
|
||||||
if ((length > 0) && (thick > 0))
|
if ((length > 0) && (thick > 0))
|
||||||
{
|
{
|
||||||
float scale = thick/(2*length);
|
float scale = thick/(2*length);
|
||||||
|
|
||||||
Vector2 radius = { -scale*delta.y, scale*delta.x };
|
Vector2 radius = { -scale*delta.y, scale*delta.x };
|
||||||
Vector2 strip[4] = {
|
Vector2 strip[4] = {
|
||||||
{ startPos.x - radius.x, startPos.y - radius.y },
|
{ startPos.x - radius.x, startPos.y - radius.y },
|
||||||
|
|
@ -208,126 +209,270 @@ void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color)
|
||||||
Vector2 previous = startPos;
|
Vector2 previous = startPos;
|
||||||
Vector2 current = { 0 };
|
Vector2 current = { 0 };
|
||||||
|
|
||||||
Vector2 points[2*BEZIER_LINE_DIVISIONS + 2] = { 0 };
|
Vector2 points[2*SPLINE_LINE_DIVISIONS + 2] = { 0 };
|
||||||
|
|
||||||
for (int i = 1; i <= BEZIER_LINE_DIVISIONS; i++)
|
for (int i = 1; i <= SPLINE_LINE_DIVISIONS; i++)
|
||||||
{
|
{
|
||||||
// Cubic easing in-out
|
// Cubic easing in-out
|
||||||
// NOTE: Easing is calculated only for y position value
|
// NOTE: Easing is calculated only for y position value
|
||||||
current.y = EaseCubicInOut((float)i, startPos.y, endPos.y - startPos.y, (float)BEZIER_LINE_DIVISIONS);
|
current.y = EaseCubicInOut((float)i, startPos.y, endPos.y - startPos.y, (float)SPLINE_LINE_DIVISIONS);
|
||||||
current.x = previous.x + (endPos.x - startPos.x)/ (float)BEZIER_LINE_DIVISIONS;
|
current.x = previous.x + (endPos.x - startPos.x)/(float)SPLINE_LINE_DIVISIONS;
|
||||||
|
|
||||||
float dy = current.y-previous.y;
|
float dy = current.y - previous.y;
|
||||||
float dx = current.x-previous.x;
|
float dx = current.x - previous.x;
|
||||||
float size = 0.5f*thick/sqrtf(dx*dx+dy*dy);
|
float size = 0.5f*thick/sqrtf(dx*dx+dy*dy);
|
||||||
|
|
||||||
if (i==1)
|
if (i == 1)
|
||||||
{
|
{
|
||||||
points[0].x = previous.x+dy*size;
|
points[0].x = previous.x + dy*size;
|
||||||
points[0].y = previous.y-dx*size;
|
points[0].y = previous.y - dx*size;
|
||||||
points[1].x = previous.x-dy*size;
|
points[1].x = previous.x - dy*size;
|
||||||
points[1].y = previous.y+dx*size;
|
points[1].y = previous.y + dx*size;
|
||||||
}
|
}
|
||||||
|
|
||||||
points[2*i+1].x = current.x-dy*size;
|
points[2*i + 1].x = current.x - dy*size;
|
||||||
points[2*i+1].y = current.y+dx*size;
|
points[2*i + 1].y = current.y + dx*size;
|
||||||
points[2*i].x = current.x+dy*size;
|
points[2*i].x = current.x + dy*size;
|
||||||
points[2*i].y = current.y-dx*size;
|
points[2*i].y = current.y - dx*size;
|
||||||
|
|
||||||
previous = current;
|
previous = current;
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawTriangleStrip(points, 2*BEZIER_LINE_DIVISIONS+2, color);
|
DrawTriangleStrip(points, 2*SPLINE_LINE_DIVISIONS + 2, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw line using quadratic bezier curves with a control point
|
// Draw line using quadratic bezier curves with a control point
|
||||||
void DrawLineBezierQuad(Vector2 startPos, Vector2 endPos, Vector2 controlPos, float thick, Color color)
|
void DrawLineBezierQuad(Vector2 startPos, Vector2 endPos, Vector2 controlPos, float thick, Color color)
|
||||||
{
|
{
|
||||||
const float step = 1.0f/BEZIER_LINE_DIVISIONS;
|
const float step = 1.0f/SPLINE_LINE_DIVISIONS;
|
||||||
|
|
||||||
Vector2 previous = startPos;
|
Vector2 previous = startPos;
|
||||||
Vector2 current = { 0 };
|
Vector2 current = { 0 };
|
||||||
float t = 0.0f;
|
float t = 0.0f;
|
||||||
|
|
||||||
Vector2 points[2*BEZIER_LINE_DIVISIONS + 2] = { 0 };
|
Vector2 points[2*SPLINE_LINE_DIVISIONS + 2] = { 0 };
|
||||||
|
|
||||||
for (int i = 1; i <= BEZIER_LINE_DIVISIONS; i++)
|
for (int i = 1; i <= SPLINE_LINE_DIVISIONS; i++)
|
||||||
{
|
{
|
||||||
t = step*i;
|
t = step*i;
|
||||||
float a = powf(1 - t, 2);
|
|
||||||
float b = 2*(1 - t)*t;
|
float a = powf(1.0f - t, 2);
|
||||||
|
float b = 2.0f*(1.0f - t)*t;
|
||||||
float c = powf(t, 2);
|
float c = powf(t, 2);
|
||||||
|
|
||||||
// NOTE: The easing functions aren't suitable here because they don't take a control point
|
// NOTE: The easing functions aren't suitable here because they don't take a control point
|
||||||
current.y = a*startPos.y + b*controlPos.y + c*endPos.y;
|
current.y = a*startPos.y + b*controlPos.y + c*endPos.y;
|
||||||
current.x = a*startPos.x + b*controlPos.x + c*endPos.x;
|
current.x = a*startPos.x + b*controlPos.x + c*endPos.x;
|
||||||
|
|
||||||
float dy = current.y-previous.y;
|
float dy = current.y - previous.y;
|
||||||
float dx = current.x-previous.x;
|
float dx = current.x - previous.x;
|
||||||
float size = 0.5f*thick/sqrtf(dx*dx+dy*dy);
|
float size = 0.5f*thick/sqrtf(dx*dx+dy*dy);
|
||||||
|
|
||||||
if (i==1)
|
if (i == 1)
|
||||||
{
|
{
|
||||||
points[0].x = previous.x+dy*size;
|
points[0].x = previous.x + dy*size;
|
||||||
points[0].y = previous.y-dx*size;
|
points[0].y = previous.y - dx*size;
|
||||||
points[1].x = previous.x-dy*size;
|
points[1].x = previous.x - dy*size;
|
||||||
points[1].y = previous.y+dx*size;
|
points[1].y = previous.y + dx*size;
|
||||||
}
|
}
|
||||||
|
|
||||||
points[2*i+1].x = current.x-dy*size;
|
points[2*i + 1].x = current.x - dy*size;
|
||||||
points[2*i+1].y = current.y+dx*size;
|
points[2*i + 1].y = current.y + dx*size;
|
||||||
points[2*i].x = current.x+dy*size;
|
points[2*i].x = current.x + dy*size;
|
||||||
points[2*i].y = current.y-dx*size;
|
points[2*i].y = current.y - dx*size;
|
||||||
|
|
||||||
previous = current;
|
previous = current;
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawTriangleStrip(points, 2*BEZIER_LINE_DIVISIONS+2, color);
|
DrawTriangleStrip(points, 2*SPLINE_LINE_DIVISIONS + 2, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw line using cubic bezier curves with 2 control points
|
// Draw line using cubic bezier curves with 2 control points
|
||||||
void DrawLineBezierCubic(Vector2 startPos, Vector2 endPos, Vector2 startControlPos, Vector2 endControlPos, float thick, Color color)
|
void DrawLineBezierCubic(Vector2 startPos, Vector2 endPos, Vector2 startControlPos, Vector2 endControlPos, float thick, Color color)
|
||||||
{
|
{
|
||||||
const float step = 1.0f/BEZIER_LINE_DIVISIONS;
|
const float step = 1.0f/SPLINE_LINE_DIVISIONS;
|
||||||
|
|
||||||
Vector2 previous = startPos;
|
Vector2 previous = startPos;
|
||||||
Vector2 current = { 0 };
|
Vector2 current = { 0 };
|
||||||
float t = 0.0f;
|
float t = 0.0f;
|
||||||
|
|
||||||
Vector2 points[2*BEZIER_LINE_DIVISIONS + 2] = { 0 };
|
Vector2 points[2*SPLINE_LINE_DIVISIONS + 2] = { 0 };
|
||||||
|
|
||||||
for (int i = 1; i <= BEZIER_LINE_DIVISIONS; i++)
|
for (int i = 1; i <= SPLINE_LINE_DIVISIONS; i++)
|
||||||
{
|
{
|
||||||
t = step*i;
|
t = step*i;
|
||||||
float a = powf(1 - t, 3);
|
|
||||||
float b = 3*powf(1 - t, 2)*t;
|
float a = powf(1.0f - t, 3);
|
||||||
float c = 3*(1-t)*powf(t, 2);
|
float b = 3.0f*powf(1.0f - t, 2)*t;
|
||||||
|
float c = 3.0f*(1.0f - t)*powf(t, 2);
|
||||||
float d = powf(t, 3);
|
float d = powf(t, 3);
|
||||||
|
|
||||||
current.y = a*startPos.y + b*startControlPos.y + c*endControlPos.y + d*endPos.y;
|
current.y = a*startPos.y + b*startControlPos.y + c*endControlPos.y + d*endPos.y;
|
||||||
current.x = a*startPos.x + b*startControlPos.x + c*endControlPos.x + d*endPos.x;
|
current.x = a*startPos.x + b*startControlPos.x + c*endControlPos.x + d*endPos.x;
|
||||||
|
|
||||||
float dy = current.y-previous.y;
|
float dy = current.y - previous.y;
|
||||||
float dx = current.x-previous.x;
|
float dx = current.x - previous.x;
|
||||||
float size = 0.5f*thick/sqrtf(dx*dx+dy*dy);
|
float size = 0.5f*thick/sqrtf(dx*dx+dy*dy);
|
||||||
|
|
||||||
if (i==1)
|
if (i == 1)
|
||||||
{
|
{
|
||||||
points[0].x = previous.x+dy*size;
|
points[0].x = previous.x + dy*size;
|
||||||
points[0].y = previous.y-dx*size;
|
points[0].y = previous.y - dx*size;
|
||||||
points[1].x = previous.x-dy*size;
|
points[1].x = previous.x - dy*size;
|
||||||
points[1].y = previous.y+dx*size;
|
points[1].y = previous.y + dx*size;
|
||||||
}
|
}
|
||||||
|
|
||||||
points[2*i+1].x = current.x-dy*size;
|
points[2*i + 1].x = current.x - dy*size;
|
||||||
points[2*i+1].y = current.y+dx*size;
|
points[2*i + 1].y = current.y + dx*size;
|
||||||
points[2*i].x = current.x+dy*size;
|
points[2*i].x = current.x + dy*size;
|
||||||
points[2*i].y = current.y-dx*size;
|
points[2*i].y = current.y - dx*size;
|
||||||
|
|
||||||
previous = current;
|
previous = current;
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawTriangleStrip(points, 2*BEZIER_LINE_DIVISIONS+2, color);
|
DrawTriangleStrip(points, 2*SPLINE_LINE_DIVISIONS + 2, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a B-Spline line, minimum 4 points
|
||||||
|
void DrawLineBSpline(Vector2 *points, int pointCount, float thick, Color color)
|
||||||
|
{
|
||||||
|
if (pointCount < 4) return;
|
||||||
|
|
||||||
|
float a[4] = { 0 };
|
||||||
|
float b[4] = { 0 };
|
||||||
|
float dy = 0.0f;
|
||||||
|
float dx = 0.0f;
|
||||||
|
float size = 0.0f;
|
||||||
|
|
||||||
|
Vector2 currentPoint = { 0 };
|
||||||
|
Vector2 nextPoint = { 0 };
|
||||||
|
Vector2 vertices[2*SPLINE_LINE_DIVISIONS + 2] = { 0 };
|
||||||
|
|
||||||
|
for (int i = 0; i < (pointCount - 3); i++)
|
||||||
|
{
|
||||||
|
float t = 0.0f;
|
||||||
|
Vector2 p1 = points[i], p2 = points[i + 1], p3 = points[i + 2], p4 = points[i + 3];
|
||||||
|
|
||||||
|
a[0] = (-p1.x + 3.0f*p2.x - 3.0f*p3.x + p4.x)/6.0f;
|
||||||
|
a[1] = (3.0f*p1.x - 6.0f*p2.x + 3.0f*p3.x)/6.0f;
|
||||||
|
a[2] = (-3.0f*p1.x + 3.0f*p3.x)/6.0f;
|
||||||
|
a[3] = (p1.x + 4.0f*p2.x + p3.x)/6.0f;
|
||||||
|
|
||||||
|
b[0] = (-p1.y + 3.0f*p2.y - 3.0f*p3.y + p4.y)/6.0f;
|
||||||
|
b[1] = (3.0f*p1.y - 6.0f*p2.y + 3.0f*p3.y)/6.0f;
|
||||||
|
b[2] = (-3.0f*p1.y + 3.0f*p3.y)/6.0f;
|
||||||
|
b[3] = (p1.y + 4.0f*p2.y + p3.y)/6.0f;
|
||||||
|
|
||||||
|
currentPoint.x = a[3];
|
||||||
|
currentPoint.y = b[3];
|
||||||
|
|
||||||
|
if (i == 0) DrawCircleV(currentPoint, thick/2.0f, color); // Draw init line circle-cap
|
||||||
|
|
||||||
|
if (i > 0)
|
||||||
|
{
|
||||||
|
vertices[0].x = currentPoint.x + dy*size;
|
||||||
|
vertices[0].y = currentPoint.y - dx*size;
|
||||||
|
vertices[1].x = currentPoint.x - dy*size;
|
||||||
|
vertices[1].y = currentPoint.y + dx*size;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 1; j <= SPLINE_LINE_DIVISIONS; j++)
|
||||||
|
{
|
||||||
|
t = ((float)j)/((float)SPLINE_LINE_DIVISIONS);
|
||||||
|
|
||||||
|
nextPoint.x = a[3] + t*(a[2] + t*(a[1] + t*a[0]));
|
||||||
|
nextPoint.y = b[3] + t*(b[2] + t*(b[1] + t*b[0]));
|
||||||
|
|
||||||
|
dy = nextPoint.y - currentPoint.y;
|
||||||
|
dx = nextPoint.x - currentPoint.x;
|
||||||
|
size = 0.5f*thick/sqrtf(dx*dx+dy*dy);
|
||||||
|
|
||||||
|
if ((i == 0) && (j == 1))
|
||||||
|
{
|
||||||
|
vertices[0].x = currentPoint.x + dy*size;
|
||||||
|
vertices[0].y = currentPoint.y - dx*size;
|
||||||
|
vertices[1].x = currentPoint.x - dy*size;
|
||||||
|
vertices[1].y = currentPoint.y + dx*size;
|
||||||
|
}
|
||||||
|
|
||||||
|
vertices[2*j + 1].x = nextPoint.x - dy*size;
|
||||||
|
vertices[2*j + 1].y = nextPoint.y + dx*size;
|
||||||
|
vertices[2*j].x = nextPoint.x + dy*size;
|
||||||
|
vertices[2*j].y = nextPoint.y - dx*size;
|
||||||
|
|
||||||
|
currentPoint = nextPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawTriangleStrip(vertices, 2*SPLINE_LINE_DIVISIONS + 2, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawCircleV(currentPoint, thick/2.0f, color); // Draw end line circle-cap
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a Catmull Rom spline line, minimum 4 points
|
||||||
|
void DrawLineCatmullRom(Vector2 *points, int pointCount, float thick, Color color)
|
||||||
|
{
|
||||||
|
if (pointCount < 4) return;
|
||||||
|
|
||||||
|
float dy = 0.0f;
|
||||||
|
float dx = 0.0f;
|
||||||
|
float size = 0.0f;
|
||||||
|
|
||||||
|
Vector2 currentPoint = points[1];
|
||||||
|
Vector2 nextPoint = { 0 };
|
||||||
|
Vector2 vertices[2*SPLINE_LINE_DIVISIONS + 2] = { 0 };
|
||||||
|
|
||||||
|
DrawCircleV(currentPoint, thick/2.0f, color); // Draw init line circle-cap
|
||||||
|
|
||||||
|
for (int i = 0; i < (pointCount - 3); i++)
|
||||||
|
{
|
||||||
|
float t = 0.0f;
|
||||||
|
Vector2 p1 = points[i], p2 = points[i + 1], p3 = points[i + 2], p4 = points[i + 3];
|
||||||
|
|
||||||
|
if (i > 0)
|
||||||
|
{
|
||||||
|
vertices[0].x = currentPoint.x + dy*size;
|
||||||
|
vertices[0].y = currentPoint.y - dx*size;
|
||||||
|
vertices[1].x = currentPoint.x - dy*size;
|
||||||
|
vertices[1].y = currentPoint.y + dx*size;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 1; j <= SPLINE_LINE_DIVISIONS; j++)
|
||||||
|
{
|
||||||
|
t = ((float)j)/((float)SPLINE_LINE_DIVISIONS);
|
||||||
|
|
||||||
|
float q0 = (-1.0f*t*t*t) + (2.0f*t*t) + (-1.0f*t);
|
||||||
|
float q1 = (3.0f*t*t*t) + (-5.0f*t*t) + 2.0f;
|
||||||
|
float q2 = (-3.0f*t*t*t) + (4.0f*t*t) + t;
|
||||||
|
float q3 = t*t*t - t*t;
|
||||||
|
|
||||||
|
nextPoint.x = 0.5f*((p1.x*q0) + (p2.x*q1) + (p3.x*q2) + (p4.x*q3));
|
||||||
|
nextPoint.y = 0.5f*((p1.y*q0) + (p2.y*q1) + (p3.y*q2) + (p4.y*q3));
|
||||||
|
|
||||||
|
dy = nextPoint.y - currentPoint.y;
|
||||||
|
dx = nextPoint.x - currentPoint.x;
|
||||||
|
size = (0.5f*thick)/sqrtf(dx*dx + dy*dy);
|
||||||
|
|
||||||
|
if ((i == 0) && (j == 1))
|
||||||
|
{
|
||||||
|
vertices[0].x = currentPoint.x + dy*size;
|
||||||
|
vertices[0].y = currentPoint.y - dx*size;
|
||||||
|
vertices[1].x = currentPoint.x - dy*size;
|
||||||
|
vertices[1].y = currentPoint.y + dx*size;
|
||||||
|
}
|
||||||
|
|
||||||
|
vertices[2*j + 1].x = nextPoint.x - dy*size;
|
||||||
|
vertices[2*j + 1].y = nextPoint.y + dx*size;
|
||||||
|
vertices[2*j].x = nextPoint.x + dy*size;
|
||||||
|
vertices[2*j].y = nextPoint.y - dx*size;
|
||||||
|
|
||||||
|
currentPoint = nextPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawTriangleStrip(vertices, 2*SPLINE_LINE_DIVISIONS + 2, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawCircleV(currentPoint, thick/2.0f, color); // Draw end line circle-cap
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw lines sequence
|
// Draw lines sequence
|
||||||
|
|
@ -353,6 +498,13 @@ void DrawCircle(int centerX, int centerY, float radius, Color color)
|
||||||
DrawCircleV((Vector2){ (float)centerX, (float)centerY }, radius, color);
|
DrawCircleV((Vector2){ (float)centerX, (float)centerY }, radius, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw a color-filled circle (Vector version)
|
||||||
|
// NOTE: On OpenGL 3.3 and ES2 we use QUADS to avoid drawing order issues
|
||||||
|
void DrawCircleV(Vector2 center, float radius, Color color)
|
||||||
|
{
|
||||||
|
DrawCircleSector(center, radius, 0, 360, 36, color);
|
||||||
|
}
|
||||||
|
|
||||||
// Draw a piece of a circle
|
// Draw a piece of a circle
|
||||||
void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color)
|
void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color)
|
||||||
{
|
{
|
||||||
|
|
@ -385,6 +537,7 @@ void DrawCircleSector(Vector2 center, float radius, float startAngle, float endA
|
||||||
rlSetTexture(texShapes.id);
|
rlSetTexture(texShapes.id);
|
||||||
|
|
||||||
rlBegin(RL_QUADS);
|
rlBegin(RL_QUADS);
|
||||||
|
|
||||||
// NOTE: Every QUAD actually represents two segments
|
// NOTE: Every QUAD actually represents two segments
|
||||||
for (int i = 0; i < segments/2; i++)
|
for (int i = 0; i < segments/2; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -394,7 +547,7 @@ void DrawCircleSector(Vector2 center, float radius, float startAngle, float endA
|
||||||
rlVertex2f(center.x, center.y);
|
rlVertex2f(center.x, center.y);
|
||||||
|
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength*2))*radius, center.y + sinf(DEG2RAD*(angle + stepLength*2))*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength*2.0f))*radius, center.y + sinf(DEG2RAD*(angle + stepLength*2.0f))*radius);
|
||||||
|
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*radius, center.y + sinf(DEG2RAD*(angle + stepLength))*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*radius, center.y + sinf(DEG2RAD*(angle + stepLength))*radius);
|
||||||
|
|
@ -402,11 +555,11 @@ void DrawCircleSector(Vector2 center, float radius, float startAngle, float endA
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
|
||||||
|
|
||||||
angle += (stepLength*2);
|
angle += (stepLength*2.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: In case number of segments is odd, we add one last piece to the cake
|
// NOTE: In case number of segments is odd, we add one last piece to the cake
|
||||||
if (segments%2)
|
if ((segments%2) == 1)
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
|
|
@ -422,6 +575,7 @@ void DrawCircleSector(Vector2 center, float radius, float startAngle, float endA
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlVertex2f(center.x, center.y);
|
rlVertex2f(center.x, center.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
rlEnd();
|
rlEnd();
|
||||||
|
|
||||||
rlSetTexture(0);
|
rlSetTexture(0);
|
||||||
|
|
@ -514,13 +668,6 @@ void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Co
|
||||||
rlEnd();
|
rlEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a color-filled circle (Vector version)
|
|
||||||
// NOTE: On OpenGL 3.3 and ES2 we use QUADS to avoid drawing order issues
|
|
||||||
void DrawCircleV(Vector2 center, float radius, Color color)
|
|
||||||
{
|
|
||||||
DrawCircleSector(center, radius, 0, 360, 36, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw circle outline
|
// Draw circle outline
|
||||||
void DrawCircleLines(int centerX, int centerY, float radius, Color color)
|
void DrawCircleLines(int centerX, int centerY, float radius, Color color)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
93
src/rtext.c
|
|
@ -71,12 +71,21 @@
|
||||||
#include <ctype.h> // Required for: toupper(), tolower() [Used in TextToUpper(), TextToLower()]
|
#include <ctype.h> // Required for: toupper(), tolower() [Used in TextToUpper(), TextToLower()]
|
||||||
|
|
||||||
#if defined(SUPPORT_FILEFORMAT_TTF)
|
#if defined(SUPPORT_FILEFORMAT_TTF)
|
||||||
|
#if defined(__GNUC__) // GCC and Clang
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define STB_RECT_PACK_IMPLEMENTATION
|
#define STB_RECT_PACK_IMPLEMENTATION
|
||||||
#include "external/stb_rect_pack.h" // Required for: ttf font rectangles packaging
|
#include "external/stb_rect_pack.h" // Required for: ttf font rectangles packaging
|
||||||
|
|
||||||
#define STBTT_STATIC
|
#define STBTT_STATIC
|
||||||
#define STB_TRUETYPE_IMPLEMENTATION
|
#define STB_TRUETYPE_IMPLEMENTATION
|
||||||
#include "external/stb_truetype.h" // Required for: ttf font data reading
|
#include "external/stb_truetype.h" // Required for: ttf font data reading
|
||||||
|
|
||||||
|
#if defined(__GNUC__) // GCC and Clang
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
@ -349,18 +358,18 @@ 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 glyphCount)
|
Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount)
|
||||||
{
|
{
|
||||||
Font font = { 0 };
|
Font font = { 0 };
|
||||||
|
|
||||||
// Loading file to memory
|
// Loading file to memory
|
||||||
unsigned int fileSize = 0;
|
int dataSize = 0;
|
||||||
unsigned char *fileData = LoadFileData(fileName, &fileSize);
|
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
||||||
|
|
||||||
if (fileData != NULL)
|
if (fileData != NULL)
|
||||||
{
|
{
|
||||||
// Loading font from memory data
|
// Loading font from memory data
|
||||||
font = LoadFontFromMemory(GetFileExtension(fileName), fileData, fileSize, fontSize, fontChars, glyphCount);
|
font = LoadFontFromMemory(GetFileExtension(fileName), fileData, dataSize, fontSize, codepoints, codepointCount);
|
||||||
|
|
||||||
UnloadFileData(fileData);
|
UnloadFileData(fileData);
|
||||||
}
|
}
|
||||||
|
|
@ -495,7 +504,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 glyphCount)
|
Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount)
|
||||||
{
|
{
|
||||||
Font font = { 0 };
|
Font font = { 0 };
|
||||||
|
|
||||||
|
|
@ -507,9 +516,9 @@ Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int
|
||||||
TextIsEqual(fileExtLower, ".otf"))
|
TextIsEqual(fileExtLower, ".otf"))
|
||||||
{
|
{
|
||||||
font.baseSize = fontSize;
|
font.baseSize = fontSize;
|
||||||
font.glyphCount = (glyphCount > 0)? glyphCount : 95;
|
font.glyphCount = (codepointCount > 0)? codepointCount : 95;
|
||||||
font.glyphPadding = 0;
|
font.glyphPadding = 0;
|
||||||
font.glyphs = LoadFontData(fileData, dataSize, font.baseSize, fontChars, font.glyphCount, FONT_DEFAULT);
|
font.glyphs = LoadFontData(fileData, dataSize, font.baseSize, codepoints, font.glyphCount, FONT_DEFAULT);
|
||||||
|
|
||||||
if (font.glyphs != NULL)
|
if (font.glyphs != NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -553,7 +562,7 @@ bool IsFontReady(Font font)
|
||||||
|
|
||||||
// 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 glyphCount, int type)
|
GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount, 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
|
||||||
|
|
@ -591,25 +600,25 @@ 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
|
||||||
glyphCount = (glyphCount > 0)? glyphCount : 95;
|
codepointCount = (codepointCount > 0)? codepointCount : 95;
|
||||||
|
|
||||||
// Fill fontChars in case not provided externally
|
// Fill fontChars in case not provided externally
|
||||||
// NOTE: By default we fill glyphCount consecutively, starting at 32 (Space)
|
// NOTE: By default we fill glyphCount consecutively, starting at 32 (Space)
|
||||||
|
|
||||||
if (fontChars == NULL)
|
if (codepoints == NULL)
|
||||||
{
|
{
|
||||||
fontChars = (int *)RL_MALLOC(glyphCount*sizeof(int));
|
codepoints = (int *)RL_MALLOC(codepointCount*sizeof(int));
|
||||||
for (int i = 0; i < glyphCount; i++) fontChars[i] = i + 32;
|
for (int i = 0; i < codepointCount; i++) codepoints[i] = i + 32;
|
||||||
genFontChars = true;
|
genFontChars = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
chars = (GlyphInfo *)RL_MALLOC(glyphCount*sizeof(GlyphInfo));
|
chars = (GlyphInfo *)RL_MALLOC(codepointCount*sizeof(GlyphInfo));
|
||||||
|
|
||||||
// NOTE: Using simple packaging, one char after another
|
// NOTE: Using simple packaging, one char after another
|
||||||
for (int i = 0; i < glyphCount; i++)
|
for (int i = 0; i < codepointCount; 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 = codepoints[i]; // Character value to get info for
|
||||||
chars[i].value = ch;
|
chars[i].value = ch;
|
||||||
|
|
||||||
// Render a unicode codepoint to a bitmap
|
// Render a unicode codepoint to a bitmap
|
||||||
|
|
@ -669,7 +678,7 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
|
||||||
}
|
}
|
||||||
else TRACELOG(LOG_WARNING, "FONT: Failed to process TTF font data");
|
else TRACELOG(LOG_WARNING, "FONT: Failed to process TTF font data");
|
||||||
|
|
||||||
if (genFontChars) RL_FREE(fontChars);
|
if (genFontChars) RL_FREE(codepoints);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -679,17 +688,17 @@ 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 glyphCount, int fontSize, int padding, int packMethod)
|
Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyphCount, int fontSize, int padding, int packMethod)
|
||||||
{
|
{
|
||||||
Image atlas = { 0 };
|
Image atlas = { 0 };
|
||||||
|
|
||||||
if (chars == NULL)
|
if (glyphs == NULL)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "FONT: Provided chars info not valid, returning empty image atlas");
|
TRACELOG(LOG_WARNING, "FONT: Provided chars info not valid, returning empty image atlas");
|
||||||
return atlas;
|
return atlas;
|
||||||
}
|
}
|
||||||
|
|
||||||
*charRecs = NULL;
|
*glyphRecs = NULL;
|
||||||
|
|
||||||
// In case no chars count provided we suppose default of 95
|
// In case no chars count provided we suppose default of 95
|
||||||
glyphCount = (glyphCount > 0)? glyphCount : 95;
|
glyphCount = (glyphCount > 0)? glyphCount : 95;
|
||||||
|
|
@ -703,8 +712,8 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
|
||||||
|
|
||||||
for (int i = 0; i < glyphCount; i++)
|
for (int i = 0; i < glyphCount; i++)
|
||||||
{
|
{
|
||||||
if (chars[i].image.width > maxGlyphWidth) maxGlyphWidth = chars[i].image.width;
|
if (glyphs[i].image.width > maxGlyphWidth) maxGlyphWidth = glyphs[i].image.width;
|
||||||
totalWidth += chars[i].image.width + 4*padding;
|
totalWidth += glyphs[i].image.width + 4*padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
//#define SUPPORT_FONT_ATLAS_SIZE_CONSERVATIVE
|
//#define SUPPORT_FONT_ATLAS_SIZE_CONSERVATIVE
|
||||||
|
|
@ -755,7 +764,7 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
|
||||||
for (int i = 0; i < glyphCount; i++)
|
for (int i = 0; i < glyphCount; i++)
|
||||||
{
|
{
|
||||||
// Check remaining space for glyph
|
// Check remaining space for glyph
|
||||||
if (offsetX >= (atlas.width - chars[i].image.width - 2*padding))
|
if (offsetX >= (atlas.width - glyphs[i].image.width - 2*padding))
|
||||||
{
|
{
|
||||||
offsetX = padding;
|
offsetX = padding;
|
||||||
|
|
||||||
|
|
@ -780,22 +789,22 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 < glyphs[i].image.height; y++)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < chars[i].image.width; x++)
|
for (int x = 0; x < glyphs[i].image.width; x++)
|
||||||
{
|
{
|
||||||
((unsigned char *)atlas.data)[(offsetY + y)*atlas.width + (offsetX + x)] = ((unsigned char *)chars[i].image.data)[y*chars[i].image.width + x];
|
((unsigned char *)atlas.data)[(offsetY + y)*atlas.width + (offsetX + x)] = ((unsigned char *)glyphs[i].image.data)[y*glyphs[i].image.width + x];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill chars rectangles in atlas info
|
// Fill chars rectangles in atlas info
|
||||||
recs[i].x = (float)offsetX;
|
recs[i].x = (float)offsetX;
|
||||||
recs[i].y = (float)offsetY;
|
recs[i].y = (float)offsetY;
|
||||||
recs[i].width = (float)chars[i].image.width;
|
recs[i].width = (float)glyphs[i].image.width;
|
||||||
recs[i].height = (float)chars[i].image.height;
|
recs[i].height = (float)glyphs[i].image.height;
|
||||||
|
|
||||||
// Move atlas position X for next character drawing
|
// Move atlas position X for next character drawing
|
||||||
offsetX += (chars[i].image.width + 2*padding);
|
offsetX += (glyphs[i].image.width + 2*padding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (packMethod == 1) // Use Skyline rect packing algorithm (stb_pack_rect)
|
else if (packMethod == 1) // Use Skyline rect packing algorithm (stb_pack_rect)
|
||||||
|
|
@ -810,8 +819,8 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
|
||||||
for (int i = 0; i < glyphCount; 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 = glyphs[i].image.width + 2*padding;
|
||||||
rects[i].h = chars[i].image.height + 2*padding;
|
rects[i].h = glyphs[i].image.height + 2*padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Package rectangles into atlas
|
// Package rectangles into atlas
|
||||||
|
|
@ -822,17 +831,17 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
|
||||||
// It returns char rectangles in atlas
|
// It returns char rectangles in atlas
|
||||||
recs[i].x = rects[i].x + (float)padding;
|
recs[i].x = rects[i].x + (float)padding;
|
||||||
recs[i].y = rects[i].y + (float)padding;
|
recs[i].y = rects[i].y + (float)padding;
|
||||||
recs[i].width = (float)chars[i].image.width;
|
recs[i].width = (float)glyphs[i].image.width;
|
||||||
recs[i].height = (float)chars[i].image.height;
|
recs[i].height = (float)glyphs[i].image.height;
|
||||||
|
|
||||||
if (rects[i].was_packed)
|
if (rects[i].was_packed)
|
||||||
{
|
{
|
||||||
// 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 < glyphs[i].image.height; y++)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < chars[i].image.width; x++)
|
for (int x = 0; x < glyphs[i].image.width; x++)
|
||||||
{
|
{
|
||||||
((unsigned char *)atlas.data)[(rects[i].y + padding + y)*atlas.width + (rects[i].x + padding + x)] = ((unsigned char *)chars[i].image.data)[y*chars[i].image.width + x];
|
((unsigned char *)atlas.data)[(rects[i].y + padding + y)*atlas.width + (rects[i].x + padding + x)] = ((unsigned char *)glyphs[i].image.data)[y*glyphs[i].image.width + x];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -870,7 +879,7 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
|
||||||
atlas.data = dataGrayAlpha;
|
atlas.data = dataGrayAlpha;
|
||||||
atlas.format = PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA;
|
atlas.format = PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA;
|
||||||
|
|
||||||
*charRecs = recs;
|
*glyphRecs = recs;
|
||||||
|
|
||||||
return atlas;
|
return atlas;
|
||||||
}
|
}
|
||||||
|
|
@ -966,7 +975,7 @@ bool ExportFontAsCode(Font font, const char *fileName)
|
||||||
byteCount += sprintf(txtData + byteCount, "static unsigned char fontData_%s[COMPRESSED_DATA_SIZE_FONT_%s] = { ", fileNamePascal, TextToUpper(fileNamePascal));
|
byteCount += sprintf(txtData + byteCount, "static unsigned char fontData_%s[COMPRESSED_DATA_SIZE_FONT_%s] = { ", fileNamePascal, TextToUpper(fileNamePascal));
|
||||||
for (int i = 0; i < compDataSize - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%02x,\n " : "0x%02x, "), compData[i]);
|
for (int i = 0; i < compDataSize - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%02x,\n " : "0x%02x, "), compData[i]);
|
||||||
byteCount += sprintf(txtData + byteCount, "0x%02x };\n\n", compData[compDataSize - 1]);
|
byteCount += sprintf(txtData + byteCount, "0x%02x };\n\n", compData[compDataSize - 1]);
|
||||||
MemFree(compData);
|
RL_FREE(compData);
|
||||||
#else
|
#else
|
||||||
// Save font image data (uncompressed)
|
// Save font image data (uncompressed)
|
||||||
byteCount += sprintf(txtData + byteCount, "// Font image pixels data\n");
|
byteCount += sprintf(txtData + byteCount, "// Font image pixels data\n");
|
||||||
|
|
@ -1066,7 +1075,7 @@ void DrawFPS(int posX, int posY)
|
||||||
if ((fps < 30) && (fps >= 15)) color = ORANGE; // Warning FPS
|
if ((fps < 30) && (fps >= 15)) color = ORANGE; // Warning FPS
|
||||||
else if (fps < 15) color = RED; // Low FPS
|
else if (fps < 15) color = RED; // Low FPS
|
||||||
|
|
||||||
DrawText(TextFormat("%2i FPS", GetFPS()), posX, posY, 20, color);
|
DrawText(TextFormat("%2i FPS", fps), posX, posY, 20, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw text (using default font)
|
// Draw text (using default font)
|
||||||
|
|
@ -1167,14 +1176,14 @@ void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSiz
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw multiple character (codepoints)
|
// Draw multiple character (codepoints)
|
||||||
void DrawTextCodepoints(Font font, const int *codepoints, int count, Vector2 position, float fontSize, float spacing, Color tint)
|
void DrawTextCodepoints(Font font, const int *codepoints, int codepointCount, Vector2 position, float fontSize, float spacing, Color tint)
|
||||||
{
|
{
|
||||||
int textOffsetY = 0; // Offset between lines (on linebreak '\n')
|
int textOffsetY = 0; // Offset between lines (on linebreak '\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 < count; i++)
|
for (int i = 0; i < codepointCount; i++)
|
||||||
{
|
{
|
||||||
int index = GetGlyphIndex(font, codepoints[i]);
|
int index = GetGlyphIndex(font, codepoints[i]);
|
||||||
|
|
||||||
|
|
@ -1688,7 +1697,7 @@ const char *TextToPascal(const char *text)
|
||||||
// WARNING: Allocated memory must be manually freed
|
// WARNING: Allocated memory must be manually freed
|
||||||
char *LoadUTF8(const int *codepoints, int length)
|
char *LoadUTF8(const int *codepoints, int length)
|
||||||
{
|
{
|
||||||
// We allocate enough memory fo fit all possible codepoints
|
// We allocate enough memory to fit all possible codepoints
|
||||||
// NOTE: 5 bytes for every codepoint should be enough
|
// NOTE: 5 bytes for every codepoint should be enough
|
||||||
char *text = (char *)RL_CALLOC(length*5, 1);
|
char *text = (char *)RL_CALLOC(length*5, 1);
|
||||||
const char *utf8 = NULL;
|
const char *utf8 = NULL;
|
||||||
|
|
@ -1757,7 +1766,7 @@ int GetCodepointCount(const char *text)
|
||||||
while (*ptr != '\0')
|
while (*ptr != '\0')
|
||||||
{
|
{
|
||||||
int next = 0;
|
int next = 0;
|
||||||
int letter = GetCodepointNext(ptr, &next);
|
GetCodepointNext(ptr, &next);
|
||||||
|
|
||||||
ptr += next;
|
ptr += next;
|
||||||
|
|
||||||
|
|
|
||||||
193
src/rtextures.c
|
|
@ -138,13 +138,24 @@
|
||||||
defined(SUPPORT_FILEFORMAT_PIC) || \
|
defined(SUPPORT_FILEFORMAT_PIC) || \
|
||||||
defined(SUPPORT_FILEFORMAT_PNM))
|
defined(SUPPORT_FILEFORMAT_PNM))
|
||||||
|
|
||||||
|
#if defined(__GNUC__) // GCC and Clang
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define STBI_MALLOC RL_MALLOC
|
#define STBI_MALLOC RL_MALLOC
|
||||||
#define STBI_FREE RL_FREE
|
#define STBI_FREE RL_FREE
|
||||||
#define STBI_REALLOC RL_REALLOC
|
#define STBI_REALLOC RL_REALLOC
|
||||||
|
|
||||||
|
#define STBI_NO_THREAD_LOCALS
|
||||||
|
|
||||||
#define STB_IMAGE_IMPLEMENTATION
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
#include "external/stb_image.h" // Required for: stbi_load_from_file()
|
#include "external/stb_image.h" // Required for: stbi_load_from_file()
|
||||||
// NOTE: Used to read image data (multiple formats support)
|
// NOTE: Used to read image data (multiple formats support)
|
||||||
|
|
||||||
|
#if defined(__GNUC__) // GCC and Clang
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined(SUPPORT_FILEFORMAT_DDS) || \
|
#if (defined(SUPPORT_FILEFORMAT_DDS) || \
|
||||||
|
|
@ -153,25 +164,35 @@
|
||||||
defined(SUPPORT_FILEFORMAT_PVR) || \
|
defined(SUPPORT_FILEFORMAT_PVR) || \
|
||||||
defined(SUPPORT_FILEFORMAT_ASTC))
|
defined(SUPPORT_FILEFORMAT_ASTC))
|
||||||
|
|
||||||
|
#if defined(__GNUC__) // GCC and Clang
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define RL_GPUTEX_IMPLEMENTATION
|
#define RL_GPUTEX_IMPLEMENTATION
|
||||||
#include "external/rl_gputex.h" // Required for: rl_load_xxx_from_memory()
|
#include "external/rl_gputex.h" // Required for: rl_load_xxx_from_memory()
|
||||||
// NOTE: Used to read compressed textures data (multiple formats support)
|
// NOTE: Used to read compressed textures data (multiple formats support)
|
||||||
|
|
||||||
|
#if defined(__GNUC__) // GCC and Clang
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(SUPPORT_FILEFORMAT_QOI)
|
#if defined(SUPPORT_FILEFORMAT_QOI)
|
||||||
#define QOI_MALLOC RL_MALLOC
|
#define QOI_MALLOC RL_MALLOC
|
||||||
#define QOI_FREE RL_FREE
|
#define QOI_FREE RL_FREE
|
||||||
|
|
||||||
#if defined(_MSC_VER ) // qoi has warnings on windows, so disable them just for this file
|
#if defined(_MSC_VER) // Disable some MSVC warning
|
||||||
#pragma warning( push )
|
#pragma warning(push)
|
||||||
#pragma warning( disable : 4267)
|
#pragma warning(disable : 4267)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define QOI_IMPLEMENTATION
|
#define QOI_IMPLEMENTATION
|
||||||
#include "external/qoi.h"
|
#include "external/qoi.h"
|
||||||
|
|
||||||
#if defined(_MSC_VER )
|
#if defined(_MSC_VER)
|
||||||
#pragma warning( pop )
|
#pragma warning(pop) // Disable MSVC warning suppression
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -194,6 +215,14 @@
|
||||||
#define STB_IMAGE_RESIZE_IMPLEMENTATION
|
#define STB_IMAGE_RESIZE_IMPLEMENTATION
|
||||||
#include "external/stb_image_resize.h" // Required for: stbir_resize_uint8() [ImageResize()]
|
#include "external/stb_image_resize.h" // Required for: stbir_resize_uint8() [ImageResize()]
|
||||||
|
|
||||||
|
#if defined(SUPPORT_FILEFORMAT_SVG)
|
||||||
|
#define NANOSVG_IMPLEMENTATION // Expands implementation
|
||||||
|
#include "external/nanosvg.h"
|
||||||
|
|
||||||
|
#define NANOSVGRAST_IMPLEMENTATION
|
||||||
|
#include "external/nanosvgrast.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Defines and Macros
|
// Defines and Macros
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
@ -250,11 +279,11 @@ Image LoadImage(const char *fileName)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Loading file to memory
|
// Loading file to memory
|
||||||
unsigned int fileSize = 0;
|
int dataSize = 0;
|
||||||
unsigned char *fileData = LoadFileData(fileName, &fileSize);
|
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
||||||
|
|
||||||
// Loading image from memory data
|
// Loading image from memory data
|
||||||
if (fileData != NULL) image = LoadImageFromMemory(GetFileExtension(fileName), fileData, fileSize);
|
if (fileData != NULL) image = LoadImageFromMemory(GetFileExtension(fileName), fileData, dataSize);
|
||||||
|
|
||||||
RL_FREE(fileData);
|
RL_FREE(fileData);
|
||||||
|
|
||||||
|
|
@ -266,7 +295,7 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int
|
||||||
{
|
{
|
||||||
Image image = { 0 };
|
Image image = { 0 };
|
||||||
|
|
||||||
unsigned int dataSize = 0;
|
int dataSize = 0;
|
||||||
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
||||||
|
|
||||||
if (fileData != NULL)
|
if (fileData != NULL)
|
||||||
|
|
@ -289,6 +318,82 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load an image from a SVG file or string with custom size
|
||||||
|
Image LoadImageSvg(const char *fileNameOrString, int width, int height)
|
||||||
|
{
|
||||||
|
Image image = { 0 };
|
||||||
|
bool isSvgStringValid = false;
|
||||||
|
|
||||||
|
#if defined(SUPPORT_FILEFORMAT_SVG)
|
||||||
|
// Validate fileName or string
|
||||||
|
if (fileNameOrString != NULL)
|
||||||
|
{
|
||||||
|
int dataSize = 0;
|
||||||
|
unsigned char *fileData = NULL;
|
||||||
|
|
||||||
|
if (FileExists(fileNameOrString))
|
||||||
|
{
|
||||||
|
fileData = LoadFileData(fileNameOrString, &dataSize);
|
||||||
|
isSvgStringValid = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Validate fileData as valid SVG string data
|
||||||
|
//<svg xmlns="http://www.w3.org/2000/svg" width="2500" height="2484" viewBox="0 0 192.756 191.488">
|
||||||
|
if ((fileNameOrString != NULL) &&
|
||||||
|
(fileNameOrString[0] == '<') &&
|
||||||
|
(fileNameOrString[1] == 's') &&
|
||||||
|
(fileNameOrString[2] == 'v') &&
|
||||||
|
(fileNameOrString[3] == 'g'))
|
||||||
|
{
|
||||||
|
fileData = fileNameOrString;
|
||||||
|
isSvgStringValid = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isSvgStringValid)
|
||||||
|
{
|
||||||
|
struct NSVGimage *svgImage = nsvgParse(fileData, "px", 96.0f);
|
||||||
|
|
||||||
|
unsigned char *img = RL_MALLOC(width*height*4);
|
||||||
|
|
||||||
|
// Calculate scales for both the width and the height
|
||||||
|
const float scaleWidth = width/svgImage->width;
|
||||||
|
const float scaleHeight = height/svgImage->height;
|
||||||
|
|
||||||
|
// Set the largest of the 2 scales to be the scale to use
|
||||||
|
const float scale = (scaleHeight > scaleWidth)? scaleWidth : scaleHeight;
|
||||||
|
|
||||||
|
int offsetX = 0;
|
||||||
|
int offsetY = 0;
|
||||||
|
|
||||||
|
if (scaleHeight > scaleWidth) offsetY = (height - svgImage->height*scale) / 2;
|
||||||
|
else offsetX = (width - svgImage->width*scale) / 2;
|
||||||
|
|
||||||
|
// Rasterize
|
||||||
|
struct NSVGrasterizer *rast = nsvgCreateRasterizer();
|
||||||
|
nsvgRasterize(rast, svgImage, (int)offsetX, (int)offsetY, scale, img, width, height, width*4);
|
||||||
|
|
||||||
|
// Populate image struct with all data
|
||||||
|
image.data = img;
|
||||||
|
image.width = width;
|
||||||
|
image.height = height;
|
||||||
|
image.mipmaps = 1;
|
||||||
|
image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
|
||||||
|
|
||||||
|
// Free used memory
|
||||||
|
nsvgDelete(svgImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isSvgStringValid && (fileData != fileNameOrString)) UnloadFileData(fileData);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
TRACELOG(LOG_WARNING, "SVG image support not enabled, image can not be loaded");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
// Load animated image data
|
// Load animated image data
|
||||||
// - Image.data buffer includes all frames: [image#0][image#1][image#2][...]
|
// - Image.data buffer includes all frames: [image#0][image#1][image#2][...]
|
||||||
// - Number of frames is returned through 'frames' parameter
|
// - Number of frames is returned through 'frames' parameter
|
||||||
|
|
@ -302,7 +407,7 @@ Image LoadImageAnim(const char *fileName, int *frames)
|
||||||
#if defined(SUPPORT_FILEFORMAT_GIF)
|
#if defined(SUPPORT_FILEFORMAT_GIF)
|
||||||
if (IsFileExtension(fileName, ".gif"))
|
if (IsFileExtension(fileName, ".gif"))
|
||||||
{
|
{
|
||||||
unsigned int dataSize = 0;
|
int dataSize = 0;
|
||||||
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
||||||
|
|
||||||
if (fileData != NULL)
|
if (fileData != NULL)
|
||||||
|
|
@ -412,12 +517,44 @@ Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, i
|
||||||
#if defined(SUPPORT_FILEFORMAT_QOI)
|
#if defined(SUPPORT_FILEFORMAT_QOI)
|
||||||
else if ((strcmp(fileType, ".qoi") == 0) || (strcmp(fileType, ".QOI") == 0))
|
else if ((strcmp(fileType, ".qoi") == 0) || (strcmp(fileType, ".QOI") == 0))
|
||||||
{
|
{
|
||||||
qoi_desc desc = { 0 };
|
if (fileData != NULL)
|
||||||
image.data = qoi_decode(fileData, dataSize, &desc, 4);
|
{
|
||||||
image.width = desc.width;
|
qoi_desc desc = { 0 };
|
||||||
image.height = desc.height;
|
image.data = qoi_decode(fileData, dataSize, &desc, 4);
|
||||||
image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
|
image.width = desc.width;
|
||||||
image.mipmaps = 1;
|
image.height = desc.height;
|
||||||
|
image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
|
||||||
|
image.mipmaps = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if defined(SUPPORT_FILEFORMAT_SVG)
|
||||||
|
else if ((strcmp(fileType, ".svg") == 0) || (strcmp(fileType, ".SVG") == 0))
|
||||||
|
{
|
||||||
|
// Validate fileData as valid SVG string data
|
||||||
|
//<svg xmlns="http://www.w3.org/2000/svg" width="2500" height="2484" viewBox="0 0 192.756 191.488">
|
||||||
|
if ((fileData != NULL) &&
|
||||||
|
(fileData[0] == '<') &&
|
||||||
|
(fileData[1] == 's') &&
|
||||||
|
(fileData[2] == 'v') &&
|
||||||
|
(fileData[3] == 'g'))
|
||||||
|
{
|
||||||
|
struct NSVGimage *svgImage = nsvgParse(fileData, "px", 96.0f);
|
||||||
|
unsigned char *img = RL_MALLOC(svgImage->width*svgImage->height*4);
|
||||||
|
|
||||||
|
// Rasterize
|
||||||
|
struct NSVGrasterizer *rast = nsvgCreateRasterizer();
|
||||||
|
nsvgRasterize(rast, svgImage, 0, 0, 1.0f, img, svgImage->width, svgImage->height, svgImage->width*4);
|
||||||
|
|
||||||
|
// Populate image struct with all data
|
||||||
|
image.data = img;
|
||||||
|
image.width = svgImage->width;
|
||||||
|
image.height = svgImage->height;
|
||||||
|
image.mipmaps = 1;
|
||||||
|
image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
|
||||||
|
|
||||||
|
nsvgDelete(svgImage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_DDS)
|
#if defined(SUPPORT_FILEFORMAT_DDS)
|
||||||
|
|
@ -3265,6 +3402,14 @@ void ImageDrawRectangleRec(Image *dst, Rectangle rec, Color color)
|
||||||
if (rec.width < 0) rec.width = 0;
|
if (rec.width < 0) rec.width = 0;
|
||||||
if (rec.height < 0) rec.height = 0;
|
if (rec.height < 0) rec.height = 0;
|
||||||
|
|
||||||
|
// Clamp the size the the image bounds
|
||||||
|
if ((rec.x + rec.width) >= dst->width) rec.width = dst->width - rec.x;
|
||||||
|
if ((rec.y + rec.height) >= dst->height) rec.height = dst->height - rec.y;
|
||||||
|
|
||||||
|
// Check if the rect is even inside the image
|
||||||
|
if ((rec.x > dst->width) || (rec.y > dst->height)) return;
|
||||||
|
if (((rec.x + rec.width) < 0) || (rec.y + rec.height < 0)) return;
|
||||||
|
|
||||||
int sy = (int)rec.y;
|
int sy = (int)rec.y;
|
||||||
int sx = (int)rec.x;
|
int sx = (int)rec.x;
|
||||||
|
|
||||||
|
|
@ -3282,12 +3427,12 @@ void ImageDrawRectangleRec(Image *dst, Rectangle rec, Color color)
|
||||||
memcpy(pSrcPixel + x*bytesPerPixel, pSrcPixel, bytesPerPixel);
|
memcpy(pSrcPixel + x*bytesPerPixel, pSrcPixel, bytesPerPixel);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Repeat the first row data for all other rows
|
// Repeat the first row data for all other rows
|
||||||
int bytesPerRow = bytesPerPixel * (int)rec.width;
|
int bytesPerRow = bytesPerPixel * (int)rec.width;
|
||||||
for (int y = 1; y < (int)rec.height; y++)
|
for (int y = 1; y < (int)rec.height; y++)
|
||||||
{
|
{
|
||||||
memcpy(pSrcPixel + (y*dst->width)*bytesPerPixel, pSrcPixel, bytesPerRow);
|
memcpy(pSrcPixel + (y*dst->width)*bytesPerPixel, pSrcPixel, bytesPerRow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw rectangle lines within an image
|
// Draw rectangle lines within an image
|
||||||
|
|
|
||||||
32
src/utils.c
|
|
@ -180,16 +180,16 @@ void MemFree(void *ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load data from file into a buffer
|
// Load data from file into a buffer
|
||||||
unsigned char *LoadFileData(const char *fileName, unsigned int *bytesRead)
|
unsigned char *LoadFileData(const char *fileName, int *dataSize)
|
||||||
{
|
{
|
||||||
unsigned char *data = NULL;
|
unsigned char *data = NULL;
|
||||||
*bytesRead = 0;
|
*dataSize = 0;
|
||||||
|
|
||||||
if (fileName != NULL)
|
if (fileName != NULL)
|
||||||
{
|
{
|
||||||
if (loadFileData)
|
if (loadFileData)
|
||||||
{
|
{
|
||||||
data = loadFileData(fileName, bytesRead);
|
data = loadFileData(fileName, dataSize);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
#if defined(SUPPORT_STANDARD_FILEIO)
|
#if defined(SUPPORT_STANDARD_FILEIO)
|
||||||
|
|
@ -211,7 +211,7 @@ unsigned char *LoadFileData(const char *fileName, unsigned int *bytesRead)
|
||||||
{
|
{
|
||||||
// NOTE: fread() returns number of read elements instead of bytes, so we read [1 byte, size elements]
|
// NOTE: fread() returns number of read elements instead of bytes, so we read [1 byte, size elements]
|
||||||
unsigned int count = (unsigned int)fread(data, sizeof(unsigned char), size, file);
|
unsigned int count = (unsigned int)fread(data, sizeof(unsigned char), size, file);
|
||||||
*bytesRead = count;
|
*dataSize = count;
|
||||||
|
|
||||||
if (count != size) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially loaded", fileName);
|
if (count != size) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially loaded", fileName);
|
||||||
else TRACELOG(LOG_INFO, "FILEIO: [%s] File loaded successfully", fileName);
|
else TRACELOG(LOG_INFO, "FILEIO: [%s] File loaded successfully", fileName);
|
||||||
|
|
@ -239,7 +239,7 @@ void UnloadFileData(unsigned char *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save data to file from buffer
|
// Save data to file from buffer
|
||||||
bool SaveFileData(const char *fileName, void *data, unsigned int bytesToWrite)
|
bool SaveFileData(const char *fileName, void *data, int dataSize)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
|
||||||
|
|
@ -247,17 +247,17 @@ bool SaveFileData(const char *fileName, void *data, unsigned int bytesToWrite)
|
||||||
{
|
{
|
||||||
if (saveFileData)
|
if (saveFileData)
|
||||||
{
|
{
|
||||||
return saveFileData(fileName, data, bytesToWrite);
|
return saveFileData(fileName, data, dataSize);
|
||||||
}
|
}
|
||||||
#if defined(SUPPORT_STANDARD_FILEIO)
|
#if defined(SUPPORT_STANDARD_FILEIO)
|
||||||
FILE *file = fopen(fileName, "wb");
|
FILE *file = fopen(fileName, "wb");
|
||||||
|
|
||||||
if (file != NULL)
|
if (file != NULL)
|
||||||
{
|
{
|
||||||
unsigned int count = (unsigned int)fwrite(data, sizeof(unsigned char), bytesToWrite, file);
|
unsigned int count = (unsigned int)fwrite(data, sizeof(unsigned char), dataSize, file);
|
||||||
|
|
||||||
if (count == 0) TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to write file", fileName);
|
if (count == 0) TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to write file", fileName);
|
||||||
else if (count != bytesToWrite) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially written", fileName);
|
else if (count != dataSize) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially written", fileName);
|
||||||
else TRACELOG(LOG_INFO, "FILEIO: [%s] File saved successfully", fileName);
|
else TRACELOG(LOG_INFO, "FILEIO: [%s] File saved successfully", fileName);
|
||||||
|
|
||||||
int result = fclose(file);
|
int result = fclose(file);
|
||||||
|
|
@ -274,7 +274,7 @@ bool SaveFileData(const char *fileName, void *data, unsigned int bytesToWrite)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Export data to code (.h), returns true on success
|
// Export data to code (.h), returns true on success
|
||||||
bool ExportDataAsCode(const unsigned char *data, unsigned int size, const char *fileName)
|
bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileName)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
|
||||||
|
|
@ -284,7 +284,7 @@ bool ExportDataAsCode(const unsigned char *data, unsigned int size, const char *
|
||||||
|
|
||||||
// NOTE: Text data buffer size is estimated considering raw data size in bytes
|
// NOTE: Text data buffer size is estimated considering raw 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(size*6 + 2000, sizeof(char));
|
char *txtData = (char *)RL_CALLOC(dataSize*6 + 2000, sizeof(char));
|
||||||
|
|
||||||
int byteCount = 0;
|
int byteCount = 0;
|
||||||
byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n");
|
byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n");
|
||||||
|
|
@ -303,11 +303,11 @@ bool ExportDataAsCode(const unsigned char *data, unsigned int size, const char *
|
||||||
strcpy(varFileName, GetFileNameWithoutExt(fileName));
|
strcpy(varFileName, GetFileNameWithoutExt(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; }
|
||||||
|
|
||||||
byteCount += sprintf(txtData + byteCount, "#define %s_DATA_SIZE %i\n\n", varFileName, size);
|
byteCount += sprintf(txtData + byteCount, "#define %s_DATA_SIZE %i\n\n", varFileName, dataSize);
|
||||||
|
|
||||||
byteCount += sprintf(txtData + byteCount, "static unsigned char %s_DATA[%s_DATA_SIZE] = { ", varFileName, varFileName);
|
byteCount += sprintf(txtData + byteCount, "static unsigned char %s_DATA[%s_DATA_SIZE] = { ", varFileName, varFileName);
|
||||||
for (unsigned int i = 0; i < size - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%x,\n" : "0x%x, "), 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, "), data[i]);
|
||||||
byteCount += sprintf(txtData + byteCount, "0x%x };\n", data[size - 1]);
|
byteCount += sprintf(txtData + byteCount, "0x%x };\n", data[dataSize - 1]);
|
||||||
|
|
||||||
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
||||||
success = SaveFileText(fileName, txtData);
|
success = SaveFileText(fileName, txtData);
|
||||||
|
|
@ -465,12 +465,12 @@ FILE *android_fopen(const char *fileName, const char *mode)
|
||||||
// Module specific Functions Definition
|
// Module specific Functions Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
#if defined(PLATFORM_ANDROID)
|
#if defined(PLATFORM_ANDROID)
|
||||||
static int android_read(void *cookie, char *buf, int size)
|
static int android_read(void *cookie, char *data, int dataSize)
|
||||||
{
|
{
|
||||||
return AAsset_read((AAsset *)cookie, buf, size);
|
return AAsset_read((AAsset *)cookie, data, dataSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int android_write(void *cookie, const char *buf, int size)
|
static int android_write(void *cookie, const char *data, int dataSize)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "ANDROID: Failed to provide write access to APK");
|
TRACELOG(LOG_WARNING, "ANDROID: Failed to provide write access to APK");
|
||||||
|
|
||||||
|
|
|
||||||