Merge pull request #6 from raysan5/master

Merge upstream changes
This commit is contained in:
MichaelFiber 2023-09-08 20:15:25 -04:00 committed by GitHub
commit cbef73c5cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
91 changed files with 6483 additions and 812 deletions

View File

@ -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 |
@ -76,6 +77,7 @@ Some people ported raylib to other languages in form of bindings or wrappers to
| raylib-sunder | **auto** | [Sunder](https://github.com/ashn-dot-dev/sunder) | 0BSD | https://github.com/ashn-dot-dev/raylib-sunder | | raylib-sunder | **auto** | [Sunder](https://github.com/ashn-dot-dev/sunder) | 0BSD | https://github.com/ashn-dot-dev/raylib-sunder |
| rayed-bqn | **auto** | [BQN](https://mlochbaum.github.io/BQN/) | MIT | https://github.com/Brian-ED/rayed-bqn | | rayed-bqn | **auto** | [BQN](https://mlochbaum.github.io/BQN/) | MIT | https://github.com/Brian-ED/rayed-bqn |
| rayjs | 4.6-dev | [QuickJS](https://bellard.org/quickjs/) | MIT | https://github.com/mode777/rayjs | | rayjs | 4.6-dev | [QuickJS](https://bellard.org/quickjs/) | MIT | https://github.com/mode777/rayjs |
| raylib-raku | **auto** | [Raku](https://www.raku.org/) | Artistic License 2.0 | https://github.com/vushu/raylib-raku |
### Utility Wrapers ### Utility Wrapers
These are utility wrappers for specific languages, they are not required to use raylib in the language but may adapt the raylib API to be more inline with the language's pardigm. These are utility wrappers for specific languages, they are not required to use raylib in the language but may adapt the raylib API to be more inline with the language's pardigm.

View File

@ -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

View File

@ -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.*

View File

@ -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)

View File

@ -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 "")

View File

@ -73,19 +73,6 @@ elseif (${PLATFORM} MATCHES "Android")
find_library(OPENGL_LIBRARY OpenGL) find_library(OPENGL_LIBRARY OpenGL)
set(LIBS_PRIVATE m log android EGL GLESv2 OpenSLES atomic c) set(LIBS_PRIVATE m log android EGL GLESv2 OpenSLES atomic c)
elseif (${PLATFORM} MATCHES "Raspberry Pi")
set(PLATFORM_CPP "PLATFORM_RPI")
set(GRAPHICS "GRAPHICS_API_OPENGL_ES2")
add_definitions(-D_DEFAULT_SOURCE)
find_library(GLESV2 brcmGLESv2 HINTS /opt/vc/lib)
find_library(EGL brcmEGL HINTS /opt/vc/lib)
find_library(BCMHOST bcm_host HINTS /opt/vc/lib)
include_directories(/opt/vc/include /opt/vc/include/interface/vmcs_host/linux /opt/vc/include/interface/vcos/pthreads)
link_directories(/opt/vc/lib)
set(LIBS_PRIVATE ${GLESV2} ${EGL} ${BCMHOST} pthread rt m dl)
elseif ("${PLATFORM}" MATCHES "DRM") elseif ("${PLATFORM}" MATCHES "DRM")
set(PLATFORM_CPP "PLATFORM_DRM") set(PLATFORM_CPP "PLATFORM_DRM")
set(GRAPHICS "GRAPHICS_API_OPENGL_ES2") set(GRAPHICS "GRAPHICS_API_OPENGL_ES2")

View File

@ -25,7 +25,7 @@
# Define required environment variables # Define required environment variables
#------------------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------------------
# Define target platform: PLATFORM_DESKTOP, PLATFORM_RPI, PLATFORM_DRM, PLATFORM_ANDROID, PLATFORM_WEB # Define target platform: PLATFORM_DESKTOP, PLATFORM_DRM, PLATFORM_ANDROID, PLATFORM_WEB
PLATFORM ?= PLATFORM_DESKTOP PLATFORM ?= PLATFORM_DESKTOP
# Define required raylib variables # Define required raylib variables
@ -58,15 +58,6 @@ BUILD_WEB_HEAP_SIZE ?= 134217728
BUILD_WEB_RESOURCES ?= TRUE BUILD_WEB_RESOURCES ?= TRUE
BUILD_WEB_RESOURCES_PATH ?= $(dir $<)resources@resources BUILD_WEB_RESOURCES_PATH ?= $(dir $<)resources@resources
# Use cross-compiler for PLATFORM_RPI
ifeq ($(PLATFORM),PLATFORM_RPI)
USE_RPI_CROSS_COMPILER ?= FALSE
ifeq ($(USE_RPI_CROSS_COMPILER),TRUE)
RPI_TOOLCHAIN ?= C:/SysGCC/Raspberry
RPI_TOOLCHAIN_SYSROOT ?= $(RPI_TOOLCHAIN)/arm-linux-gnueabihf/sysroot
endif
endif
# Determine PLATFORM_OS in case PLATFORM_DESKTOP or PLATFORM_WEB selected # Determine PLATFORM_OS in case PLATFORM_DESKTOP or PLATFORM_WEB selected
ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_DESKTOP PLATFORM_WEB)) ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_DESKTOP PLATFORM_WEB))
# No uname.exe on MinGW!, but OS=Windows_NT on Windows! # No uname.exe on MinGW!, but OS=Windows_NT on Windows!
@ -95,12 +86,6 @@ ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_DESKTOP PLATFORM_WEB))
endif endif
endif endif
endif endif
ifeq ($(PLATFORM),PLATFORM_RPI)
UNAMEOS = $(shell uname)
ifeq ($(UNAMEOS),Linux)
PLATFORM_OS = LINUX
endif
endif
ifeq ($(PLATFORM),PLATFORM_DRM) ifeq ($(PLATFORM),PLATFORM_DRM)
UNAMEOS = $(shell uname) UNAMEOS = $(shell uname)
ifeq ($(UNAMEOS),Linux) ifeq ($(UNAMEOS),Linux)
@ -118,9 +103,6 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
endif endif
# Default path for raylib on Raspberry Pi # Default path for raylib on Raspberry Pi
ifeq ($(PLATFORM),PLATFORM_RPI)
RAYLIB_PATH ?= /home/pi/raylib
endif
ifeq ($(PLATFORM),PLATFORM_DRM) ifeq ($(PLATFORM),PLATFORM_DRM)
RAYLIB_PATH ?= /home/pi/raylib RAYLIB_PATH ?= /home/pi/raylib
endif endif
@ -154,13 +136,6 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
CC = clang CC = clang
endif endif
endif endif
ifeq ($(PLATFORM),PLATFORM_RPI)
ifeq ($(USE_RPI_CROSS_COMPILER),TRUE)
# Define RPI cross-compiler
#CC = armv6j-hardfloat-linux-gnueabi-gcc
CC = $(RPI_TOOLCHAIN)/bin/arm-linux-gnueabihf-gcc
endif
endif
ifeq ($(PLATFORM),PLATFORM_WEB) ifeq ($(PLATFORM),PLATFORM_WEB)
# HTML5 emscripten compiler # HTML5 emscripten compiler
# WARNING: To compile to HTML5, code must be redesigned # WARNING: To compile to HTML5, code must be redesigned
@ -231,9 +206,6 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
endif endif
endif endif
endif endif
ifeq ($(PLATFORM),PLATFORM_RPI)
CFLAGS += -std=gnu99
endif
ifeq ($(PLATFORM),PLATFORM_DRM) ifeq ($(PLATFORM),PLATFORM_DRM)
CFLAGS += -std=gnu99 -DEGL_NO_X11 CFLAGS += -std=gnu99 -DEGL_NO_X11
endif endif
@ -252,15 +224,15 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
INCLUDE_PATHS += -I$(RAYLIB_INCLUDE_PATH) INCLUDE_PATHS += -I$(RAYLIB_INCLUDE_PATH)
endif endif
endif endif
ifeq ($(PLATFORM),PLATFORM_RPI)
INCLUDE_PATHS += -I$(RPI_TOOLCHAIN_SYSROOT)/opt/vc/include
INCLUDE_PATHS += -I$(RPI_TOOLCHAIN_SYSROOT)/opt/vc/include/interface/vmcs_host/linux
INCLUDE_PATHS += -I$(RPI_TOOLCHAIN_SYSROOT)/opt/vc/include/interface/vcos/pthreads
endif
ifeq ($(PLATFORM),PLATFORM_DRM) 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
@ -323,9 +295,6 @@ ifeq ($(PLATFORM),PLATFORM_WEB)
# logic to a self contained function: UpdateDrawFrame(), check core_basic_window_web.c for reference. # logic to a self contained function: UpdateDrawFrame(), check core_basic_window_web.c for reference.
endif endif
ifeq ($(PLATFORM),PLATFORM_RPI)
LDFLAGS += -L$(RPI_TOOLCHAIN_SYSROOT)/opt/vc/lib
endif
# Define libraries required on linking: LDLIBS # Define libraries required on linking: LDLIBS
# NOTE: To link libraries (lib<name>.so or lib<name>.a), use -l<name> # NOTE: To link libraries (lib<name>.so or lib<name>.a), use -l<name>
@ -376,14 +345,6 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
LDLIBS += -lglfw LDLIBS += -lglfw
endif endif
endif endif
ifeq ($(PLATFORM),PLATFORM_RPI)
# Libraries for Raspberry Pi compiling
# NOTE: Required packages: libasound2-dev (ALSA)
LDLIBS = -lraylib -lbrcmGLESv2 -lbrcmEGL -lpthread -lrt -lm -lbcm_host -ldl -latomic
ifeq ($(USE_RPI_CROSS_COMPILER),TRUE)
LDLIBS += -lvchiq_arm -lvcos
endif
endif
ifeq ($(PLATFORM),PLATFORM_DRM) ifeq ($(PLATFORM),PLATFORM_DRM)
# Libraries for DRM compiling # Libraries for DRM compiling
# NOTE: Required packages: libasound2-dev (ALSA) # NOTE: Required packages: libasound2-dev (ALSA)
@ -409,9 +370,11 @@ CORE = \
core/core_2d_camera \ core/core_2d_camera \
core/core_2d_camera_platformer \ core/core_2d_camera_platformer \
core/core_2d_camera_mouse_zoom \ core/core_2d_camera_mouse_zoom \
core/core_2d_camera_split_screen \
core/core_3d_camera_mode \ core/core_3d_camera_mode \
core/core_3d_camera_free \ core/core_3d_camera_free \
core/core_3d_camera_first_person \ core/core_3d_camera_first_person \
core/core_3d_camera_split_screen \
core/core_3d_picking \ core/core_3d_picking \
core/core_world_screen \ core/core_world_screen \
core/core_custom_logging \ core/core_custom_logging \
@ -424,7 +387,6 @@ CORE = \
core/core_window_flags \ core/core_window_flags \
core/core_window_letterbox \ core/core_window_letterbox \
core/core_window_should_close \ core/core_window_should_close \
core/core_split_screen \
core/core_smooth_pixelperfect \ core/core_smooth_pixelperfect \
core/core_custom_frame_control core/core_custom_frame_control
@ -470,7 +432,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 \
@ -524,6 +487,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 \
@ -586,10 +550,6 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
rm -f *.o rm -f *.o
endif endif
endif endif
ifeq ($(PLATFORM),PLATFORM_RPI)
find . -type f -executable -delete
rm -fv *.o
endif
ifeq ($(PLATFORM),PLATFORM_DRM) ifeq ($(PLATFORM),PLATFORM_DRM)
find . -type f -executable -delete find . -type f -executable -delete
rm -fv *.o rm -fv *.o

View File

@ -25,7 +25,7 @@
# Define required environment variables # Define required environment variables
#------------------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------------------
# Define target platform: PLATFORM_DESKTOP, PLATFORM_RPI, PLATFORM_DRM, PLATFORM_ANDROID, PLATFORM_WEB # Define target platform: PLATFORM_DESKTOP, PLATFORM_DRM, PLATFORM_ANDROID, PLATFORM_WEB
PLATFORM ?= PLATFORM_WEB PLATFORM ?= PLATFORM_WEB
# Define required raylib variables # Define required raylib variables
@ -51,15 +51,6 @@ USE_EXTERNAL_GLFW ?= FALSE
# NOTE: This variable is only used for PLATFORM_OS: LINUX # NOTE: This variable is only used for PLATFORM_OS: LINUX
USE_WAYLAND_DISPLAY ?= FALSE USE_WAYLAND_DISPLAY ?= FALSE
# Use cross-compiler for PLATFORM_RPI
ifeq ($(PLATFORM),PLATFORM_RPI)
USE_RPI_CROSS_COMPILER ?= FALSE
ifeq ($(USE_RPI_CROSS_COMPILER),TRUE)
RPI_TOOLCHAIN ?= C:/SysGCC/Raspberry
RPI_TOOLCHAIN_SYSROOT ?= $(RPI_TOOLCHAIN)/arm-linux-gnueabihf/sysroot
endif
endif
# Determine PLATFORM_OS in case PLATFORM_DESKTOP or PLATFORM_WEB selected # Determine PLATFORM_OS in case PLATFORM_DESKTOP or PLATFORM_WEB selected
ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_DESKTOP PLATFORM_WEB)) ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_DESKTOP PLATFORM_WEB))
# No uname.exe on MinGW!, but OS=Windows_NT on Windows! # No uname.exe on MinGW!, but OS=Windows_NT on Windows!
@ -88,12 +79,6 @@ ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_DESKTOP PLATFORM_WEB))
endif endif
endif endif
endif endif
ifeq ($(PLATFORM),PLATFORM_RPI)
UNAMEOS = $(shell uname)
ifeq ($(UNAMEOS),Linux)
PLATFORM_OS = LINUX
endif
endif
ifeq ($(PLATFORM),PLATFORM_DRM) ifeq ($(PLATFORM),PLATFORM_DRM)
UNAMEOS = $(shell uname) UNAMEOS = $(shell uname)
ifeq ($(UNAMEOS),Linux) ifeq ($(UNAMEOS),Linux)
@ -111,9 +96,6 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
endif endif
# Default path for raylib on Raspberry Pi # Default path for raylib on Raspberry Pi
ifeq ($(PLATFORM),PLATFORM_RPI)
RAYLIB_PATH ?= /home/pi/raylib
endif
ifeq ($(PLATFORM),PLATFORM_DRM) ifeq ($(PLATFORM),PLATFORM_DRM)
RAYLIB_PATH ?= /home/pi/raylib RAYLIB_PATH ?= /home/pi/raylib
endif endif
@ -147,13 +129,6 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
CC = clang CC = clang
endif endif
endif endif
ifeq ($(PLATFORM),PLATFORM_RPI)
ifeq ($(USE_RPI_CROSS_COMPILER),TRUE)
# Define RPI cross-compiler
#CC = armv6j-hardfloat-linux-gnueabi-gcc
CC = $(RPI_TOOLCHAIN)/bin/arm-linux-gnueabihf-gcc
endif
endif
ifeq ($(PLATFORM),PLATFORM_WEB) ifeq ($(PLATFORM),PLATFORM_WEB)
# HTML5 emscripten compiler # HTML5 emscripten compiler
# WARNING: To compile to HTML5, code must be redesigned # WARNING: To compile to HTML5, code must be redesigned
@ -224,9 +199,6 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
endif endif
endif endif
endif endif
ifeq ($(PLATFORM),PLATFORM_RPI)
CFLAGS += -std=gnu99
endif
ifeq ($(PLATFORM),PLATFORM_DRM) ifeq ($(PLATFORM),PLATFORM_DRM)
CFLAGS += -std=gnu99 -DEGL_NO_X11 CFLAGS += -std=gnu99 -DEGL_NO_X11
endif endif
@ -245,11 +217,6 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
INCLUDE_PATHS += -I$(RAYLIB_INCLUDE_PATH) INCLUDE_PATHS += -I$(RAYLIB_INCLUDE_PATH)
endif endif
endif endif
ifeq ($(PLATFORM),PLATFORM_RPI)
INCLUDE_PATHS += -I$(RPI_TOOLCHAIN_SYSROOT)/opt/vc/include
INCLUDE_PATHS += -I$(RPI_TOOLCHAIN_SYSROOT)/opt/vc/include/interface/vmcs_host/linux
INCLUDE_PATHS += -I$(RPI_TOOLCHAIN_SYSROOT)/opt/vc/include/interface/vcos/pthreads
endif
ifeq ($(PLATFORM),PLATFORM_DRM) ifeq ($(PLATFORM),PLATFORM_DRM)
INCLUDE_PATHS += -I/usr/include/libdrm INCLUDE_PATHS += -I/usr/include/libdrm
endif endif
@ -304,9 +271,6 @@ ifeq ($(PLATFORM),PLATFORM_WEB)
LDFLAGS += --shell-file $(RAYLIB_PATH)/src/shell.html LDFLAGS += --shell-file $(RAYLIB_PATH)/src/shell.html
EXT = .html EXT = .html
endif endif
ifeq ($(PLATFORM),PLATFORM_RPI)
LDFLAGS += -L$(RPI_TOOLCHAIN_SYSROOT)/opt/vc/lib
endif
# Define libraries required on linking: LDLIBS # Define libraries required on linking: LDLIBS
# NOTE: To link libraries (lib<name>.so or lib<name>.a), use -l<name> # NOTE: To link libraries (lib<name>.so or lib<name>.a), use -l<name>
@ -357,14 +321,6 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
LDLIBS += -lglfw LDLIBS += -lglfw
endif endif
endif endif
ifeq ($(PLATFORM),PLATFORM_RPI)
# Libraries for Raspberry Pi compiling
# NOTE: Required packages: libasound2-dev (ALSA)
LDLIBS = -lraylib -lbrcmGLESv2 -lbrcmEGL -lpthread -lrt -lm -lbcm_host -ldl -latomic
ifeq ($(USE_RPI_CROSS_COMPILER),TRUE)
LDLIBS += -lvchiq_arm -lvcos
endif
endif
ifeq ($(PLATFORM),PLATFORM_DRM) ifeq ($(PLATFORM),PLATFORM_DRM)
# Libraries for DRM compiling # Libraries for DRM compiling
# NOTE: Required packages: libasound2-dev (ALSA) # NOTE: Required packages: libasound2-dev (ALSA)
@ -390,9 +346,11 @@ CORE = \
core/core_2d_camera \ core/core_2d_camera \
core/core_2d_camera_platformer \ core/core_2d_camera_platformer \
core/core_2d_camera_mouse_zoom \ core/core_2d_camera_mouse_zoom \
core/core_2d_camera_split_screen \
core/core_3d_camera_mode \ core/core_3d_camera_mode \
core/core_3d_camera_free \ core/core_3d_camera_free \
core/core_3d_camera_first_person \ core/core_3d_camera_first_person \
core/core_3d_camera_split_screen \
core/core_3d_picking \ core/core_3d_picking \
core/core_world_screen \ core/core_world_screen \
core/core_custom_logging \ core/core_custom_logging \
@ -404,7 +362,6 @@ CORE = \
core/core_window_flags \ core/core_window_flags \
core/core_window_letterbox \ core/core_window_letterbox \
core/core_window_should_close \ core/core_window_should_close \
core/core_split_screen \
core/core_smooth_pixelperfect \ core/core_smooth_pixelperfect \
core/core_custom_frame_control \ core/core_custom_frame_control \
core/core_loading_thread core/core_loading_thread
@ -450,7 +407,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 \
@ -504,6 +462,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 \
@ -571,6 +530,9 @@ core/core_2d_camera_platformer: core/core_2d_camera_platformer.c
core/core_2d_camera_mouse_zoom: core/core_2d_camera_mouse_zoom.c core/core_2d_camera_mouse_zoom: core/core_2d_camera_mouse_zoom.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
core/core_2d_camera_split_screen: core/core_2d_camera_split_screen.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
core/core_3d_camera_mode: core/core_3d_camera_mode.c core/core_3d_camera_mode: core/core_3d_camera_mode.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
@ -580,6 +542,9 @@ core/core_3d_camera_free: core/core_3d_camera_free.c
core/core_3d_camera_first_person: core/core_3d_camera_first_person.c core/core_3d_camera_first_person: core/core_3d_camera_first_person.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
core/core_3d_camera_split_screen: core/core_3d_camera_split_screen.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
core/core_3d_picking: core/core_3d_picking.c core/core_3d_picking: core/core_3d_picking.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
@ -611,9 +576,6 @@ core/core_vr_simulator: core/core_vr_simulator.c
core/core_window_flags: core/core_window_flags.c core/core_window_flags: core/core_window_flags.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
core/core_split_screen: core/core_split_screen.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
core/core_smooth_pixelperfect: core/core_smooth_pixelperfect.c core/core_smooth_pixelperfect: core/core_smooth_pixelperfect.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
@ -1065,10 +1027,6 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
rm -f *.o rm -f *.o
endif endif
endif endif
ifeq ($(PLATFORM),PLATFORM_RPI)
find . -type f -executable -delete
rm -fv *.o
endif
ifeq ($(PLATFORM),PLATFORM_DRM) ifeq ($(PLATFORM),PLATFORM_DRM)
find . -type f -executable -delete find . -type f -executable -delete
rm -fv *.o rm -fv *.o

View File

@ -34,26 +34,27 @@ Examples using raylib core platform functionality like window creation, inputs,
| 08 | [core_2d_camera](core/core_2d_camera.c) | <img src="core/core_2d_camera.png" alt="core_2d_camera" width="80"> | ⭐️⭐️☆☆ | 1.5 | 3.0 | [Ray](https://github.com/raysan5) | | 08 | [core_2d_camera](core/core_2d_camera.c) | <img src="core/core_2d_camera.png" alt="core_2d_camera" width="80"> | ⭐️⭐️☆☆ | 1.5 | 3.0 | [Ray](https://github.com/raysan5) |
| 09 | [core_2d_camera_mouse_zoom](core/core_2d_camera_mouse_zoom.c) | <img src="core/core_2d_camera_mouse_zoom.png" alt="core_2d_camera_mouse_zoom" width="80"> | ⭐️⭐️☆☆ | **4.2** | **4.2** | [Jeffery Myers](https://github.com/JeffM2501) | | 09 | [core_2d_camera_mouse_zoom](core/core_2d_camera_mouse_zoom.c) | <img src="core/core_2d_camera_mouse_zoom.png" alt="core_2d_camera_mouse_zoom" width="80"> | ⭐️⭐️☆☆ | **4.2** | **4.2** | [Jeffery Myers](https://github.com/JeffM2501) |
| 10 | [core_2d_camera_platformer](core/core_2d_camera_platformer.c) | <img src="core/core_2d_camera_platformer.png" alt="core_2d_camera_platformer" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | 3.0 | [avyy](https://github.com/avyy) | | 10 | [core_2d_camera_platformer](core/core_2d_camera_platformer.c) | <img src="core/core_2d_camera_platformer.png" alt="core_2d_camera_platformer" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | 3.0 | [avyy](https://github.com/avyy) |
| 11 | [core_3d_camera_mode](core/core_3d_camera_mode.c) | <img src="core/core_3d_camera_mode.png" alt="core_3d_camera_mode" width="80"> | ⭐️☆☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) | | 11 | [core_2d_camera_split_screen](core/core_2d_camera_split_screen.c) | <img src="core/core_2d_camera_split_screen.png" alt="core_2d_camera_split_screen" width="80"> | ⭐️⭐️⭐️⭐️ | **4.5** | **4.5** | [Gabriel dos Santos Sanches](https://github.com/gabrielssanches) |
| 12 | [core_3d_camera_free](core/core_3d_camera_free.c) | <img src="core/core_3d_camera_free.png" alt="core_3d_camera_free" width="80"> | ⭐️☆☆☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) | | 12 | [core_3d_camera_mode](core/core_3d_camera_mode.c) | <img src="core/core_3d_camera_mode.png" alt="core_3d_camera_mode" width="80"> | ⭐️☆☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) |
| 13 | [core_3d_camera_first_person](core/core_3d_camera_first_person.c) | <img src="core/core_3d_camera_first_person.png" alt="core_3d_camera_first_person" width="80"> | ⭐️⭐️☆☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) | | 13 | [core_3d_camera_free](core/core_3d_camera_free.c) | <img src="core/core_3d_camera_free.png" alt="core_3d_camera_free" width="80"> | ⭐️☆☆☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) |
| 14 | [core_3d_picking](core/core_3d_picking.c) | <img src="core/core_3d_picking.png" alt="core_3d_picking" width="80"> | ⭐️⭐️☆☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) | | 14 | [core_3d_camera_first_person](core/core_3d_camera_first_person.c) | <img src="core/core_3d_camera_first_person.png" alt="core_3d_camera_first_person" width="80"> | ⭐️⭐️☆☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) |
| 15 | [core_world_screen](core/core_world_screen.c) | <img src="core/core_world_screen.png" alt="core_world_screen" width="80"> | ⭐️⭐️☆☆ | 1.3 | 1.4 | [Ray](https://github.com/raysan5) | | 15 | [core_3d_camera:split_screen](core/core_3d_camera_split_screen.c) | <img src="core/core_3d_camera_split_screen.png" alt="core_3d_camera_split_screen" width="80"> | ⭐️⭐️⭐️⭐️ | 3.7 | **4.0** | [Jeffery Myers](https://github.com/JeffM2501) |
| 16 | [core_custom_logging](core/core_custom_logging.c) | <img src="core/core_custom_logging.png" alt="core_custom_logging" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Pablo Marcos Oltra](https://github.com/pamarcos) | | 16 | [core_3d_picking](core/core_3d_picking.c) | <img src="core/core_3d_picking.png" alt="core_3d_picking" width="80"> | ⭐️⭐️☆☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) |
| 17 | [core_window_flags](core/core_window_flags.c) | <img src="core/core_window_flags.png" alt="core_window_flags" width="80"> | ⭐️⭐️⭐️☆ | 3.5 | 3.5 | [Ray](https://github.com/raysan5) | | 17 | [core_world_screen](core/core_world_screen.c) | <img src="core/core_world_screen.png" alt="core_world_screen" width="80"> | ⭐️⭐️☆☆ | 1.3 | 1.4 | [Ray](https://github.com/raysan5) |
| 18 | [core_window_letterbox](core/core_window_letterbox.c) | <img src="core/core_window_letterbox.png" alt="core_window_letterbox" width="80"> | ⭐️⭐️☆☆ | 2.5 | **4.0** | [Anata](https://github.com/anatagawa) | | 18 | [core_custom_logging](core/core_custom_logging.c) | <img src="core/core_custom_logging.png" alt="core_custom_logging" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Pablo Marcos Oltra](https://github.com/pamarcos) |
| 19 | [core_window_should_close](core/core_window_should_close.c) | <img src="core/core_window_should_close.png" alt="core_window_should_close" width="80"> | ⭐️☆☆☆ | **4.2** | **4.2** | [Ray](https://github.com/raysan5) | | 19 | [core_window_flags](core/core_window_flags.c) | <img src="core/core_window_flags.png" alt="core_window_flags" width="80"> | ⭐️⭐️⭐️☆ | 3.5 | 3.5 | [Ray](https://github.com/raysan5) |
| 20 | [core_drop_files](core/core_drop_files.c) | <img src="core/core_drop_files.png" alt="core_drop_files" width="80"> | ⭐️⭐️☆☆ | 1.3 | **4.2** | [Ray](https://github.com/raysan5) | | 20 | [core_window_letterbox](core/core_window_letterbox.c) | <img src="core/core_window_letterbox.png" alt="core_window_letterbox" width="80"> | ⭐️⭐️☆☆ | 2.5 | **4.0** | [Anata](https://github.com/anatagawa) |
| 21 | [core_random_values](core/core_random_values.c) | <img src="core/core_random_values.png" alt="core_random_values" width="80"> | ⭐️☆☆☆ | 1.1 | 1.1 | [Ray](https://github.com/raysan5) | | 21 | [core_window_should_close](core/core_window_should_close.c) | <img src="core/core_window_should_close.png" alt="core_window_should_close" width="80"> | ⭐️☆☆☆ | **4.2** | **4.2** | [Ray](https://github.com/raysan5) |
| 22 | [core_storage_values](core/core_storage_values.c) | <img src="core/core_storage_values.png" alt="core_storage_values" width="80"> | ⭐️⭐️☆☆ | 1.4 | **4.2** | [Ray](https://github.com/raysan5) | | 22 | [core_drop_files](core/core_drop_files.c) | <img src="core/core_drop_files.png" alt="core_drop_files" width="80"> | ⭐️⭐️☆☆ | 1.3 | **4.2** | [Ray](https://github.com/raysan5) |
| 23 | [core_vr_simulator](core/core_vr_simulator.c) | <img src="core/core_vr_simulator.png" alt="core_vr_simulator" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | **4.0** | [Ray](https://github.com/raysan5) | | 23 | [core_random_values](core/core_random_values.c) | <img src="core/core_random_values.png" alt="core_random_values" width="80"> | ⭐️☆☆☆ | 1.1 | 1.1 | [Ray](https://github.com/raysan5) |
| 24 | [core_loading_thread](core/core_loading_thread.c) | <img src="core/core_loading_thread.png" alt="core_loading_thread" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | 3.0 | [Ray](https://github.com/raysan5) | | 24 | [core_storage_values](core/core_storage_values.c) | <img src="core/core_storage_values.png" alt="core_storage_values" width="80"> | ⭐️⭐️☆☆ | 1.4 | **4.2** | [Ray](https://github.com/raysan5) |
| 25 | [core_scissor_test](core/core_scissor_test.c) | <img src="core/core_scissor_test.png" alt="core_scissor_test" width="80"> | ⭐️☆☆☆ | 2.5 | 3.0 | [Chris Dill](https://github.com/MysteriousSpace) | | 25 | [core_vr_simulator](core/core_vr_simulator.c) | <img src="core/core_vr_simulator.png" alt="core_vr_simulator" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | **4.0** | [Ray](https://github.com/raysan5) |
| 26 | [core_basic_screen_manager](core/core_basic_screen_manager.c) | <img src="core/core_basic_screen_manager.png" alt="core_basic_screen_manager" width="80"> | ⭐️☆☆☆ | **4.0** | **4.0** | [Ray](https://github.com/raysan5) | | 26 | [core_loading_thread](core/core_loading_thread.c) | <img src="core/core_loading_thread.png" alt="core_loading_thread" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | 3.0 | [Ray](https://github.com/raysan5) |
| 27 | [core_custom_frame_control](core/core_custom_frame_control.c) | <img src="core/core_custom_frame_control.png" alt="core_custom_frame_control" width="80"> | ⭐️⭐️⭐️⭐️ | **4.0** | **4.0** | [Ray](https://github.com/raysan5) | | 27 | [core_scissor_test](core/core_scissor_test.c) | <img src="core/core_scissor_test.png" alt="core_scissor_test" width="80"> | ⭐️☆☆☆ | 2.5 | 3.0 | [Chris Dill](https://github.com/MysteriousSpace) |
| 28 | [core_smooth_pixelperfect](core/core_smooth_pixelperfect.c) | <img src="core/core_smooth_pixelperfect.png" alt="core_smooth_pixelperfect" width="80"> | ⭐️⭐️⭐️☆ | 3.7 | **4.0** | [Giancamillo Alessandroni](https://github.com/NotManyIdeasDev) | | 28 | [core_basic_screen_manager](core/core_basic_screen_manager.c) | <img src="core/core_basic_screen_manager.png" alt="core_basic_screen_manager" width="80"> | ⭐️☆☆☆ | **4.0** | **4.0** | [Ray](https://github.com/raysan5) |
| 29 | [core_split_screen](core/core_split_screen.c) | <img src="core/core_split_screen.png" alt="core_split_screen" width="80"> | ⭐️⭐️⭐️⭐️ | 3.7 | **4.0** | [Jeffery Myers](https://github.com/JeffM2501) | | 29 | [core_custom_frame_control](core/core_custom_frame_control.c) | <img src="core/core_custom_frame_control.png" alt="core_custom_frame_control" width="80"> | ⭐️⭐️⭐️⭐️ | **4.0** | **4.0** | [Ray](https://github.com/raysan5) |
| 30 | [core_window_should_close](core/core_window_should_close.c) | <img src="core/core_window_should_close.png" alt="core_window_should_close" width="80"> | ⭐️⭐️☆☆ | **4.2** | **4.2** | [Ray](https://github.com/raysan5) | | 30 | [core_smooth_pixelperfect](core/core_smooth_pixelperfect.c) | <img src="core/core_smooth_pixelperfect.png" alt="core_smooth_pixelperfect" width="80"> | ⭐️⭐️⭐️☆ | 3.7 | **4.0** | [Giancamillo Alessandroni](https://github.com/NotManyIdeasDev) |
| 31 | [core_window_should_close](core/core_window_should_close.c) | <img src="core/core_window_should_close.png" alt="core_window_should_close" width="80"> | ⭐️⭐️☆☆ | **4.2** | **4.2** | [Ray](https://github.com/raysan5) |
### category: shapes ### category: shapes

View File

@ -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();
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@ -0,0 +1,167 @@
/*******************************************************************************************
*
* raylib [core] example - 2d camera split screen
*
* Addapted from the core_3d_camera_split_screen example:
* https://github.com/raysan5/raylib/blob/master/examples/core/core_3d_camera_split_screen.c
*
* Example originally created with raylib 4.5, last time updated with raylib 4.5
*
* Example contributed by Gabriel dos Santos Sanches (@gabrielssanches) and reviewed by Ramon Santamaria (@raysan5)
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2023 Gabriel dos Santos Sanches (@gabrielssanches)
*
********************************************************************************************/
#include "raylib.h"
#define PLAYER_SIZE 40
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 440;
InitWindow(screenWidth, screenHeight, "raylib [core] example - 2d camera split screen");
Rectangle player1 = { 200, 200, PLAYER_SIZE, PLAYER_SIZE };
Rectangle player2 = { 250, 200, PLAYER_SIZE, PLAYER_SIZE };
Camera2D camera1 = { 0 };
camera1.target = (Vector2){ player1.x, player1.y };
camera1.offset = (Vector2){ 200.0f, 200.0f };
camera1.rotation = 0.0f;
camera1.zoom = 1.0f;
Camera2D camera2 = { 0 };
camera2.target = (Vector2){ player2.x, player2.y };
camera2.offset = (Vector2){ 200.0f, 200.0f };
camera2.rotation = 0.0f;
camera2.zoom = 1.0f;
RenderTexture screenCamera1 = LoadRenderTexture(screenWidth/2, screenHeight);
RenderTexture screenCamera2 = LoadRenderTexture(screenWidth/2, screenHeight);
// Build a flipped rectangle the size of the split view to use for drawing later
Rectangle splitScreenRect = { 0.0f, 0.0f, (float)screenCamera1.texture.width, (float)-screenCamera1.texture.height };
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
//----------------------------------------------------------------------------------
if (IsKeyDown(KEY_S)) player1.y += 3.0f;
else if (IsKeyDown(KEY_W)) player1.y -= 3.0f;
if (IsKeyDown(KEY_D)) player1.x += 3.0f;
else if (IsKeyDown(KEY_A)) player1.x -= 3.0f;
if (IsKeyDown(KEY_UP)) player2.y -= 3.0f;
else if (IsKeyDown(KEY_DOWN)) player2.y += 3.0f;
if (IsKeyDown(KEY_RIGHT)) player2.x += 3.0f;
else if (IsKeyDown(KEY_LEFT)) player2.x -= 3.0f;
camera1.target = (Vector2){ player1.x, player1.y };
camera2.target = (Vector2){ player2.x, player2.y };
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginTextureMode(screenCamera1);
ClearBackground(RAYWHITE);
BeginMode2D(camera1);
// Draw full scene with first camera
for (int i = 0; i < screenWidth/PLAYER_SIZE + 1; i++)
{
DrawLineV((Vector2){PLAYER_SIZE*i, 0}, (Vector2){PLAYER_SIZE*i, screenHeight}, LIGHTGRAY);
}
for (int i = 0; i < screenHeight/PLAYER_SIZE + 1; i++)
{
DrawLineV((Vector2){0, PLAYER_SIZE*i}, (Vector2){screenWidth, PLAYER_SIZE*i}, LIGHTGRAY);
}
for (int i = 0; i < screenWidth/PLAYER_SIZE; i++)
{
for (int j = 0; j < screenHeight/PLAYER_SIZE; j++)
{
DrawText(TextFormat("[%i,%i]", i, j), 10 + PLAYER_SIZE*i, 15 + PLAYER_SIZE*j, 10, LIGHTGRAY);
}
}
DrawRectangleRec(player1, RED);
DrawRectangleRec(player2, BLUE);
EndMode2D();
DrawRectangle(0, 0, GetScreenWidth()/2, 30, Fade(RAYWHITE, 0.6f));
DrawText("PLAYER1: W/S/A/D to move", 10, 10, 10, MAROON);
EndTextureMode();
BeginTextureMode(screenCamera2);
ClearBackground(RAYWHITE);
BeginMode2D(camera2);
// Draw full scene with second camera
for (int i = 0; i < screenWidth/PLAYER_SIZE + 1; i++)
{
DrawLineV((Vector2){PLAYER_SIZE*i, 0}, (Vector2){PLAYER_SIZE*i, screenHeight}, LIGHTGRAY);
}
for (int i = 0; i < screenHeight/PLAYER_SIZE + 1; i++)
{
DrawLineV((Vector2){0, PLAYER_SIZE*i}, (Vector2){screenWidth, PLAYER_SIZE*i}, LIGHTGRAY);
}
for (int i = 0; i < screenWidth/PLAYER_SIZE; i++)
{
for (int j = 0; j < screenHeight/PLAYER_SIZE; j++)
{
DrawText(TextFormat("[%i,%i]", i, j), 10 + PLAYER_SIZE*i, 15 + PLAYER_SIZE*j, 10, LIGHTGRAY);
}
}
DrawRectangleRec(player1, RED);
DrawRectangleRec(player2, BLUE);
EndMode2D();
DrawRectangle(0, 0, GetScreenWidth()/2, 30, Fade(RAYWHITE, 0.6f));
DrawText("PLAYER2: UP/DOWN/LEFT/RIGHT to move", 10, 10, 10, DARKBLUE);
EndTextureMode();
// Draw both views render textures to the screen side by side
BeginDrawing();
ClearBackground(BLACK);
DrawTextureRec(screenCamera1.texture, splitScreenRect, (Vector2){ 0, 0 }, WHITE);
DrawTextureRec(screenCamera2.texture, splitScreenRect, (Vector2){ screenWidth/2.0f, 0 }, WHITE);
DrawRectangle(GetScreenWidth()/2 - 2, 0, 4, GetScreenHeight(), LIGHTGRAY);
EndDrawing();
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadRenderTexture(screenCamera1); // Unload render texture
UnloadRenderTexture(screenCamera2); // Unload render texture
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -72,7 +72,7 @@ int main(void)
DrawText("- Mouse Wheel to Zoom in-out", 40, 40, 10, DARKGRAY); DrawText("- Mouse Wheel to Zoom in-out", 40, 40, 10, DARKGRAY);
DrawText("- Mouse Wheel Pressed to Pan", 40, 60, 10, DARKGRAY); DrawText("- Mouse Wheel Pressed to Pan", 40, 60, 10, DARKGRAY);
DrawText("- Alt + Mouse Wheel Pressed to Rotate", 40, 80, 10, DARKGRAY); DrawText("- Alt + Mouse Wheel Pressed to Rotate", 40, 80, 10, DARKGRAY);
DrawText("- Alt + Ctrl + Mouse Wheel Pressed for Smooth Zoom", 40, 100, 10, DARKGRAY); //DrawText("- Alt + Ctrl + Mouse Wheel Pressed for Smooth Zoom", 40, 100, 10, DARKGRAY);
DrawText("- Z to zoom to (0, 0, 0)", 40, 120, 10, DARKGRAY); DrawText("- Z to zoom to (0, 0, 0)", 40, 120, 10, DARKGRAY);
EndDrawing(); EndDrawing();

View File

@ -1,6 +1,6 @@
/******************************************************************************************* /*******************************************************************************************
* *
* raylib [core] example - split screen * raylib [core] example - 3d cmaera split screen
* *
* Example originally created with raylib 3.7, last time updated with raylib 4.0 * Example originally created with raylib 3.7, last time updated with raylib 4.0
* *
@ -15,32 +15,6 @@
#include "raylib.h" #include "raylib.h"
Camera cameraPlayer1 = { 0 };
Camera cameraPlayer2 = { 0 };
// Scene drawing
void DrawScene(void)
{
int count = 5;
float spacing = 4;
// Grid of cube trees on a plane to make a "world"
DrawPlane((Vector3){ 0, 0, 0 }, (Vector2){ 50, 50 }, BEIGE); // Simple world plane
for (float x = -count*spacing; x <= count*spacing; x += spacing)
{
for (float z = -count*spacing; z <= count*spacing; z += spacing)
{
DrawCube((Vector3) { x, 1.5f, z }, 1, 1, 1, LIME);
DrawCube((Vector3) { x, 0.5f, z }, 0.25f, 1, 0.25f, BROWN);
}
}
// Draw a cube at each player's position
DrawCube(cameraPlayer1.position, 1, 1, 1, RED);
DrawCube(cameraPlayer2.position, 1, 1, 1, BLUE);
}
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Program main entry point // Program main entry point
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
@ -51,9 +25,10 @@ int main(void)
const int screenWidth = 800; const int screenWidth = 800;
const int screenHeight = 450; const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - split screen"); InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera split screen");
// Setup player 1 camera and screen // Setup player 1 camera and screen
Camera cameraPlayer1 = { 0 };
cameraPlayer1.fovy = 45.0f; cameraPlayer1.fovy = 45.0f;
cameraPlayer1.up.y = 1.0f; cameraPlayer1.up.y = 1.0f;
cameraPlayer1.target.y = 1.0f; cameraPlayer1.target.y = 1.0f;
@ -63,6 +38,7 @@ int main(void)
RenderTexture screenPlayer1 = LoadRenderTexture(screenWidth/2, screenHeight); RenderTexture screenPlayer1 = LoadRenderTexture(screenWidth/2, screenHeight);
// Setup player two camera and screen // Setup player two camera and screen
Camera cameraPlayer2 = { 0 };
cameraPlayer2.fovy = 45.0f; cameraPlayer2.fovy = 45.0f;
cameraPlayer2.up.y = 1.0f; cameraPlayer2.up.y = 1.0f;
cameraPlayer2.target.y = 3.0f; cameraPlayer2.target.y = 3.0f;
@ -74,6 +50,10 @@ int main(void)
// Build a flipped rectangle the size of the split view to use for drawing later // Build a flipped rectangle the size of the split view to use for drawing later
Rectangle splitScreenRect = { 0.0f, 0.0f, (float)screenPlayer1.texture.width, (float)-screenPlayer1.texture.height }; Rectangle splitScreenRect = { 0.0f, 0.0f, (float)screenPlayer1.texture.width, (float)-screenPlayer1.texture.height };
// Grid data
int count = 5;
float spacing = 4;
SetTargetFPS(60); // Set our game to run at 60 frames-per-second SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
@ -116,26 +96,69 @@ int main(void)
// Draw Player1 view to the render texture // Draw Player1 view to the render texture
BeginTextureMode(screenPlayer1); BeginTextureMode(screenPlayer1);
ClearBackground(SKYBLUE); ClearBackground(SKYBLUE);
BeginMode3D(cameraPlayer1); BeginMode3D(cameraPlayer1);
DrawScene();
// Draw scene: grid of cube trees on a plane to make a "world"
DrawPlane((Vector3){ 0, 0, 0 }, (Vector2){ 50, 50 }, BEIGE); // Simple world plane
for (float x = -count*spacing; x <= count*spacing; x += spacing)
{
for (float z = -count*spacing; z <= count*spacing; z += spacing)
{
DrawCube((Vector3) { x, 1.5f, z }, 1, 1, 1, LIME);
DrawCube((Vector3) { x, 0.5f, z }, 0.25f, 1, 0.25f, BROWN);
}
}
// Draw a cube at each player's position
DrawCube(cameraPlayer1.position, 1, 1, 1, RED);
DrawCube(cameraPlayer2.position, 1, 1, 1, BLUE);
EndMode3D(); EndMode3D();
DrawText("PLAYER1 W/S to move", 10, 10, 20, RED);
DrawRectangle(0, 0, GetScreenWidth()/2, 40, Fade(RAYWHITE, 0.8f));
DrawText("PLAYER1: W/S to move", 10, 10, 20, MAROON);
EndTextureMode(); EndTextureMode();
// Draw Player2 view to the render texture // Draw Player2 view to the render texture
BeginTextureMode(screenPlayer2); BeginTextureMode(screenPlayer2);
ClearBackground(SKYBLUE); ClearBackground(SKYBLUE);
BeginMode3D(cameraPlayer2); BeginMode3D(cameraPlayer2);
DrawScene();
// Draw scene: grid of cube trees on a plane to make a "world"
DrawPlane((Vector3){ 0, 0, 0 }, (Vector2){ 50, 50 }, BEIGE); // Simple world plane
for (float x = -count*spacing; x <= count*spacing; x += spacing)
{
for (float z = -count*spacing; z <= count*spacing; z += spacing)
{
DrawCube((Vector3) { x, 1.5f, z }, 1, 1, 1, LIME);
DrawCube((Vector3) { x, 0.5f, z }, 0.25f, 1, 0.25f, BROWN);
}
}
// Draw a cube at each player's position
DrawCube(cameraPlayer1.position, 1, 1, 1, RED);
DrawCube(cameraPlayer2.position, 1, 1, 1, BLUE);
EndMode3D(); EndMode3D();
DrawText("PLAYER2 UP/DOWN to move", 10, 10, 20, BLUE);
DrawRectangle(0, 0, GetScreenWidth()/2, 40, Fade(RAYWHITE, 0.8f));
DrawText("PLAYER2: UP/DOWN to move", 10, 10, 20, DARKBLUE);
EndTextureMode(); EndTextureMode();
// Draw both views render textures to the screen side by side // Draw both views render textures to the screen side by side
BeginDrawing(); BeginDrawing();
ClearBackground(BLACK); ClearBackground(BLACK);
DrawTextureRec(screenPlayer1.texture, splitScreenRect, (Vector2){ 0, 0 }, WHITE); DrawTextureRec(screenPlayer1.texture, splitScreenRect, (Vector2){ 0, 0 }, WHITE);
DrawTextureRec(screenPlayer2.texture, splitScreenRect, (Vector2){ screenWidth/2.0f, 0 }, WHITE); DrawTextureRec(screenPlayer2.texture, splitScreenRect, (Vector2){ screenWidth/2.0f, 0 }, WHITE);
DrawRectangle(GetScreenWidth()/2 - 2, 0, 4, GetScreenHeight(), LIGHTGRAY);
EndDrawing(); EndDrawing();
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -2,7 +2,7 @@
* *
* raylib [core] example - Basic window (adapted for HTML5 platform) * raylib [core] example - Basic window (adapted for HTML5 platform)
* *
* NOTE: This example is prepared to compile for PLATFORM_WEB, PLATFORM_DESKTOP and PLATFORM_RPI * NOTE: This example is prepared to compile for PLATFORM_WEB, and PLATFORM_DESKTOP
* As you will notice, code structure is slightly diferent to the other examples... * As you will notice, code structure is slightly diferent to the other examples...
* To compile it for PLATFORM_WEB just uncomment #define PLATFORM_WEB at beginning * To compile it for PLATFORM_WEB just uncomment #define PLATFORM_WEB at beginning
* *

View File

@ -21,13 +21,8 @@
// NOTE: Gamepad name ID depends on drivers and OS // NOTE: Gamepad name ID depends on drivers and OS
#define XBOX360_LEGACY_NAME_ID "Xbox Controller" #define XBOX360_LEGACY_NAME_ID "Xbox Controller"
#if defined(PLATFORM_RPI) #define XBOX360_NAME_ID "Xbox 360 Controller"
#define XBOX360_NAME_ID "Microsoft X-Box 360 pad" #define PS3_NAME_ID "PLAYSTATION(R)3 Controller"
#define PS3_NAME_ID "PLAYSTATION(R)3 Controller"
#else
#define XBOX360_NAME_ID "Xbox 360 Controller"
#define PS3_NAME_ID "PLAYSTATION(R)3 Controller"
#endif
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Program main entry point // Program main entry point

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

View File

@ -15,7 +15,7 @@
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330 #define GLSL_VERSION 330
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB #else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100 #define GLSL_VERSION 100
#endif #endif

View File

@ -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();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -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();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -18,7 +18,7 @@
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330 #define GLSL_VERSION 330
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB #else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100 #define GLSL_VERSION 100
#endif #endif

View File

@ -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);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -42,7 +42,7 @@
#endif #endif
#define GLSL_VERSION 330 #define GLSL_VERSION 330
#endif #endif
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB #else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100 #define GLSL_VERSION 100
#endif #endif

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -27,7 +27,7 @@
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330 #define GLSL_VERSION 330
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB #else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100 #define GLSL_VERSION 100
#endif #endif

View File

@ -22,7 +22,7 @@
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330 #define GLSL_VERSION 330
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB #else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100 #define GLSL_VERSION 100
#endif #endif

View File

@ -29,7 +29,7 @@
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330 #define GLSL_VERSION 330
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB #else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100 #define GLSL_VERSION 100
#endif #endif

View File

@ -27,7 +27,7 @@
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330 #define GLSL_VERSION 330
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB #else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100 #define GLSL_VERSION 100
#endif #endif

View File

@ -21,7 +21,7 @@
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330 #define GLSL_VERSION 330
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB #else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100 #define GLSL_VERSION 100
#endif #endif

View File

@ -20,7 +20,7 @@
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330 #define GLSL_VERSION 330
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB #else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100 #define GLSL_VERSION 100
#endif #endif

View File

@ -22,7 +22,7 @@
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330 #define GLSL_VERSION 330
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB #else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100 #define GLSL_VERSION 100
#endif #endif

View File

@ -25,7 +25,7 @@
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330 #define GLSL_VERSION 330
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB #else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100 #define GLSL_VERSION 100
#endif #endif

View File

@ -24,7 +24,7 @@
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330 #define GLSL_VERSION 330
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB #else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100 #define GLSL_VERSION 100
#endif #endif

View File

@ -22,7 +22,7 @@
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330 #define GLSL_VERSION 330
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB #else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100 #define GLSL_VERSION 100
#endif #endif

View File

@ -22,7 +22,7 @@
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330 #define GLSL_VERSION 330
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB #else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100 #define GLSL_VERSION 100
#endif #endif

View File

@ -24,7 +24,7 @@
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330 #define GLSL_VERSION 330
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB #else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100 #define GLSL_VERSION 100
#endif #endif

View File

@ -22,7 +22,7 @@
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330 #define GLSL_VERSION 330
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB #else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100 #define GLSL_VERSION 100
#endif #endif

View File

@ -18,7 +18,7 @@
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330 #define GLSL_VERSION 330
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB -> Not supported at this moment #else // PLATFORM_ANDROID, PLATFORM_WEB -> Not supported at this moment
#define GLSL_VERSION 100 #define GLSL_VERSION 100
#endif #endif

View File

@ -22,7 +22,7 @@
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330 #define GLSL_VERSION 330
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB #else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100 #define GLSL_VERSION 100
#endif #endif

View File

@ -25,7 +25,7 @@
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330 #define GLSL_VERSION 330
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB #else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100 #define GLSL_VERSION 100
#endif #endif

View File

@ -34,7 +34,7 @@
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330 #define GLSL_VERSION 330
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB #else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100 #define GLSL_VERSION 100
#endif #endif

View File

@ -19,7 +19,7 @@
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330 #define GLSL_VERSION 330
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB #else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100 #define GLSL_VERSION 100
#endif #endif

View File

@ -20,7 +20,7 @@
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330 #define GLSL_VERSION 330
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB #else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100 #define GLSL_VERSION 100
#endif #endif
@ -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);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 258 KiB

After

Width:  |  Height:  |  Size: 258 KiB

View File

@ -24,7 +24,7 @@
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330 #define GLSL_VERSION 330
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB #else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100 #define GLSL_VERSION 100
#endif #endif
@ -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");

View File

@ -19,7 +19,7 @@
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330 #define GLSL_VERSION 330
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB #else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100 #define GLSL_VERSION 100
#endif #endif

View File

@ -23,6 +23,7 @@ int main(void)
const int screenWidth = 800; const int screenWidth = 800;
const int screenHeight = 450; const int screenHeight = 450;
SetConfigFlags(FLAG_MSAA_4X_HINT);
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - bouncing ball"); InitWindow(screenWidth, screenHeight, "raylib [shapes] example - bouncing ball");
Vector2 ballPosition = { GetScreenWidth()/2.0f, GetScreenHeight()/2.0f }; Vector2 ballPosition = { GetScreenWidth()/2.0f, GetScreenHeight()/2.0f };
@ -61,11 +62,14 @@ int main(void)
ClearBackground(RAYWHITE); ClearBackground(RAYWHITE);
DrawCircleV(ballPosition, (float)ballRadius, MAROON); DrawCircleV(ballPosition, (float)ballRadius, MAROON);
DrawText("PRESS SPACE to PAUSE BALL MOVEMENT", 10, GetScreenHeight() - 25, 20, LIGHTGRAY); //DrawText("PRESS SPACE to PAUSE BALL MOVEMENT", 10, GetScreenHeight() - 25, 20, LIGHTGRAY);
// On pause, we draw a blinking message // On pause, we draw a blinking message
if (pause && ((framesCounter/30)%2)) DrawText("PAUSED", 350, 200, 30, GRAY); if (pause && ((framesCounter/30)%2)) DrawText("PAUSED", 350, 200, 30, GRAY);
DrawCircle(400.5, 300.5, 50, BLACK);
DrawCircle(528.0, 172.0, 26, BLACK);
DrawFPS(10, 10); DrawFPS(10, 10);
EndDrawing(); EndDrawing();

View File

@ -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();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -29,6 +29,9 @@ int main(void)
Vector2 start = { 0, 0 }; Vector2 start = { 0, 0 };
Vector2 end = { (float)screenWidth, (float)screenHeight }; Vector2 end = { (float)screenWidth, (float)screenHeight };
Vector2 startControl = { 100, 0 };
Vector2 endControl = { GetScreenWidth() - 100, GetScreenHeight() };
SetTargetFPS(60); // Set our game to run at 60 frames-per-second SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
@ -37,8 +40,16 @@ int main(void)
{ {
// Update // Update
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
if (IsMouseButtonDown(MOUSE_BUTTON_LEFT)) start = GetMousePosition(); if (IsKeyDown(KEY_LEFT_CONTROL))
else if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) end = GetMousePosition(); {
if (IsMouseButtonDown(MOUSE_BUTTON_LEFT)) startControl = GetMousePosition();
else if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) endControl = GetMousePosition();
}
else
{
if (IsMouseButtonDown(MOUSE_BUTTON_LEFT)) start = GetMousePosition();
else if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) end = GetMousePosition();
}
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw // Draw
@ -49,7 +60,14 @@ int main(void)
DrawText("USE MOUSE LEFT-RIGHT CLICK to DEFINE LINE START and END POINTS", 15, 20, 20, GRAY); DrawText("USE MOUSE LEFT-RIGHT CLICK to DEFINE LINE START and END POINTS", 15, 20, 20, GRAY);
DrawLineBezier(start, end, 2.0f, RED); //DrawLineBezier(start, end, 2.0f, RED);
DrawLineBezierCubic(start, end, startControl, endControl, 2.0f, RED);
DrawLineEx(start, startControl, 1.0, LIGHTGRAY);
DrawLineEx(end, endControl, 1.0, LIGHTGRAY);
DrawCircleV(startControl, 10, RED);
DrawCircleV(endControl, 10, RED);
EndDrawing(); EndDrawing();
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------

View File

@ -0,0 +1,155 @@
/*******************************************************************************************
*
* raylib [shapes] example - splines drawing
*
* Example originally created with raylib 4.6-dev, last time updated with raylib 4.6-dev
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2023 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#define MAX_CONTROL_POINTS 32
typedef struct {
Vector2 start;
Vector2 end;
} ControlPoint;
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
SetConfigFlags(FLAG_MSAA_4X_HINT);
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - splines drawing");
Vector2 points[MAX_CONTROL_POINTS] = {
{ 100.0f, 200.0f },
{ 300.0f, 400.0f },
{ 500.0f, 300.0f },
{ 700.0f, 100.0f },
{ 200.0f, 100.0f },
};
int pointCount = 5;
int selectedPoint = -1;
int splineType = 0; // 0-Linear, 1-BSpline, 2-CatmullRom, 3-Bezier
// Cubic Bezier control points
ControlPoint control[MAX_CONTROL_POINTS] = { 0 };
for (int i = 0; i < pointCount - 1; i++)
{
control[i].start = points[i];
control[i].end = points[i + 1];
}
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
//----------------------------------------------------------------------------------
// Points movement logic
if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON) && (pointCount < MAX_CONTROL_POINTS))
{
points[pointCount] = GetMousePosition();
pointCount++;
}
for (int i = 0; i < pointCount; i++)
{
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON) && CheckCollisionPointCircle(GetMousePosition(), points[i], 6.0f))
{
selectedPoint = i;
break;
}
}
if (selectedPoint >= 0)
{
points[selectedPoint] = GetMousePosition();
if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) selectedPoint = -1;
}
// TODO: Cubic Bezier spline control points logic
// Spline selection logic
if (IsKeyPressed(KEY_ONE)) splineType = 0;
else if (IsKeyPressed(KEY_TWO)) splineType = 1;
else if (IsKeyPressed(KEY_THREE)) splineType = 2;
else if (IsKeyPressed(KEY_FOUR)) splineType = 3;
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
if (splineType == 0) // Linear
{
// Draw linear spline
for (int i = 0; i < pointCount - 1; i++)
{
DrawLineEx(points[i], points[i + 1], 2.0f, RED);
}
}
else if (splineType == 1) // B-Spline
{
// Draw b-spline
DrawLineBSpline(points, pointCount, 2.0f, RED);
//for (int i = 0; i < (pointCount - 3); i++) DrawLineBSplineSegment(points[i], points[i + 1], points[i + 2], points[i + 3], 24.0f, BLUE);
}
else if (splineType == 2) // CatmullRom Spline
{
// Draw spline: catmull-rom
DrawLineCatmullRom(points, pointCount, 2.0f, RED);
//for (int i = 0; i < (pointCount - 3); i++) DrawLineCatmullRomSegment(points[i], points[i + 1], points[i + 2], points[i + 3], 24.0f, Fade(BLUE, 0.4f));
}
else if (splineType == 3) // Cubic Bezier
{
// Draw line bezier cubic (with control points)
for (int i = 0; i < pointCount - 1; i++)
{
DrawLineBezierCubic(points[i], points[i + 1], control[i].start, control[i + 1].end, 2.0f, RED);
// TODO: Every cubic bezier point should have two control points
DrawCircleV(control[i].start, 4, GOLD);
DrawCircleV(control[i].end, 4, GOLD);
DrawLineEx(points[i], control[i].start, 1.0, LIGHTGRAY);
DrawLineEx(points[i + 1], control[i].end, 1.0, LIGHTGRAY);
}
}
// Draw control points
for (int i = 0; i < pointCount; i++)
{
DrawCircleV(points[i], 6.0f, RED);
if ((splineType != 0) && (i < pointCount - 1)) DrawLineV(points[i], points[i + 1], GRAY);
}
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -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);

View File

@ -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

View File

@ -15,7 +15,7 @@
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330 #define GLSL_VERSION 330
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB #else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100 #define GLSL_VERSION 100
#endif #endif

View File

@ -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

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@ -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();
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 37 KiB

View File

@ -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();
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 35 KiB

View 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;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -2,7 +2,7 @@
* *
* raylib [core] example - Basic window (adapted for HTML5 platform) * raylib [core] example - Basic window (adapted for HTML5 platform)
* *
* This example is prepared to compile for PLATFORM_WEB, PLATFORM_DESKTOP and PLATFORM_RPI * This example is prepared to compile for PLATFORM_WEB and PLATFORM_DESKTOP
* As you will notice, code structure is slightly different to the other examples... * As you will notice, code structure is slightly different to the other examples...
* To compile it for PLATFORM_WEB just uncomment #define PLATFORM_WEB at beginning * To compile it for PLATFORM_WEB just uncomment #define PLATFORM_WEB at beginning
* *

View File

@ -0,0 +1,387 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug.DLL|Win32">
<Configuration>Debug.DLL</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug.DLL|x64">
<Configuration>Debug.DLL</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release.DLL|Win32">
<Configuration>Release.DLL</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release.DLL|x64">
<Configuration>Release.DLL</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{CC62F7DB-D089-4677-8575-CAB7A7815C43}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>core_2d_camera_split_screen</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>core_2d_camera_split_screen</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'">
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\core</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|x64'">
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\core</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\core</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\core</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'">
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\core</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\core</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\core</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|x64'">
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\core</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<CompileAs>CompileAsC</CompileAs>
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<CompileAs>CompileAsC</CompileAs>
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<CompileAs>CompileAsC</CompileAs>
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"</Command>
<Message>Copy Debug DLL to output directory</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<CompileAs>CompileAsC</CompileAs>
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"</Command>
<Message>Copy Debug DLL to output directory</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<CompileAs>CompileAsC</CompileAs>
<RemoveUnreferencedCodeData>true</RemoveUnreferencedCodeData>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<CompileAs>CompileAsC</CompileAs>
<RemoveUnreferencedCodeData>true</RemoveUnreferencedCodeData>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<CompileAs>CompileAsC</CompileAs>
<RemoveUnreferencedCodeData>true</RemoveUnreferencedCodeData>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
</Link>
<PostBuildEvent>
<Command>xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"</Command>
</PostBuildEvent>
<PostBuildEvent>
<Message>Copy Release DLL to output directory</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<CompileAs>CompileAsC</CompileAs>
<RemoveUnreferencedCodeData>true</RemoveUnreferencedCodeData>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
</Link>
<PostBuildEvent>
<Command>xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"</Command>
</PostBuildEvent>
<PostBuildEvent>
<Message>Copy Release DLL to output directory</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\..\examples\core\core_2d_camera_split_screen.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\raylib\raylib.vcxproj">
<Project>{e89d61ac-55de-4482-afd4-df7242ebc859}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -37,9 +37,9 @@
<PropertyGroup Label="Globals"> <PropertyGroup Label="Globals">
<ProjectGuid>{946A1700-C7AA-46F0-AEF2-67C98B5722AC}</ProjectGuid> <ProjectGuid>{946A1700-C7AA-46F0-AEF2-67C98B5722AC}</ProjectGuid>
<Keyword>Win32Proj</Keyword> <Keyword>Win32Proj</Keyword>
<RootNamespace>core_split_screen</RootNamespace> <RootNamespace>core_3d_camera_split_screen</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>core_split_screen</ProjectName> <ProjectName>core_3d_camera_split_screen</ProjectName>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@ -374,7 +374,7 @@
</PostBuildEvent> </PostBuildEvent>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\..\..\examples\core\core_split_screen.c" /> <ClCompile Include="..\..\..\examples\core\core_3d_camera_split_screen.c" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\raylib\raylib.vcxproj"> <ProjectReference Include="..\raylib\raylib.vcxproj">

View File

@ -33,6 +33,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_3d_camera_free", "exam
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_3d_camera_mode", "examples\core_3d_camera_mode.vcxproj", "{6D1CA2F1-7FCA-4249-9220-075C2DF4F965}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_3d_camera_mode", "examples\core_3d_camera_mode.vcxproj", "{6D1CA2F1-7FCA-4249-9220-075C2DF4F965}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_3d_camera_split_screen", "examples\core_3d_camera_split_screen.vcxproj", "{946A1700-C7AA-46F0-AEF2-67C98B5722AC}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_3d_picking", "examples\core_3d_picking.vcxproj", "{FD193822-3D5C-4161-A147-884C2ABDE483}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_3d_picking", "examples\core_3d_picking.vcxproj", "{FD193822-3D5C-4161-A147-884C2ABDE483}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_custom_logging", "examples\core_custom_logging.vcxproj", "{20AD0AC9-9159-4744-99CC-6AC5779D6B87}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_custom_logging", "examples\core_custom_logging.vcxproj", "{20AD0AC9-9159-4744-99CC-6AC5779D6B87}"
@ -233,8 +235,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "easings_testbed", "examples
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rlgl_standalone", "examples\rlgl_standalone.vcxproj", "{C8765523-58F8-4C8E-9914-693396F6F0FF}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rlgl_standalone", "examples\rlgl_standalone.vcxproj", "{C8765523-58F8-4C8E-9914-693396F6F0FF}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_split_screen", "examples\core_split_screen.vcxproj", "{946A1700-C7AA-46F0-AEF2-67C98B5722AC}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models_loading_vox", "examples\models_loading_vox.vcxproj", "{2F1B955B-275E-4D8E-8864-06FEC44D7912}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models_loading_vox", "examples\models_loading_vox.vcxproj", "{2F1B955B-275E-4D8E-8864-06FEC44D7912}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models_loading_gltf", "examples\models_loading_gltf.vcxproj", "{F5FC9279-DE63-4EF3-B31F-CFCEF9B11F71}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models_loading_gltf", "examples\models_loading_gltf.vcxproj", "{F5FC9279-DE63-4EF3-B31F-CFCEF9B11F71}"
@ -271,6 +271,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shaders_hybrid_render", "ex
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "audio_sound_multi", "examples\audio_sound_multi.vcxproj", "{F81C5819-85B4-4D2E-B6DC-104A7634461B}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "audio_sound_multi", "examples\audio_sound_multi.vcxproj", "{F81C5819-85B4-4D2E-B6DC-104A7634461B}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_2d_camera_split_screen", "examples\core_2d_camera_split_screen.vcxproj", "{CC62F7DB-D089-4677-8575-CAB7A7815C43}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug.DLL|x64 = Debug.DLL|x64 Debug.DLL|x64 = Debug.DLL|x64
@ -507,6 +509,22 @@ Global
{6D1CA2F1-7FCA-4249-9220-075C2DF4F965}.Release|x64.Build.0 = Release|x64 {6D1CA2F1-7FCA-4249-9220-075C2DF4F965}.Release|x64.Build.0 = Release|x64
{6D1CA2F1-7FCA-4249-9220-075C2DF4F965}.Release|x86.ActiveCfg = Release|Win32 {6D1CA2F1-7FCA-4249-9220-075C2DF4F965}.Release|x86.ActiveCfg = Release|Win32
{6D1CA2F1-7FCA-4249-9220-075C2DF4F965}.Release|x86.Build.0 = Release|Win32 {6D1CA2F1-7FCA-4249-9220-075C2DF4F965}.Release|x86.Build.0 = Release|Win32
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Debug.DLL|x64.Build.0 = Debug.DLL|x64
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Debug|x64.ActiveCfg = Debug|x64
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Debug|x64.Build.0 = Debug|x64
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Debug|x86.ActiveCfg = Debug|Win32
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Debug|x86.Build.0 = Debug|Win32
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Release.DLL|x64.ActiveCfg = Release.DLL|x64
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Release.DLL|x64.Build.0 = Release.DLL|x64
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Release.DLL|x86.Build.0 = Release.DLL|Win32
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Release|x64.ActiveCfg = Release|x64
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Release|x64.Build.0 = Release|x64
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Release|x86.ActiveCfg = Release|Win32
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Release|x86.Build.0 = Release|Win32
{FD193822-3D5C-4161-A147-884C2ABDE483}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 {FD193822-3D5C-4161-A147-884C2ABDE483}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64
{FD193822-3D5C-4161-A147-884C2ABDE483}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 {FD193822-3D5C-4161-A147-884C2ABDE483}.Debug.DLL|x64.Build.0 = Debug.DLL|x64
{FD193822-3D5C-4161-A147-884C2ABDE483}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 {FD193822-3D5C-4161-A147-884C2ABDE483}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
@ -1975,22 +1993,6 @@ Global
{C8765523-58F8-4C8E-9914-693396F6F0FF}.Release|x64.Build.0 = Release|x64 {C8765523-58F8-4C8E-9914-693396F6F0FF}.Release|x64.Build.0 = Release|x64
{C8765523-58F8-4C8E-9914-693396F6F0FF}.Release|x86.ActiveCfg = Release|Win32 {C8765523-58F8-4C8E-9914-693396F6F0FF}.Release|x86.ActiveCfg = Release|Win32
{C8765523-58F8-4C8E-9914-693396F6F0FF}.Release|x86.Build.0 = Release|Win32 {C8765523-58F8-4C8E-9914-693396F6F0FF}.Release|x86.Build.0 = Release|Win32
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Debug.DLL|x64.Build.0 = Debug.DLL|x64
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Debug|x64.ActiveCfg = Debug|x64
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Debug|x64.Build.0 = Debug|x64
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Debug|x86.ActiveCfg = Debug|Win32
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Debug|x86.Build.0 = Debug|Win32
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Release.DLL|x64.ActiveCfg = Release.DLL|x64
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Release.DLL|x64.Build.0 = Release.DLL|x64
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Release.DLL|x86.Build.0 = Release.DLL|Win32
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Release|x64.ActiveCfg = Release|x64
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Release|x64.Build.0 = Release|x64
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Release|x86.ActiveCfg = Release|Win32
{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Release|x86.Build.0 = Release|Win32
{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 {2F1B955B-275E-4D8E-8864-06FEC44D7912}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64
{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 {2F1B955B-275E-4D8E-8864-06FEC44D7912}.Debug.DLL|x64.Build.0 = Debug.DLL|x64
{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 {2F1B955B-275E-4D8E-8864-06FEC44D7912}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
@ -2279,6 +2281,22 @@ Global
{F81C5819-85B4-4D2E-B6DC-104A7634461B}.Release|x64.Build.0 = Release|x64 {F81C5819-85B4-4D2E-B6DC-104A7634461B}.Release|x64.Build.0 = Release|x64
{F81C5819-85B4-4D2E-B6DC-104A7634461B}.Release|x86.ActiveCfg = Release|Win32 {F81C5819-85B4-4D2E-B6DC-104A7634461B}.Release|x86.ActiveCfg = Release|Win32
{F81C5819-85B4-4D2E-B6DC-104A7634461B}.Release|x86.Build.0 = Release|Win32 {F81C5819-85B4-4D2E-B6DC-104A7634461B}.Release|x86.Build.0 = Release|Win32
{CC62F7DB-D089-4677-8575-CAB7A7815C43}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64
{CC62F7DB-D089-4677-8575-CAB7A7815C43}.Debug.DLL|x64.Build.0 = Debug.DLL|x64
{CC62F7DB-D089-4677-8575-CAB7A7815C43}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
{CC62F7DB-D089-4677-8575-CAB7A7815C43}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32
{CC62F7DB-D089-4677-8575-CAB7A7815C43}.Debug|x64.ActiveCfg = Debug|x64
{CC62F7DB-D089-4677-8575-CAB7A7815C43}.Debug|x64.Build.0 = Debug|x64
{CC62F7DB-D089-4677-8575-CAB7A7815C43}.Debug|x86.ActiveCfg = Debug|Win32
{CC62F7DB-D089-4677-8575-CAB7A7815C43}.Debug|x86.Build.0 = Debug|Win32
{CC62F7DB-D089-4677-8575-CAB7A7815C43}.Release.DLL|x64.ActiveCfg = Release.DLL|x64
{CC62F7DB-D089-4677-8575-CAB7A7815C43}.Release.DLL|x64.Build.0 = Release.DLL|x64
{CC62F7DB-D089-4677-8575-CAB7A7815C43}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32
{CC62F7DB-D089-4677-8575-CAB7A7815C43}.Release.DLL|x86.Build.0 = Release.DLL|Win32
{CC62F7DB-D089-4677-8575-CAB7A7815C43}.Release|x64.ActiveCfg = Release|x64
{CC62F7DB-D089-4677-8575-CAB7A7815C43}.Release|x64.Build.0 = Release|x64
{CC62F7DB-D089-4677-8575-CAB7A7815C43}.Release|x86.ActiveCfg = Release|Win32
{CC62F7DB-D089-4677-8575-CAB7A7815C43}.Release|x86.Build.0 = Release|Win32
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -2297,6 +2315,7 @@ Global
{557138B0-7BE2-4392-B2E2-B45734031A62} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} {557138B0-7BE2-4392-B2E2-B45734031A62} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
{9EED87BB-527F-4D05-9384-6D16CFD627A8} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} {9EED87BB-527F-4D05-9384-6D16CFD627A8} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
{6D1CA2F1-7FCA-4249-9220-075C2DF4F965} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} {6D1CA2F1-7FCA-4249-9220-075C2DF4F965} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
{946A1700-C7AA-46F0-AEF2-67C98B5722AC} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
{FD193822-3D5C-4161-A147-884C2ABDE483} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} {FD193822-3D5C-4161-A147-884C2ABDE483} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
{20AD0AC9-9159-4744-99CC-6AC5779D6B87} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} {20AD0AC9-9159-4744-99CC-6AC5779D6B87} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
{0199E349-0701-40BC-8A7F-06A54FFA3E7C} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} {0199E349-0701-40BC-8A7F-06A54FFA3E7C} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
@ -2397,7 +2416,6 @@ Global
{FDE6080B-E203-4066-910D-AD0302566008} = {E9D708A5-9C1F-4B84-A795-C5F191801762} {FDE6080B-E203-4066-910D-AD0302566008} = {E9D708A5-9C1F-4B84-A795-C5F191801762}
{E1B6D565-9D7C-46B7-9202-ECF54974DE50} = {E9D708A5-9C1F-4B84-A795-C5F191801762} {E1B6D565-9D7C-46B7-9202-ECF54974DE50} = {E9D708A5-9C1F-4B84-A795-C5F191801762}
{C8765523-58F8-4C8E-9914-693396F6F0FF} = {E9D708A5-9C1F-4B84-A795-C5F191801762} {C8765523-58F8-4C8E-9914-693396F6F0FF} = {E9D708A5-9C1F-4B84-A795-C5F191801762}
{946A1700-C7AA-46F0-AEF2-67C98B5722AC} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
{2F1B955B-275E-4D8E-8864-06FEC44D7912} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C} {2F1B955B-275E-4D8E-8864-06FEC44D7912} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C}
{F5FC9279-DE63-4EF3-B31F-CFCEF9B11F71} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C} {F5FC9279-DE63-4EF3-B31F-CFCEF9B11F71} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C}
{F2DB2E59-76BF-4D81-859A-AFC289C046C0} = {8D3C83B7-F1E0-4C2E-9E34-EE5F6AB2502A} {F2DB2E59-76BF-4D81-859A-AFC289C046C0} = {8D3C83B7-F1E0-4C2E-9E34-EE5F6AB2502A}
@ -2416,6 +2434,7 @@ Global
{70B35F59-AFC2-4D8F-8833-5314D2047A81} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} {70B35F59-AFC2-4D8F-8833-5314D2047A81} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9}
{3755E9F4-CB48-4EC3-B561-3B85964EBDEF} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} {3755E9F4-CB48-4EC3-B561-3B85964EBDEF} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9}
{F81C5819-85B4-4D2E-B6DC-104A7634461B} = {CC132A4D-D081-4C26-BFB9-AB11984054F8} {F81C5819-85B4-4D2E-B6DC-104A7634461B} = {CC132A4D-D081-4C26-BFB9-AB11984054F8}
{CC62F7DB-D089-4677-8575-CAB7A7815C43} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29} SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29}

View File

@ -32,7 +32,7 @@ RAYLIB_PATH ?= ..\..
COMPILER_PATH ?= C:/raylib/w64devkit/bin COMPILER_PATH ?= C:/raylib/w64devkit/bin
# Define default options # Define default options
# One of PLATFORM_DESKTOP, PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB # One of PLATFORM_DESKTOP, PLATFORM_ANDROID, PLATFORM_WEB
PLATFORM ?= PLATFORM_DESKTOP PLATFORM ?= PLATFORM_DESKTOP
# Locations of your newly installed library and associated headers. See ../src/Makefile # Locations of your newly installed library and associated headers. See ../src/Makefile

View File

@ -8,7 +8,6 @@
# PLATFORM_DESKTOP: OSX/macOS (arm64, x86_64) # PLATFORM_DESKTOP: OSX/macOS (arm64, x86_64)
# PLATFORM_DESKTOP: FreeBSD, OpenBSD, NetBSD, DragonFly # PLATFORM_DESKTOP: FreeBSD, OpenBSD, NetBSD, DragonFly
# PLATFORM_ANDROID: Android (arm, i686, arm64, x86_64) # PLATFORM_ANDROID: Android (arm, i686, arm64, x86_64)
# PLATFORM_RPI: Raspberry Pi (deprecated - RPI OS Buster only)
# PLATFORM_DRM: Linux native mode, including Raspberry Pi (RPI OS Bullseye) # PLATFORM_DRM: Linux native mode, including Raspberry Pi (RPI OS Bullseye)
# PLATFORM_WEB: HTML5 (Chrome, Firefox) # PLATFORM_WEB: HTML5 (Chrome, Firefox)
# #
@ -41,7 +40,7 @@
# Define required environment variables # Define required environment variables
#------------------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------------------
# Define target platform: PLATFORM_DESKTOP, PLATFORM_RPI, PLATFORM_DRM, PLATFORM_ANDROID, PLATFORM_WEB # Define target platform: PLATFORM_DESKTOP, PLATFORM_DRM, PLATFORM_ANDROID, PLATFORM_WEB
PLATFORM ?= PLATFORM_DESKTOP PLATFORM ?= PLATFORM_DESKTOP
# Define required raylib variables # Define required raylib variables
@ -94,14 +93,6 @@ USE_EXTERNAL_GLFW ?= FALSE
# NOTE: This variable is only used for PLATFORM_OS: LINUX # NOTE: This variable is only used for PLATFORM_OS: LINUX
USE_WAYLAND_DISPLAY ?= FALSE USE_WAYLAND_DISPLAY ?= FALSE
# Use cross-compiler for PLATFORM_RPI
USE_RPI_CROSS_COMPILER ?= FALSE
ifeq ($(USE_RPI_CROSS_COMPILER),TRUE)
RPI_TOOLCHAIN ?= C:/SysGCC/Raspberry
RPI_TOOLCHAIN_NAME ?= arm-linux-gnueabihf
RPI_TOOLCHAIN_SYSROOT ?= $(RPI_TOOLCHAIN)/$(RPI_TOOLCHAIN_NAME)/sysroot
endif
# Determine if the file has root access (only required to install raylib) # Determine if the file has root access (only required to install raylib)
# "whoami" prints the name of the user that calls him (so, if it is the root user, "whoami" prints "root") # "whoami" prints the name of the user that calls him (so, if it is the root user, "whoami" prints "root")
ROOT = $(shell whoami) ROOT = $(shell whoami)
@ -144,15 +135,6 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
endif endif
endif endif
endif endif
ifeq ($(PLATFORM),PLATFORM_RPI)
UNAMEOS = $(shell uname)
ifeq ($(UNAMEOS),Linux)
PLATFORM_OS = LINUX
endif
ifndef PLATFORM_SHELL
PLATFORM_SHELL = sh
endif
endif
ifeq ($(PLATFORM),PLATFORM_DRM) ifeq ($(PLATFORM),PLATFORM_DRM)
UNAMEOS = $(shell uname) UNAMEOS = $(shell uname)
ifeq ($(UNAMEOS),Linux) ifeq ($(UNAMEOS),Linux)
@ -235,10 +217,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
#GRAPHICS = GRAPHICS_API_OPENGL_43 # Uncomment to use OpenGL 4.3 #GRAPHICS = GRAPHICS_API_OPENGL_43 # Uncomment to use OpenGL 4.3
#GRAPHICS = GRAPHICS_API_OPENGL_ES2 # Uncomment to use OpenGL ES 2.0 (ANGLE) #GRAPHICS = GRAPHICS_API_OPENGL_ES2 # Uncomment to use OpenGL ES 2.0 (ANGLE)
endif endif
ifeq ($(PLATFORM),PLATFORM_RPI)
# On RPI OpenGL ES 2.0 must be used
GRAPHICS = GRAPHICS_API_OPENGL_ES2
endif
ifeq ($(PLATFORM),PLATFORM_DRM) ifeq ($(PLATFORM),PLATFORM_DRM)
# On DRM OpenGL ES 2.0 must be used # On DRM OpenGL ES 2.0 must be used
GRAPHICS = GRAPHICS_API_OPENGL_ES2 GRAPHICS = GRAPHICS_API_OPENGL_ES2
@ -269,14 +248,6 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
CC = clang CC = clang
endif endif
endif endif
ifeq ($(PLATFORM),PLATFORM_RPI)
ifeq ($(USE_RPI_CROSS_COMPILER),TRUE)
# Define RPI cross-compiler
#CC = armv6j-hardfloat-linux-gnueabi-gcc
CC = $(RPI_TOOLCHAIN)/bin/$(RPI_TOOLCHAIN_NAME)-gcc
AR = $(RPI_TOOLCHAIN)/bin/$(RPI_TOOLCHAIN_NAME)-ar
endif
endif
ifeq ($(PLATFORM),PLATFORM_DRM) ifeq ($(PLATFORM),PLATFORM_DRM)
ifeq ($(USE_RPI_CROSS_COMPILER),TRUE) ifeq ($(USE_RPI_CROSS_COMPILER),TRUE)
# Define RPI cross-compiler # Define RPI cross-compiler
@ -452,11 +423,6 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
INCLUDE_PATHS += -I/usr/local/include INCLUDE_PATHS += -I/usr/local/include
endif endif
endif endif
ifeq ($(PLATFORM),PLATFORM_RPI)
INCLUDE_PATHS += -I$(RPI_TOOLCHAIN_SYSROOT)/opt/vc/include
INCLUDE_PATHS += -I$(RPI_TOOLCHAIN_SYSROOT)/opt/vc/include/interface/vmcs_host/linux
INCLUDE_PATHS += -I$(RPI_TOOLCHAIN_SYSROOT)/opt/vc/include/interface/vcos/pthreads
endif
ifeq ($(PLATFORM),PLATFORM_DRM) ifeq ($(PLATFORM),PLATFORM_DRM)
INCLUDE_PATHS += -I/usr/include/libdrm INCLUDE_PATHS += -I/usr/include/libdrm
ifeq ($(USE_RPI_CROSSCOMPILER), TRUE) ifeq ($(USE_RPI_CROSSCOMPILER), TRUE)
@ -506,9 +472,6 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
LDFLAGS += -Wl,-soname,lib$(RAYLIB_LIB_NAME).$(RAYLIB_API_VERSION).so -Lsrc -L/usr/local/lib LDFLAGS += -Wl,-soname,lib$(RAYLIB_LIB_NAME).$(RAYLIB_API_VERSION).so -Lsrc -L/usr/local/lib
endif endif
endif endif
ifeq ($(PLATFORM),PLATFORM_RPI)
LDFLAGS += -Wl,-soname,lib$(RAYLIB_LIB_NAME).so.$(RAYLIB_API_VERSION) -L$(RPI_TOOLCHAIN_SYSROOT)/opt/vc/lib
endif
ifeq ($(PLATFORM),PLATFORM_DRM) ifeq ($(PLATFORM),PLATFORM_DRM)
LDFLAGS += -Wl,-soname,lib$(RAYLIB_LIB_NAME).so.$(RAYLIB_API_VERSION) LDFLAGS += -Wl,-soname,lib$(RAYLIB_LIB_NAME).so.$(RAYLIB_API_VERSION)
ifeq ($(USE_RPI_CROSSCOMPILER), TRUE) ifeq ($(USE_RPI_CROSSCOMPILER), TRUE)
@ -557,12 +520,6 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
LDLIBS = -lglfw LDLIBS = -lglfw
endif endif
endif endif
ifeq ($(PLATFORM),PLATFORM_RPI)
LDLIBS = -lbrcmGLESv2 -lbrcmEGL -lpthread -lrt -lm -lbcm_host -ldl
ifeq ($(RAYLIB_MODULE_AUDIO),TRUE)
LDLIBS += -latomic
endif
endif
ifeq ($(PLATFORM),PLATFORM_DRM) ifeq ($(PLATFORM),PLATFORM_DRM)
LDLIBS = -lGLESv2 -lEGL -ldrm -lgbm -lpthread -lrt -lm -ldl LDLIBS = -lGLESv2 -lEGL -ldrm -lgbm -lpthread -lrt -lm -ldl
ifeq ($(RAYLIB_MODULE_AUDIO),TRUE) ifeq ($(RAYLIB_MODULE_AUDIO),TRUE)
@ -647,14 +604,6 @@ else
cd $(RAYLIB_RELEASE_PATH) && ln -fs lib$(RAYLIB_LIB_NAME).$(RAYLIB_VERSION).so lib$(RAYLIB_LIB_NAME).so cd $(RAYLIB_RELEASE_PATH) && ln -fs lib$(RAYLIB_LIB_NAME).$(RAYLIB_VERSION).so lib$(RAYLIB_LIB_NAME).so
endif endif
endif endif
ifeq ($(PLATFORM),PLATFORM_RPI)
# Compile raylib shared library version $(RAYLIB_VERSION).
# WARNING: you should type "make clean" before doing this target
$(CC) -shared -o $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).so.$(RAYLIB_VERSION) $(OBJS) $(LDFLAGS) $(LDLIBS)
@echo "raylib shared library generated (lib$(RAYLIB_LIB_NAME).so.$(RAYLIB_VERSION)) in $(RAYLIB_RELEASE_PATH)!"
cd $(RAYLIB_RELEASE_PATH) && ln -fsv lib$(RAYLIB_LIB_NAME).so.$(RAYLIB_VERSION) lib$(RAYLIB_LIB_NAME).so.$(RAYLIB_API_VERSION)
cd $(RAYLIB_RELEASE_PATH) && ln -fsv lib$(RAYLIB_LIB_NAME).so.$(RAYLIB_API_VERSION) lib$(RAYLIB_LIB_NAME).so
endif
ifeq ($(PLATFORM),PLATFORM_DRM) ifeq ($(PLATFORM),PLATFORM_DRM)
# Compile raylib shared library version $(RAYLIB_VERSION). # Compile raylib shared library version $(RAYLIB_VERSION).
# WARNING: you should type "make clean" before doing this target # WARNING: you should type "make clean" before doing this target
@ -827,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
@ -839,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

View File

@ -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");
} }

View File

@ -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

File diff suppressed because it is too large Load Diff

1458
src/external/nanosvgrast.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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());

View File

@ -8,7 +8,6 @@
* - PLATFORM_DESKTOP: FreeBSD, OpenBSD, NetBSD, DragonFly (X11 desktop) * - PLATFORM_DESKTOP: FreeBSD, OpenBSD, NetBSD, DragonFly (X11 desktop)
* - PLATFORM_DESKTOP: OSX/macOS * - PLATFORM_DESKTOP: OSX/macOS
* - PLATFORM_ANDROID: Android (ARM, ARM64) * - PLATFORM_ANDROID: Android (ARM, ARM64)
* - PLATFORM_RPI: Raspberry Pi 0,1,2,3 (Raspbian, native mode)
* - PLATFORM_DRM: Linux native mode, including Raspberry Pi 4 with V3D fkms driver * - PLATFORM_DRM: Linux native mode, including Raspberry Pi 4 with V3D fkms driver
* - PLATFORM_WEB: HTML5 with WebAssembly * - PLATFORM_WEB: HTML5 with WebAssembly
* *
@ -21,12 +20,6 @@
* Windowing and input system configured for Android device, app activity managed internally in this module. * Windowing and input system configured for Android device, app activity managed internally in this module.
* NOTE: OpenGL ES 2.0 is required and graphic device is managed by EGL * NOTE: OpenGL ES 2.0 is required and graphic device is managed by EGL
* *
* #define PLATFORM_RPI (deprecated - RPI OS Buster only)
* Windowing and input system configured for Raspberry Pi in native mode (no XWindow required),
* graphic device is managed by EGL and inputs are processed is raw mode, reading from /dev/input/
* WARNING: This platform is deprecated, since RPI OS Bullseye, the old Dispmanx libraries are not
* supported and you must be using PLATFORM_DRM
*
* #define PLATFORM_DRM * #define PLATFORM_DRM
* Windowing and input system configured for DRM native mode (RPI4 and other devices) * Windowing and input system configured for DRM native mode (RPI4 and other devices)
* graphic device is managed by EGL and inputs are processed is raw mode, reading from /dev/input/ * graphic device is managed by EGL and inputs are processed is raw mode, reading from /dev/input/
@ -49,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
@ -263,7 +253,7 @@
//#include <GLES2/gl2.h> // OpenGL ES 2.0 library (not required in this module, only in rlgl) //#include <GLES2/gl2.h> // OpenGL ES 2.0 library (not required in this module, only in rlgl)
#endif #endif
#if defined(PLATFORM_RPI) || defined(PLATFORM_DRM) #if defined(PLATFORM_DRM)
#include <fcntl.h> // POSIX file control definitions - open(), creat(), fcntl() #include <fcntl.h> // POSIX file control definitions - open(), creat(), fcntl()
#include <unistd.h> // POSIX standard function definitions - read(), close(), STDIN_FILENO #include <unistd.h> // POSIX standard function definitions - read(), close(), STDIN_FILENO
#include <termios.h> // POSIX terminal control definitions - tcgetattr(), tcsetattr() #include <termios.h> // POSIX terminal control definitions - tcgetattr(), tcsetattr()
@ -275,9 +265,6 @@
#include <linux/input.h> // Linux: Keycodes constants definition (KEY_A, ...) #include <linux/input.h> // Linux: Keycodes constants definition (KEY_A, ...)
#include <linux/joystick.h> // Linux: Joystick support library #include <linux/joystick.h> // Linux: Joystick support library
#if defined(PLATFORM_RPI)
#include "bcm_host.h" // Raspberry Pi VideoCore IV access functions
#endif
#if defined(PLATFORM_DRM) #if defined(PLATFORM_DRM)
#include <gbm.h> // Generic Buffer Management (native platform for EGL on DRM) #include <gbm.h> // Generic Buffer Management (native platform for EGL on DRM)
#include <xf86drm.h> // Direct Rendering Manager user-level library interface #include <xf86drm.h> // Direct Rendering Manager user-level library interface
@ -302,7 +289,7 @@
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Defines and Macros // Defines and Macros
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#if defined(PLATFORM_RPI) || defined(PLATFORM_DRM) #if defined(PLATFORM_DRM)
#define USE_LAST_TOUCH_DEVICE // When multiple touchscreens are connected, only use the one with the highest event<N> number #define USE_LAST_TOUCH_DEVICE // When multiple touchscreens are connected, only use the one with the highest event<N> number
#define DEFAULT_GAMEPAD_DEV "/dev/input/js" // Gamepad input (base dev for all gamepads: js0, js1, ...) #define DEFAULT_GAMEPAD_DEV "/dev/input/js" // Gamepad input (base dev for all gamepads: js0, js1, ...)
@ -354,7 +341,7 @@
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Types and Structures Definition // Types and Structures Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#if defined(PLATFORM_RPI) || defined(PLATFORM_DRM) #if defined(PLATFORM_DRM)
typedef struct { typedef struct {
pthread_t threadId; // Event reading thread id pthread_t threadId; // Event reading thread id
int fd; // File descriptor to the device it is assigned to int fd; // File descriptor to the device it is assigned to
@ -378,10 +365,7 @@ typedef struct CoreData {
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
GLFWwindow *handle; // GLFW window handle (graphic device) GLFWwindow *handle; // GLFW window handle (graphic device)
#endif #endif
#if defined(PLATFORM_RPI) #if defined(PLATFORM_ANDROID) || defined(PLATFORM_DRM)
EGL_DISPMANX_WINDOW_T handle; // Native window handle (graphic device)
#endif
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_DRM)
#if defined(PLATFORM_DRM) #if defined(PLATFORM_DRM)
int fd; // File descriptor for /dev/dri/... int fd; // File descriptor for /dev/dri/...
drmModeConnector *connector; // Direct Rendering Manager (DRM) mode connector drmModeConnector *connector; // Direct Rendering Manager (DRM) mode connector
@ -405,15 +389,15 @@ typedef struct CoreData {
bool resizedLastFrame; // Check if window has been resized last frame bool resizedLastFrame; // Check if window has been resized last frame
bool eventWaiting; // Wait for events before ending frame bool eventWaiting; // Wait for events before ending frame
Point position; // Window position on screen (required on fullscreen toggle) Point position; // Window position (required on fullscreen toggle)
Point previousPosition; // Window previous position (required on borderless windowed toggle)
Size display; // Display width and height (monitor, device-screen, LCD, ...) Size display; // Display width and height (monitor, device-screen, LCD, ...)
Size screen; // Screen width and height (used render area) Size screen; // Screen width and height (used render area)
Size previousScreen; // Screen previous width and height (required on borderless windowed toggle)
Size currentFbo; // Current render width and height (depends on active fbo) Size currentFbo; // Current render width and height (depends on active fbo)
Size render; // Framebuffer width and height (render area, including black bars if required) Size render; // Framebuffer width and height (render area, including black bars if required)
Point renderOffset; // Offset from render area (must be divided by 2) Point renderOffset; // Offset from render area (must be divided by 2)
Matrix screenScale; // Matrix to scale screen (framebuffer rendering) Matrix screenScale; // Matrix to scale screen (framebuffer rendering)
Point previousPosition; // Previous screen position (required on borderless windowed toggle)
Size previousScreen; // Previous screen size (required on borderless windowed toggle)
char **dropFilepaths; // Store dropped files paths pointers (provided by GLFW) char **dropFilepaths; // Store dropped files paths pointers (provided by GLFW)
unsigned int dropFileCount; // Count dropped files strings unsigned int dropFileCount; // Count dropped files strings
@ -431,13 +415,15 @@ typedef struct CoreData {
const char *basePath; // Base path for data storage const char *basePath; // Base path for data storage
} Storage; } Storage;
struct { struct {
#if defined(PLATFORM_RPI) || defined(PLATFORM_DRM) #if defined(PLATFORM_DRM)
InputEventWorker eventWorker[10]; // List of worker threads for every monitored "/dev/input/event<N>" InputEventWorker eventWorker[10]; // List of worker threads for every monitored "/dev/input/event<N>"
#endif #endif
struct { struct {
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
@ -445,7 +431,7 @@ typedef struct CoreData {
int charPressedQueue[MAX_CHAR_PRESSED_QUEUE]; // Input characters queue (unicode) int charPressedQueue[MAX_CHAR_PRESSED_QUEUE]; // Input characters queue (unicode)
int charPressedQueueCount; // Input characters queue count int charPressedQueueCount; // Input characters queue count
#if defined(PLATFORM_RPI) || defined(PLATFORM_DRM) #if defined(PLATFORM_DRM)
int defaultMode; // Default keyboard mode int defaultMode; // Default keyboard mode
#if defined(SUPPORT_SSH_KEYBOARD_RPI) #if defined(SUPPORT_SSH_KEYBOARD_RPI)
bool evtMode; // Keyboard in event mode bool evtMode; // Keyboard in event mode
@ -469,7 +455,7 @@ typedef struct CoreData {
char previousButtonState[MAX_MOUSE_BUTTONS]; // Registers previous mouse button state char previousButtonState[MAX_MOUSE_BUTTONS]; // Registers previous mouse button state
Vector2 currentWheelMove; // Registers current mouse wheel variation Vector2 currentWheelMove; // Registers current mouse wheel variation
Vector2 previousWheelMove; // Registers previous mouse wheel variation Vector2 previousWheelMove; // Registers previous mouse wheel variation
#if defined(PLATFORM_RPI) || defined(PLATFORM_DRM) #if defined(PLATFORM_DRM)
Vector2 eventWheelMove; // Registers the event mouse wheel variation Vector2 eventWheelMove; // Registers the event mouse wheel variation
// NOTE: currentButtonState[] can't be written directly due to multithreading, app could miss the update // NOTE: currentButtonState[] can't be written directly due to multithreading, app could miss the update
char currentButtonStateEvdev[MAX_MOUSE_BUTTONS]; // Holds the new mouse state for the next polling event to grab char currentButtonStateEvdev[MAX_MOUSE_BUTTONS]; // Holds the new mouse state for the next polling event to grab
@ -490,7 +476,7 @@ typedef struct CoreData {
char currentButtonState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Current gamepad buttons state char currentButtonState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Current gamepad buttons state
char previousButtonState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Previous gamepad buttons state char previousButtonState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Previous gamepad buttons state
float axisState[MAX_GAMEPADS][MAX_GAMEPAD_AXIS]; // Gamepad axis state float axisState[MAX_GAMEPADS][MAX_GAMEPAD_AXIS]; // Gamepad axis state
#if defined(PLATFORM_RPI) || defined(PLATFORM_DRM) #if defined(PLATFORM_DRM)
pthread_t threadId; // Gamepad reading thread id pthread_t threadId; // Gamepad reading thread id
int streamId[MAX_GAMEPADS]; // Gamepad device file descriptor int streamId[MAX_GAMEPADS]; // Gamepad device file descriptor
#endif #endif
@ -503,8 +489,8 @@ typedef struct CoreData {
double draw; // Time measure for frame draw double draw; // Time measure for frame draw
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_RPI) || 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;
@ -599,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)
@ -668,7 +654,7 @@ static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent
static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData); static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData);
#endif #endif
#if defined(PLATFORM_RPI) || defined(PLATFORM_DRM) #if defined(PLATFORM_DRM)
static void InitKeyboard(void); // Initialize raw keyboard system static void InitKeyboard(void); // Initialize raw keyboard system
static void RestoreKeyboard(void); // Restore keyboard system static void RestoreKeyboard(void); // Restore keyboard system
#if defined(SUPPORT_SSH_KEYBOARD_RPI) #if defined(SUPPORT_SSH_KEYBOARD_RPI)
@ -683,13 +669,11 @@ static void *EventThread(void *arg); // Input device events r
static void InitGamepad(void); // Initialize raw gamepad input static void InitGamepad(void); // Initialize raw gamepad input
static void *GamepadThread(void *arg); // Mouse reading thread static void *GamepadThread(void *arg); // Mouse reading thread
#if defined(PLATFORM_DRM)
static int FindMatchingConnectorMode(const drmModeConnector *connector, const drmModeModeInfo *mode); // Search matching DRM mode in connector's mode list static int FindMatchingConnectorMode(const drmModeConnector *connector, const drmModeModeInfo *mode); // Search matching DRM mode in connector's mode list
static int FindExactConnectorMode(const drmModeConnector *connector, uint width, uint height, uint fps, bool allowInterlaced); // Search exactly matching DRM connector mode in connector's list static int FindExactConnectorMode(const drmModeConnector *connector, uint width, uint height, uint fps, bool allowInterlaced); // Search exactly matching DRM connector mode in connector's list
static int FindNearestConnectorMode(const drmModeConnector *connector, uint width, uint height, uint fps, bool allowInterlaced); // Search the nearest matching DRM connector mode in connector's list static int FindNearestConnectorMode(const drmModeConnector *connector, uint width, uint height, uint fps, bool allowInterlaced); // Search the nearest matching DRM connector mode in connector's list
#endif
#endif // PLATFORM_RPI || PLATFORM_DRM #endif // PLATFORM_DRM
#if defined(SUPPORT_EVENTS_AUTOMATION) #if defined(SUPPORT_EVENTS_AUTOMATION)
static void LoadAutomationEvents(const char *fileName); // Load automation events from file static void LoadAutomationEvents(const char *fileName); // Load automation events from file
@ -858,7 +842,7 @@ void InitWindow(int width, int height, const char *title)
} }
} }
#endif #endif
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) || defined(PLATFORM_RPI) || defined(PLATFORM_DRM) #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) || defined(PLATFORM_DRM)
// Initialize graphics device (display device and OpenGL context) // Initialize graphics device (display device and OpenGL context)
// NOTE: returns true if window and graphic device has been initialized successfully // NOTE: returns true if window and graphic device has been initialized successfully
CORE.Window.ready = InitGraphicsDevice(width, height); CORE.Window.ready = InitGraphicsDevice(width, height);
@ -885,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)
@ -907,7 +901,7 @@ void InitWindow(int width, int height, const char *title)
} }
#endif #endif
#if defined(PLATFORM_RPI) || defined(PLATFORM_DRM) #if defined(PLATFORM_DRM)
// Initialize raw input system // Initialize raw input system
InitEvdevInput(); // Evdev inputs initialization InitEvdevInput(); // Evdev inputs initialization
InitGamepad(); // Gamepad init InitGamepad(); // Gamepad init
@ -949,7 +943,7 @@ void InitWindow(int width, int height, const char *title)
CORE.Time.frameCounter = 0; CORE.Time.frameCounter = 0;
#endif #endif
#endif // PLATFORM_DESKTOP || PLATFORM_WEB || PLATFORM_RPI || PLATFORM_DRM #endif // PLATFORM_DESKTOP || PLATFORM_WEB || PLATFORM_DRM
} }
// Close window and unload OpenGL context // Close window and unload OpenGL context
@ -979,7 +973,7 @@ void CloseWindow(void)
timeEndPeriod(1); // Restore time period timeEndPeriod(1); // Restore time period
#endif #endif
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) #if defined(PLATFORM_ANDROID)
// Close surface, context and display // Close surface, context and display
if (CORE.Window.device != EGL_NO_DISPLAY) if (CORE.Window.device != EGL_NO_DISPLAY)
{ {
@ -1067,7 +1061,7 @@ void CloseWindow(void)
} }
#endif #endif
#if defined(PLATFORM_RPI) || defined(PLATFORM_DRM) #if defined(PLATFORM_DRM)
// Wait for mouse and gamepad threads to finish before closing // Wait for mouse and gamepad threads to finish before closing
// NOTE: Those threads should already have finished at this point // NOTE: Those threads should already have finished at this point
// because they are controlled by CORE.Window.shouldClose variable // because they are controlled by CORE.Window.shouldClose variable
@ -1129,7 +1123,7 @@ bool WindowShouldClose(void)
else return true; else return true;
#endif #endif
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_DRM) #if defined(PLATFORM_ANDROID) || defined(PLATFORM_DRM)
if (CORE.Window.ready) return CORE.Window.shouldClose; if (CORE.Window.ready) return CORE.Window.shouldClose;
else return true; else return true;
#endif #endif
@ -1315,7 +1309,7 @@ void ToggleFullscreen(void)
CORE.Window.fullscreen = !CORE.Window.fullscreen; // Toggle fullscreen flag CORE.Window.fullscreen = !CORE.Window.fullscreen; // Toggle fullscreen flag
#endif #endif
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_DRM) #if defined(PLATFORM_ANDROID) || defined(PLATFORM_DRM)
TRACELOG(LOG_WARNING, "SYSTEM: Failed to toggle to windowed mode"); TRACELOG(LOG_WARNING, "SYSTEM: Failed to toggle to windowed mode");
#endif #endif
} }
@ -2148,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
} }
@ -2997,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;
@ -3038,7 +3032,7 @@ double GetTime(void)
time = glfwGetTime(); // Elapsed time since glfwInit() time = glfwGetTime(); // Elapsed time since glfwInit()
#endif #endif
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_DRM) #if defined(PLATFORM_ANDROID) || defined(PLATFORM_DRM)
struct timespec ts = { 0 }; struct timespec ts = { 0 };
clock_gettime(CLOCK_MONOTONIC, &ts); clock_gettime(CLOCK_MONOTONIC, &ts);
unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec; unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec;
@ -3191,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);
} }
@ -3493,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
@ -3694,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
{ {
@ -3750,16 +3755,38 @@ bool IsKeyPressed(int key)
{ {
bool pressed = false; bool pressed = false;
if ((CORE.Input.Keyboard.previousKeyState[key] == 0) && (CORE.Input.Keyboard.currentKeyState[key] == 1)) pressed = true; if ((key > 0) && (key < MAX_KEYBOARD_KEYS))
{
if ((CORE.Input.Keyboard.previousKeyState[key] == 0) && (CORE.Input.Keyboard.currentKeyState[key] == 1)) pressed = true;
}
return pressed; return pressed;
} }
// Check if a key has been pressed again (only PLATFORM_DESKTOP)
bool IsKeyPressedRepeat(int key)
{
bool repeat = false;
if ((key > 0) && (key < MAX_KEYBOARD_KEYS))
{
if (CORE.Input.Keyboard.keyRepeatInFrame[key] == 1) repeat = true;
}
return repeat;
}
// 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 (CORE.Input.Keyboard.currentKeyState[key] == 1) return true; bool down = false;
else return false;
if ((key > 0) && (key < MAX_KEYBOARD_KEYS))
{
if (CORE.Input.Keyboard.currentKeyState[key] == 1) down = true;
}
return down;
} }
// Check if a key has been released once // Check if a key has been released once
@ -3767,7 +3794,10 @@ bool IsKeyReleased(int key)
{ {
bool released = false; bool released = false;
if ((CORE.Input.Keyboard.previousKeyState[key] == 1) && (CORE.Input.Keyboard.currentKeyState[key] == 0)) released = true; if ((key > 0) && (key < MAX_KEYBOARD_KEYS))
{
if ((CORE.Input.Keyboard.previousKeyState[key] == 1) && (CORE.Input.Keyboard.currentKeyState[key] == 0)) released = true;
}
return released; return released;
} }
@ -3775,8 +3805,14 @@ 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 (CORE.Input.Keyboard.currentKeyState[key] == 0) return true; bool up = false;
else return false;
if ((key > 0) && (key < MAX_KEYBOARD_KEYS))
{
if (CORE.Input.Keyboard.currentKeyState[key] == 0) up = true;
}
return up;
} }
// Get the last key pressed // Get the last key pressed
@ -3789,7 +3825,7 @@ int GetKeyPressed(void)
// Get character from the queue head // Get character from the queue head
value = CORE.Input.Keyboard.keyPressedQueue[0]; value = CORE.Input.Keyboard.keyPressedQueue[0];
// Shift elements 1 step toward the head. // Shift elements 1 step toward the head
for (int i = 0; i < (CORE.Input.Keyboard.keyPressedQueueCount - 1); i++) for (int i = 0; i < (CORE.Input.Keyboard.keyPressedQueueCount - 1); i++)
CORE.Input.Keyboard.keyPressedQueue[i] = CORE.Input.Keyboard.keyPressedQueue[i + 1]; CORE.Input.Keyboard.keyPressedQueue[i] = CORE.Input.Keyboard.keyPressedQueue[i + 1];
@ -3811,7 +3847,7 @@ int GetCharPressed(void)
// Get character from the queue head // Get character from the queue head
value = CORE.Input.Keyboard.charPressedQueue[0]; value = CORE.Input.Keyboard.charPressedQueue[0];
// Shift elements 1 step toward the head. // Shift elements 1 step toward the head
for (int i = 0; i < (CORE.Input.Keyboard.charPressedQueueCount - 1); i++) for (int i = 0; i < (CORE.Input.Keyboard.charPressedQueueCount - 1); i++)
CORE.Input.Keyboard.charPressedQueue[i] = CORE.Input.Keyboard.charPressedQueue[i + 1]; CORE.Input.Keyboard.charPressedQueue[i] = CORE.Input.Keyboard.charPressedQueue[i + 1];
@ -3847,24 +3883,29 @@ bool IsGamepadAvailable(int gamepad)
// Get gamepad internal name id // Get gamepad internal name id
const char *GetGamepadName(int gamepad) const char *GetGamepadName(int gamepad)
{ {
const char *name = NULL;
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
if (CORE.Input.Gamepad.ready[gamepad]) return glfwGetJoystickName(gamepad); if (CORE.Input.Gamepad.ready[gamepad]) name = glfwGetJoystickName(gamepad);
else return NULL;
#endif #endif
#if defined(PLATFORM_RPI) || defined(PLATFORM_DRM) #if defined(PLATFORM_DRM)
if (CORE.Input.Gamepad.ready[gamepad]) ioctl(CORE.Input.Gamepad.streamId[gamepad], JSIOCGNAME(64), &CORE.Input.Gamepad.name[gamepad]); if (CORE.Input.Gamepad.ready[gamepad])
return CORE.Input.Gamepad.name[gamepad]; {
ioctl(CORE.Input.Gamepad.streamId[gamepad], JSIOCGNAME(64), &CORE.Input.Gamepad.name[gamepad]);
name = CORE.Input.Gamepad.name[gamepad];
}
#endif #endif
#if defined(PLATFORM_WEB) #if defined(PLATFORM_WEB)
return CORE.Input.Gamepad.name[gamepad]; name = CORE.Input.Gamepad.name[gamepad];
#endif #endif
return NULL;
return name;
} }
// Get gamepad axis count // Get gamepad axis count
int GetGamepadAxisCount(int gamepad) int GetGamepadAxisCount(int gamepad)
{ {
#if defined(PLATFORM_RPI) || defined(PLATFORM_DRM) #if defined(PLATFORM_DRM)
int axisCount = 0; int axisCount = 0;
if (CORE.Input.Gamepad.ready[gamepad]) ioctl(CORE.Input.Gamepad.streamId[gamepad], JSIOCGAXES, &axisCount); if (CORE.Input.Gamepad.ready[gamepad]) ioctl(CORE.Input.Gamepad.streamId[gamepad], JSIOCGAXES, &axisCount);
CORE.Input.Gamepad.axisCount = axisCount; CORE.Input.Gamepad.axisCount = axisCount;
@ -3898,12 +3939,12 @@ bool IsGamepadButtonPressed(int gamepad, int button)
// Check if a gamepad button is being pressed // Check if a gamepad button is being pressed
bool IsGamepadButtonDown(int gamepad, int button) bool IsGamepadButtonDown(int gamepad, int button)
{ {
bool result = false; bool down = false;
if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (button < MAX_GAMEPAD_BUTTONS) && if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (button < MAX_GAMEPAD_BUTTONS) &&
(CORE.Input.Gamepad.currentButtonState[gamepad][button] == 1)) result = true; (CORE.Input.Gamepad.currentButtonState[gamepad][button] == 1)) down = true;
return result; return down;
} }
// Check if a gamepad button has NOT been pressed once // Check if a gamepad button has NOT been pressed once
@ -3920,12 +3961,12 @@ bool IsGamepadButtonReleased(int gamepad, int button)
// Check if a gamepad button is NOT being pressed // Check if a gamepad button is NOT being pressed
bool IsGamepadButtonUp(int gamepad, int button) bool IsGamepadButtonUp(int gamepad, int button)
{ {
bool result = false; bool up = false;
if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (button < MAX_GAMEPAD_BUTTONS) && if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (button < MAX_GAMEPAD_BUTTONS) &&
(CORE.Input.Gamepad.currentButtonState[gamepad][button] == 0)) result = true; (CORE.Input.Gamepad.currentButtonState[gamepad][button] == 0)) up = true;
return result; return up;
} }
// Get the last gamepad button pressed // Get the last gamepad button pressed
@ -3966,7 +4007,7 @@ bool IsMouseButtonDown(int button)
if (CORE.Input.Mouse.currentButtonState[button] == 1) down = true; if (CORE.Input.Mouse.currentButtonState[button] == 1) down = true;
// Map touches to mouse buttons checking // NOTE: Touches are considered like mouse buttons
if (CORE.Input.Touch.currentTouchState[button] == 1) down = true; if (CORE.Input.Touch.currentTouchState[button] == 1) down = true;
return down; return down;
@ -3988,7 +4029,14 @@ bool IsMouseButtonReleased(int button)
// Check if a mouse button is NOT being pressed // Check if a mouse button is NOT being pressed
bool IsMouseButtonUp(int button) bool IsMouseButtonUp(int button)
{ {
return !IsMouseButtonDown(button); bool up = false;
if (CORE.Input.Mouse.currentButtonState[button] == 0) up = true;
// NOTE: Touches are considered like mouse buttons
if (CORE.Input.Touch.currentTouchState[button] == 0) up = true;
return up;
} }
// Get mouse position X // Get mouse position X
@ -4016,9 +4064,12 @@ Vector2 GetMousePosition(void)
{ {
Vector2 position = { 0 }; Vector2 position = { 0 };
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) // TODO: Review touch position on PLATFORM_WEB
#if defined(PLATFORM_ANDROID) //|| defined(PLATFORM_WEB)
position = GetTouchPosition(0); position = GetTouchPosition(0);
#else #else
// NOTE: On PLATFORM_WEB, even on canvas scaling, mouse position is proportionally returned
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;
position.y = (CORE.Input.Mouse.currentPosition.y + CORE.Input.Mouse.offset.y)*CORE.Input.Mouse.scale.y; position.y = (CORE.Input.Mouse.currentPosition.y + CORE.Input.Mouse.offset.y)*CORE.Input.Mouse.scale.y;
#endif #endif
@ -4106,7 +4157,7 @@ int GetTouchX(void)
{ {
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) #if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB)
return (int)CORE.Input.Touch.position[0].x; return (int)CORE.Input.Touch.position[0].x;
#else // PLATFORM_DESKTOP, PLATFORM_RPI, PLATFORM_DRM #else // PLATFORM_DESKTOP, PLATFORM_DRM
return GetMouseX(); return GetMouseX();
#endif #endif
} }
@ -4116,7 +4167,7 @@ int GetTouchY(void)
{ {
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) #if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB)
return (int)CORE.Input.Touch.position[0].y; return (int)CORE.Input.Touch.position[0].y;
#else // PLATFORM_DESKTOP, PLATFORM_RPI, PLATFORM_DRM #else // PLATFORM_DESKTOP, PLATFORM_DRM
return GetMouseY(); return GetMouseY();
#endif #endif
} }
@ -4133,7 +4184,7 @@ Vector2 GetTouchPosition(int index)
// https://docs.microsoft.com/en-us/windows/win32/wintouch/getting-started-with-multi-touch-messages // https://docs.microsoft.com/en-us/windows/win32/wintouch/getting-started-with-multi-touch-messages
if (index == 0) position = GetMousePosition(); if (index == 0) position = GetMousePosition();
#endif #endif
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) || defined(PLATFORM_RPI) || defined(PLATFORM_DRM) #if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) || defined(PLATFORM_DRM)
if (index < MAX_TOUCH_POINTS) position = CORE.Input.Touch.position[index]; if (index < MAX_TOUCH_POINTS) position = CORE.Input.Touch.position[index];
else TRACELOG(LOG_WARNING, "INPUT: Required touch point out of range (Max touch points: %i)", MAX_TOUCH_POINTS); else TRACELOG(LOG_WARNING, "INPUT: Required touch point out of range (Max touch points: %i)", MAX_TOUCH_POINTS);
#endif #endif
@ -4277,9 +4328,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
} }
@ -4461,13 +4512,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;
@ -4502,21 +4556,10 @@ static bool InitGraphicsDevice(int width, int height)
#endif // PLATFORM_DESKTOP || PLATFORM_WEB #endif // PLATFORM_DESKTOP || PLATFORM_WEB
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_DRM) #if defined(PLATFORM_ANDROID) || defined(PLATFORM_DRM)
CORE.Window.fullscreen = true; CORE.Window.fullscreen = true;
CORE.Window.flags |= FLAG_FULLSCREEN_MODE; CORE.Window.flags |= FLAG_FULLSCREEN_MODE;
#if defined(PLATFORM_RPI)
bcm_host_init();
DISPMANX_ELEMENT_HANDLE_T dispmanElement = { 0 };
DISPMANX_DISPLAY_HANDLE_T dispmanDisplay = { 0 };
DISPMANX_UPDATE_HANDLE_T dispmanUpdate = { 0 };
VC_RECT_T dstRect = { 0 };
VC_RECT_T srcRect = { 0 };
#endif
#if defined(PLATFORM_DRM) #if defined(PLATFORM_DRM)
CORE.Window.fd = -1; CORE.Window.fd = -1;
CORE.Window.connector = NULL; CORE.Window.connector = NULL;
@ -4713,7 +4756,7 @@ static bool InitGraphicsDevice(int width, int height)
EGL_NONE EGL_NONE
}; };
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_DRM) #if defined(PLATFORM_ANDROID) || defined(PLATFORM_DRM)
EGLint numConfigs = 0; EGLint numConfigs = 0;
// Get an EGL device connection // Get an EGL device connection
@ -4828,58 +4871,6 @@ static bool InitGraphicsDevice(int width, int height)
CORE.Window.surface = eglCreateWindowSurface(CORE.Window.device, CORE.Window.config, CORE.Android.app->window, NULL); CORE.Window.surface = eglCreateWindowSurface(CORE.Window.device, CORE.Window.config, CORE.Android.app->window, NULL);
#endif // PLATFORM_ANDROID #endif // PLATFORM_ANDROID
#if defined(PLATFORM_RPI)
graphics_get_display_size(0, &CORE.Window.display.width, &CORE.Window.display.height);
// Screen size security check
if (CORE.Window.screen.width <= 0) CORE.Window.screen.width = CORE.Window.display.width;
if (CORE.Window.screen.height <= 0) CORE.Window.screen.height = CORE.Window.display.height;
// At this point we need to manage render size vs screen size
// NOTE: This function use and modify global module variables:
// -> CORE.Window.screen.width/CORE.Window.screen.height
// -> CORE.Window.render.width/CORE.Window.render.height
// -> CORE.Window.screenScale
SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height);
dstRect.x = 0;
dstRect.y = 0;
dstRect.width = CORE.Window.display.width;
dstRect.height = CORE.Window.display.height;
srcRect.x = 0;
srcRect.y = 0;
srcRect.width = CORE.Window.render.width << 16;
srcRect.height = CORE.Window.render.height << 16;
// NOTE: RPI dispmanx windowing system takes care of source rectangle scaling to destination rectangle by hardware (no cost)
// Take care that renderWidth/renderHeight fit on displayWidth/displayHeight aspect ratio
VC_DISPMANX_ALPHA_T alpha = { 0 };
alpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS;
//alpha.flags = DISPMANX_FLAGS_ALPHA_FROM_SOURCE; // TODO: Allow transparent framebuffer! -> FLAG_WINDOW_TRANSPARENT
alpha.opacity = 255; // Set transparency level for framebuffer, requires EGLAttrib: EGL_TRANSPARENT_TYPE
alpha.mask = 0;
dispmanDisplay = vc_dispmanx_display_open(0); // LCD
dispmanUpdate = vc_dispmanx_update_start(0);
dispmanElement = vc_dispmanx_element_add(dispmanUpdate, dispmanDisplay, 0/*layer*/, &dstRect, 0/*src*/,
&srcRect, DISPMANX_PROTECTION_NONE, &alpha, 0/*clamp*/, DISPMANX_NO_ROTATE);
CORE.Window.handle.element = dispmanElement;
CORE.Window.handle.width = CORE.Window.render.width;
CORE.Window.handle.height = CORE.Window.render.height;
vc_dispmanx_update_submit_sync(dispmanUpdate);
CORE.Window.surface = eglCreateWindowSurface(CORE.Window.device, CORE.Window.config, &CORE.Window.handle, NULL);
const unsigned char *const renderer = glGetString(GL_RENDERER);
if (renderer) TRACELOG(LOG_INFO, "DISPLAY: Renderer name is: %s", renderer);
else TRACELOG(LOG_WARNING, "DISPLAY: Failed to get renderer name");
//---------------------------------------------------------------------------------
#endif // PLATFORM_RPI
#if defined(PLATFORM_DRM) #if defined(PLATFORM_DRM)
CORE.Window.surface = eglCreateWindowSurface(CORE.Window.device, CORE.Window.config, (EGLNativeWindowType)CORE.Window.gbmSurface, NULL); CORE.Window.surface = eglCreateWindowSurface(CORE.Window.device, CORE.Window.config, (EGLNativeWindowType)CORE.Window.gbmSurface, NULL);
if (EGL_NO_SURFACE == CORE.Window.surface) if (EGL_NO_SURFACE == CORE.Window.surface)
@ -4917,7 +4908,7 @@ static bool InitGraphicsDevice(int width, int height)
TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height); TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);
TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y); TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y);
} }
#endif // PLATFORM_ANDROID || PLATFORM_RPI || PLATFORM_DRM #endif // PLATFORM_ANDROID || PLATFORM_DRM
// Load OpenGL extensions // Load OpenGL extensions
// NOTE: GL procedures address loader is required to load extensions // NOTE: GL procedures address loader is required to load extensions
@ -5061,7 +5052,7 @@ static void InitTimer(void)
timeBeginPeriod(1); // Setup high-resolution timer to 1ms (granularity of 1-2 ms) timeBeginPeriod(1); // Setup high-resolution timer to 1ms (granularity of 1-2 ms)
#endif #endif
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_DRM) #if defined(PLATFORM_ANDROID) || defined(PLATFORM_DRM)
struct timespec now = { 0 }; struct timespec now = { 0 };
if (clock_gettime(CLOCK_MONOTONIC, &now) == 0) // Success if (clock_gettime(CLOCK_MONOTONIC, &now) == 0) // Success
@ -5125,7 +5116,7 @@ void SwapScreenBuffer(void)
glfwSwapBuffers(CORE.Window.handle); glfwSwapBuffers(CORE.Window.handle);
#endif #endif
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_DRM) #if defined(PLATFORM_ANDROID) || defined(PLATFORM_DRM)
eglSwapBuffers(CORE.Window.device, CORE.Window.surface); eglSwapBuffers(CORE.Window.device, CORE.Window.surface);
#if defined(PLATFORM_DRM) #if defined(PLATFORM_DRM)
@ -5155,7 +5146,7 @@ void SwapScreenBuffer(void)
CORE.Window.prevBO = bo; CORE.Window.prevBO = bo;
#endif // PLATFORM_DRM #endif // PLATFORM_DRM
#endif // PLATFORM_ANDROID || PLATFORM_RPI || PLATFORM_DRM #endif // PLATFORM_ANDROID || PLATFORM_DRM
} }
// Register all input events // Register all input events
@ -5170,16 +5161,20 @@ 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;
#if !(defined(PLATFORM_RPI) || defined(PLATFORM_DRM))
// 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
CORE.Input.Gamepad.axisCount = 0; CORE.Input.Gamepad.axisCount = 0;
#endif
#if defined(PLATFORM_RPI) || 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();
@ -5208,7 +5203,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];
@ -5390,7 +5389,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;
@ -5412,7 +5415,7 @@ void PollInputEvents(void)
} }
#endif #endif
#if (defined(PLATFORM_RPI) || defined(PLATFORM_DRM)) && defined(SUPPORT_SSH_KEYBOARD_RPI) #if defined(PLATFORM_DRM) && defined(SUPPORT_SSH_KEYBOARD_RPI)
// NOTE: Keyboard reading could be done using input_event(s) or just read from stdin, both methods are used here. // NOTE: Keyboard reading could be done using input_event(s) or just read from stdin, both methods are used here.
// stdin reading is still used for legacy purposes, it allows keyboard input trough SSH console // stdin reading is still used for legacy purposes, it allows keyboard input trough SSH console
@ -5586,7 +5589,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
@ -5890,7 +5894,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... :(
@ -6054,6 +6058,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)
@ -6285,7 +6290,7 @@ static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent
} }
#endif #endif
#if defined(PLATFORM_RPI) || defined(PLATFORM_DRM) #if defined(PLATFORM_DRM)
// Initialize Keyboard system (using standard input) // Initialize Keyboard system (using standard input)
static void InitKeyboard(void) static void InitKeyboard(void)
{ {
@ -6357,7 +6362,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++)
@ -6473,7 +6482,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);
@ -6575,7 +6588,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;
@ -6589,7 +6602,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;
@ -6604,7 +6617,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);
@ -6612,7 +6625,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);
@ -6740,7 +6753,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)))
@ -6817,8 +6830,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;
@ -6826,8 +6839,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;
@ -6838,12 +6851,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)
@ -6918,7 +6931,7 @@ static void *EventThread(void *arg)
if (CORE.Input.Touch.position[2].x >= 0) CORE.Input.Touch.pointCount++; if (CORE.Input.Touch.position[2].x >= 0) CORE.Input.Touch.pointCount++;
if (CORE.Input.Touch.position[3].x >= 0) CORE.Input.Touch.pointCount++; if (CORE.Input.Touch.position[3].x >= 0) CORE.Input.Touch.pointCount++;
#if defined(SUPPORT_GESTURES_SYSTEM) // PLATFORM_RPI, PLATFORM_DRM #if defined(SUPPORT_GESTURES_SYSTEM) // PLATFORM_DRM
if (gestureUpdate) if (gestureUpdate)
{ {
GestureEvent gestureEvent = { 0 }; GestureEvent gestureEvent = { 0 };
@ -7035,7 +7048,7 @@ static void *GamepadThread(void *arg)
return NULL; return NULL;
} }
#endif // PLATFORM_RPI || PLATFORM_DRM #endif // PLATFORM_DRM
#if defined(PLATFORM_DRM) #if defined(PLATFORM_DRM)
// Search matching DRM mode in connector's mode list // Search matching DRM mode in connector's mode list

View File

@ -815,7 +815,7 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
// It seems OpenGL ES 2.0 instancing entry points are not defined on Raspberry Pi // It seems OpenGL ES 2.0 instancing entry points are not defined on Raspberry Pi
// provided headers (despite being defined in official Khronos GLES2 headers) // provided headers (despite being defined in official Khronos GLES2 headers)
#if defined(PLATFORM_RPI) || defined(PLATFORM_DRM) #if defined(PLATFORM_DRM)
typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount); typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount);
typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISOREXTPROC) (GLuint index, GLuint divisor); typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISOREXTPROC) (GLuint index, GLuint divisor);
@ -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;
@ -3681,7 +3687,11 @@ void rlDrawVertexArray(int offset, int count)
// Draw vertex array elements // Draw vertex array elements
void rlDrawVertexArrayElements(int offset, int count, const void *buffer) void rlDrawVertexArrayElements(int offset, int count, const void *buffer)
{ {
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (const unsigned short *)buffer + offset); // NOTE: Added pointer math separately from function to avoid UBSAN complaining
unsigned short *bufferPtr = (unsigned short *)buffer;
if (offset > 0) bufferPtr += offset;
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (const unsigned short *)bufferPtr);
} }
// Draw vertex array instanced // Draw vertex array instanced
@ -3696,7 +3706,11 @@ void rlDrawVertexArrayInstanced(int offset, int count, int instances)
void rlDrawVertexArrayElementsInstanced(int offset, int count, const void *buffer, int instances) void rlDrawVertexArrayElementsInstanced(int offset, int count, const void *buffer, int instances)
{ {
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
glDrawElementsInstanced(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (const unsigned short *)buffer + offset, instances); // NOTE: Added pointer math separately from function to avoid UBSAN complaining
unsigned short *bufferPtr = (unsigned short *)buffer;
if (offset > 0) bufferPtr += offset;
glDrawElementsInstanced(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (const unsigned short *)bufferPtr, instances);
#endif #endif
} }
@ -4544,6 +4558,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"

View File

@ -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);

View File

@ -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)
{ {

View File

@ -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;
@ -779,23 +788,23 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
} }
} }
// Copy pixel data from fc.data to atlas // Copy pixel data from glyph image 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;

View File

@ -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

View File

@ -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");