diff --git a/.github/workflows/analyze_codeql.yml b/.github/workflows/analyze_codeql.yml
index 5fd169dd0..6598aa063 100644
--- a/.github/workflows/analyze_codeql.yml
+++ b/.github/workflows/analyze_codeql.yml
@@ -44,7 +44,7 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@master
with:
submodules: recursive
@@ -128,7 +128,7 @@ jobs:
- name: Upload CodeQL results as an artifact
if: success() || failure()
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@v7
with:
name: codeql-results
path: ${{ steps.step1.outputs.sarif-output }}
diff --git a/.github/workflows/build_android.yml b/.github/workflows/build_android.yml
index c87807847..b4efab67c 100644
--- a/.github/workflows/build_android.yml
+++ b/.github/workflows/build_android.yml
@@ -21,7 +21,7 @@ permissions:
jobs:
build:
permissions:
- contents: write # for actions/upload-release-asset to upload release asset
+ contents: write # Required for actions/upload-release-asset to upload release asset
runs-on: windows-latest
strategy:
fail-fast: false
@@ -82,7 +82,7 @@ jobs:
tar -czvf ${{ env.RELEASE_NAME }}.tar.gz ${{ env.RELEASE_NAME }}
- name: Upload Artifacts
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@v7
with:
name: ${{ env.RELEASE_NAME }}
path: |
@@ -90,7 +90,7 @@ jobs:
!./build/${{ env.RELEASE_NAME }}.tar.gz
- name: Upload Artifact to Release
- uses: softprops/action-gh-release@v1
+ uses: softprops/action-gh-release@v3
with:
files: ./build/${{ env.RELEASE_NAME }}.tar.gz
env:
diff --git a/.github/workflows/build_cmake.yml b/.github/workflows/build_cmake.yml
index 0158fb510..da1993026 100644
--- a/.github/workflows/build_cmake.yml
+++ b/.github/workflows/build_cmake.yml
@@ -36,7 +36,7 @@ jobs:
runs-on: windows-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@master
- name: Create Build Environment
# Some projects don't allow in-source building, so create a separate build directory
@@ -75,7 +75,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@master
- name: Create Build Environment
# Some projects don't allow in-source building, so create a separate build directory
diff --git a/.github/workflows/build_examples_linux.yml b/.github/workflows/build_examples_linux.yml
index c293efd1d..ca15acd81 100644
--- a/.github/workflows/build_examples_linux.yml
+++ b/.github/workflows/build_examples_linux.yml
@@ -22,7 +22,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
- uses: actions/checkout@v4
+ uses: actions/checkout@master
- name: Setup Environment
run: |
diff --git a/.github/workflows/build_examples_windows.yml b/.github/workflows/build_examples_windows.yml
index 4cc2e84b9..186242c24 100644
--- a/.github/workflows/build_examples_windows.yml
+++ b/.github/workflows/build_examples_windows.yml
@@ -22,7 +22,7 @@ jobs:
runs-on: windows-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@master
- name: Add MSBuild to PATH
uses: microsoft/setup-msbuild@v1
diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml
index 0fc32d374..fa1c0b82c 100644
--- a/.github/workflows/build_linux.yml
+++ b/.github/workflows/build_linux.yml
@@ -21,7 +21,7 @@ permissions:
jobs:
build:
permissions:
- contents: write # for actions/upload-release-asset to upload release asset
+ contents: write # Required for actions/upload-release-asset to upload release asset
strategy:
fail-fast: false
max-parallel: 1
@@ -112,7 +112,7 @@ jobs:
tar -czvf ${{ env.RELEASE_NAME }}.tar.gz ${{ env.RELEASE_NAME }}
- name: Upload Artifacts
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@v7
with:
name: ${{ env.RELEASE_NAME }}
path: |
@@ -120,7 +120,7 @@ jobs:
!./build/${{ env.RELEASE_NAME }}.tar.gz
- name: Upload Artifact to Release
- uses: softprops/action-gh-release@v1
+ uses: softprops/action-gh-release@v3
with:
files: ./build/${{ env.RELEASE_NAME }}.tar.gz
env:
diff --git a/.github/workflows/build_macos.yml b/.github/workflows/build_macos.yml
index 08ea0188a..9da31412e 100644
--- a/.github/workflows/build_macos.yml
+++ b/.github/workflows/build_macos.yml
@@ -21,7 +21,7 @@ permissions:
jobs:
build:
permissions:
- contents: write # for actions/upload-release-asset to upload release asset
+ contents: write # Required for actions/upload-release-asset to upload release asset
runs-on: macos-latest
env:
@@ -99,7 +99,7 @@ jobs:
tar -czvf ${{ env.RELEASE_NAME }}.tar.gz ${{ env.RELEASE_NAME }}
- name: Upload Artifacts
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@v7
with:
name: ${{ env.RELEASE_NAME }}
path: |
@@ -107,7 +107,7 @@ jobs:
!./build/${{ env.RELEASE_NAME }}.tar.gz
- name: Upload Artifact to Release
- uses: softprops/action-gh-release@v1
+ uses: softprops/action-gh-release@v3
with:
files: ./build/${{ env.RELEASE_NAME }}.tar.gz
env:
diff --git a/.github/workflows/build_webassembly.yml b/.github/workflows/build_webassembly.yml
index 1e4066c26..ae4b37087 100644
--- a/.github/workflows/build_webassembly.yml
+++ b/.github/workflows/build_webassembly.yml
@@ -27,7 +27,7 @@ jobs:
uses: actions/checkout@master
- name: Setup emsdk
- uses: mymindstorm/setup-emsdk@v14
+ uses: emscripten-core/setup-emsdk@v15
with:
version: 5.0.3
actions-cache-folder: 'emsdk-cache'
@@ -69,7 +69,7 @@ jobs:
shell: cmd
- name: Upload Artifacts
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@v7
with:
name: ${{ env.RELEASE_NAME }}
path: |
@@ -77,7 +77,7 @@ jobs:
!./build/${{ env.RELEASE_NAME }}.zip
- name: Upload Artifact to Release
- uses: softprops/action-gh-release@v1
+ uses: softprops/action-gh-release@v3
with:
files: ./build/${{ env.RELEASE_NAME }}.zip
env:
diff --git a/.github/workflows/build_windows.yml b/.github/workflows/build_windows.yml
index 988428403..10b7ca91b 100644
--- a/.github/workflows/build_windows.yml
+++ b/.github/workflows/build_windows.yml
@@ -21,7 +21,7 @@ permissions:
jobs:
build:
permissions:
- contents: write # for actions/upload-release-asset to upload release asset
+ contents: write # Required for actions/upload-release-asset to upload release asset
runs-on: windows-latest
strategy:
fail-fast: false
@@ -81,7 +81,7 @@ jobs:
# Setup MSBuild.exe path if required
- name: Setup MSBuild
- uses: microsoft/setup-msbuild@v2
+ uses: microsoft/setup-msbuild@v3
if: matrix.compiler == 'msvc16'
- name: Build Library (MinGW-w64 32bit)
@@ -140,7 +140,7 @@ jobs:
shell: cmd
- name: Upload Artifacts
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@v7
with:
name: ${{ env.RELEASE_NAME }}
path: |
@@ -148,7 +148,7 @@ jobs:
!./build/${{ env.RELEASE_NAME }}.zip
- name: Upload Artifact to Release
- uses: softprops/action-gh-release@v1
+ uses: softprops/action-gh-release@v3
with:
files: ./build/${{ env.RELEASE_NAME }}.zip
env:
diff --git a/.github/workflows/parse_api.yml b/.github/workflows/parse_api.yml
index e25cde18b..36f7fb5db 100644
--- a/.github/workflows/parse_api.yml
+++ b/.github/workflows/parse_api.yml
@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@master
- name: Update parse files
working-directory: tools/rlparser
diff --git a/.github/workflows/update_examples.yml b/.github/workflows/update_examples.yml
index fe8e4c48f..1d1edc524 100644
--- a/.github/workflows/update_examples.yml
+++ b/.github/workflows/update_examples.yml
@@ -15,10 +15,10 @@ jobs:
steps:
- name: Checkout
- uses: actions/checkout@v4
+ uses: actions/checkout@master
- name: Setup emsdk
- uses: mymindstorm/setup-emsdk@v14
+ uses: emscripten-core/setup-emsdk@v15
with:
version: 'latest'
actions-cache-folder: 'emsdk-cache'
diff --git a/BINDINGS.md b/BINDINGS.md
index f528c892a..624ec8155 100644
--- a/BINDINGS.md
+++ b/BINDINGS.md
@@ -52,7 +52,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers
| [KaylibKit](https://codeberg.org/Kenta/KaylibKit) | 4.5 | [Kotlin/native](https://kotlinlang.org) | Zlib |
| [raylib-lua](https://github.com/TSnake41/raylib-lua) | 5.5 | [Lua](http://www.lua.org) | ISC |
| [raylib-lua-bindings (WIP)](https://github.com/legendaryredfox/raylib-lua-bindings) | 5.5 | [Lua](http://www.lua.org) | ISC |
-| [ReiLua](https://github.com/nullstare/ReiLua) | 5.5 | [Lua](http://www.lua.org) | MIT |
+| [ReiLua](https://github.com/nullstare/ReiLua) | 6.0 | [Lua](http://www.lua.org) | MIT |
| [raylib-lua-sol](https://github.com/RobLoach/raylib-lua-sol) | 5.5 | [Lua](http://www.lua.org) | Zlib |
| [raylib-luajit](https://github.com/homma/raylib-luajit) | 5.5 | [Lua](http://www.lua.org) | MIT |
| [raylib-luajit-generated](https://github.com/james2doyle/raylib-luajit-generated) | 5.5 | [Lua](http://www.lua.org) | MIT |
diff --git a/SECURITY.md b/SECURITY.md
index 48a825e37..7a52e4359 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -11,8 +11,4 @@ Most considerations of errors and defects can be handled using the project Issue
## Reporting a Vulnerability
-Discovered vulnerability can be directly reported using the project Issues and/or Discussions.
-
-_TODO: Tell them where to go, how often they can expect to get an update on a
-reported vulnerability, what to expect if the vulnerability is accepted or
-declined, etc._
+Discovered vulnerability can be directly reported using the project Issues and/or Discussions. They will be reviewed as soon as possible.
diff --git a/examples/shaders/resources/shaders/glsl100/pbr.fs b/examples/shaders/resources/shaders/glsl100/pbr.fs
index 28212bf63..f29cb0e59 100644
--- a/examples/shaders/resources/shaders/glsl100/pbr.fs
+++ b/examples/shaders/resources/shaders/glsl100/pbr.fs
@@ -99,7 +99,7 @@ vec3 ComputePBR()
vec3 N = normalize(fragNormal);
if (useTexNormal == 1)
{
- N = texture2D(normalMap, vec2(fragTexCoord.x*tiling.x + offset.y, fragTexCoord.y*tiling.y + offset.y)).rgb;
+ N = texture2D(normalMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb;
N = normalize(N*2.0 - 1.0);
N = normalize(N*TBN);
}
diff --git a/examples/shaders/resources/shaders/glsl120/pbr.fs b/examples/shaders/resources/shaders/glsl120/pbr.fs
index b36b76bee..450986f1b 100644
--- a/examples/shaders/resources/shaders/glsl120/pbr.fs
+++ b/examples/shaders/resources/shaders/glsl120/pbr.fs
@@ -97,7 +97,7 @@ vec3 ComputePBR()
vec3 N = normalize(fragNormal);
if (useTexNormal == 1)
{
- N = texture2D(normalMap, vec2(fragTexCoord.x*tiling.x + offset.y, fragTexCoord.y*tiling.y + offset.y)).rgb;
+ N = texture2D(normalMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb;
N = normalize(N*2.0 - 1.0);
N = normalize(N*TBN);
}
diff --git a/examples/shaders/resources/shaders/glsl330/pbr.fs b/examples/shaders/resources/shaders/glsl330/pbr.fs
index ceaead308..67254851c 100644
--- a/examples/shaders/resources/shaders/glsl330/pbr.fs
+++ b/examples/shaders/resources/shaders/glsl330/pbr.fs
@@ -100,7 +100,7 @@ vec3 ComputePBR()
vec3 N = normalize(fragNormal);
if (useTexNormal == 1)
{
- N = texture(normalMap, vec2(fragTexCoord.x*tiling.x + offset.y, fragTexCoord.y*tiling.y + offset.y)).rgb;
+ N = texture(normalMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb;
N = normalize(N*2.0 - 1.0);
N = normalize(N*TBN);
}
diff --git a/projects/4coder/Makefile b/projects/4coder/Makefile
deleted file mode 100644
index ec0977aaf..000000000
--- a/projects/4coder/Makefile
+++ /dev/null
@@ -1,401 +0,0 @@
-#**************************************************************************************************
-#
-# raylib makefile for Desktop platforms, Raspberry Pi, Android and HTML5
-#
-# Copyright (c) 2013-2026 Ramon Santamaria (@raysan5)
-#
-# This software is provided "as-is", without any express or implied warranty. In no event
-# will the authors be held liable for any damages arising from the use of this software.
-#
-# Permission is granted to anyone to use this software for any purpose, including commercial
-# applications, and to alter it and redistribute it freely, subject to the following restrictions:
-#
-# 1. The origin of this software must not be misrepresented; you must not claim that you
-# wrote the original software. If you use this software in a product, an acknowledgment
-# in the product documentation would be appreciated but is not required.
-#
-# 2. Altered source versions must be plainly marked as such, and must not be misrepresented
-# as being the original software.
-#
-# 3. This notice may not be removed or altered from any source distribution.
-#
-#**************************************************************************************************
-
-.PHONY: all clean
-
-# Define required raylib variables
-PROJECT_NAME ?= game
-RAYLIB_VERSION ?= 4.2.0
-RAYLIB_PATH ?= ..\..
-
-# Define default options
-
-# One of PLATFORM_DESKTOP, PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB
-PLATFORM ?= PLATFORM_DESKTOP
-
-# Locations of your newly installed library and associated headers. See ../src/Makefile
-# On Linux, if you have installed raylib but cannot compile the examples, check that
-# the *_INSTALL_PATH values here are the same as those in src/Makefile or point to known locations.
-# To enable system-wide compile-time and runtime linking to libraylib.so, run ../src/$ sudo make install RAYLIB_LIBTYPE_SHARED.
-# To enable compile-time linking to a special version of libraylib.so, change these variables here.
-# To enable runtime linking to a special version of libraylib.so, see EXAMPLE_RUNTIME_PATH below.
-# If there is a libraylib in both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, at runtime,
-# the library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over the one at RAYLIB_INSTALL_PATH.
-# RAYLIB_INSTALL_PATH should be the desired full path to libraylib. No relative paths.
-DESTDIR ?= /usr/local
-RAYLIB_INSTALL_PATH ?= $(DESTDIR)/lib
-# RAYLIB_H_INSTALL_PATH locates the installed raylib header and associated source files.
-RAYLIB_H_INSTALL_PATH ?= $(DESTDIR)/include
-
-# Library type used for raylib: STATIC (.a) or SHARED (.so/.dll)
-RAYLIB_LIBTYPE ?= STATIC
-
-# Build mode for project: DEBUG or RELEASE
-BUILD_MODE ?= RELEASE
-
-# Use external GLFW library instead of rglfw module
-# TODO: Review usage on Linux. Target version of choice. Switch on -lglfw or -lglfw3
-USE_EXTERNAL_GLFW ?= FALSE
-
-# Use Wayland display server protocol on Linux desktop
-# by default it uses X11 windowing system
-USE_WAYLAND_DISPLAY ?= FALSE
-
-# Determine PLATFORM_OS in case PLATFORM_DESKTOP selected
-ifeq ($(PLATFORM),PLATFORM_DESKTOP)
- # No uname.exe on MinGW!, but OS=Windows_NT on Windows!
- # ifeq ($(UNAME),Msys) -> Windows
- ifeq ($(OS),Windows_NT)
- PLATFORM_OS=WINDOWS
- else
- UNAMEOS=$(shell uname)
- ifeq ($(UNAMEOS),Linux)
- PLATFORM_OS=LINUX
- endif
- ifeq ($(UNAMEOS),FreeBSD)
- PLATFORM_OS=BSD
- endif
- ifeq ($(UNAMEOS),OpenBSD)
- PLATFORM_OS=BSD
- endif
- ifeq ($(UNAMEOS),NetBSD)
- PLATFORM_OS=BSD
- endif
- ifeq ($(UNAMEOS),DragonFly)
- PLATFORM_OS=BSD
- endif
- ifeq ($(UNAMEOS),Darwin)
- PLATFORM_OS=OSX
- endif
- endif
-endif
-ifeq ($(PLATFORM),PLATFORM_RPI)
- UNAMEOS=$(shell uname)
- ifeq ($(UNAMEOS),Linux)
- PLATFORM_OS=LINUX
- endif
-endif
-
-# RAYLIB_PATH adjustment for different platforms.
-# If using GNU make, we can get the full path to the top of the tree. Windows? BSD?
-# Required for ldconfig or other tools that do not perform path expansion.
-ifeq ($(PLATFORM),PLATFORM_DESKTOP)
- ifeq ($(PLATFORM_OS),LINUX)
- RAYLIB_PREFIX ?= ..
- RAYLIB_PATH = $(realpath $(RAYLIB_PREFIX))
- endif
-endif
-# Default path for raylib on Raspberry Pi, if installed in different path, update it!
-# This is not currently used by src/Makefile. Not sure of its origin or usage. Refer to wiki.
-# TODO: update install: target in src/Makefile for RPI, consider relation to LINUX.
-ifeq ($(PLATFORM),PLATFORM_RPI)
- RAYLIB_PATH ?= /home/pi/raylib
-endif
-
-ifeq ($(PLATFORM),PLATFORM_WEB)
- # Emscripten required variables
- EMSDK_PATH ?= C:/raylib/emsdk
- EMSCRIPTEN_PATH ?= $(EMSDK_PATH)/upstream/emscripten
- CLANG_PATH = $(EMSDK_PATH)/upstream/bin
- PYTHON_PATH = $(EMSDK_PATH)/python/3.13.3_64bit
- NODE_PATH = $(EMSDK_PATH)/node/22.16.0_64bit/bin
- export PATH = $(EMSDK_PATH);$(EMSCRIPTEN_PATH);$(CLANG_PATH);$(NODE_PATH);$(PYTHON_PATH);C:\raylib\MinGW\bin:$$(PATH)
-endif
-
-# Define raylib release directory for compiled library.
-# RAYLIB_RELEASE_PATH points to provided binaries or your freshly built version
-RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/src
-
-# EXAMPLE_RUNTIME_PATH embeds a custom runtime location of libraylib.so or other desired libraries
-# into each example binary compiled with RAYLIB_LIBTYPE=SHARED. It defaults to RAYLIB_RELEASE_PATH
-# so that these examples link at runtime with your version of libraylib.so in ../release/libs/linux
-# without formal installation from ../src/Makefile. It aids portability and is useful if you have
-# multiple versions of raylib, have raylib installed to a non-standard location, or want to
-# bundle libraylib.so with your game. Change it to your liking.
-# NOTE: If, at runtime, there is a libraylib.so at both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH,
-# The library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over RAYLIB_INSTALL_PATH,
-# Implemented for LINUX below with CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH)
-# To see the result, run readelf -d core/core_basic_window; looking at the RPATH or RUNPATH attribute.
-# To see which libraries a built example is linking to, ldd core/core_basic_window;
-# Look for libraylib.so.1 => $(RAYLIB_INSTALL_PATH)/libraylib.so.1 or similar listing.
-EXAMPLE_RUNTIME_PATH ?= $(RAYLIB_RELEASE_PATH)
-
-# Define default C compiler: gcc
-# NOTE: define g++ compiler if using C++
-CC = gcc
-
-ifeq ($(PLATFORM),PLATFORM_DESKTOP)
- ifeq ($(PLATFORM_OS),OSX)
- # OSX default compiler
- CC = clang
- endif
- ifeq ($(PLATFORM_OS),BSD)
- # FreeBSD, OpenBSD, NetBSD, DragonFly default compiler
- CC = clang
- 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)
- # HTML5 emscripten compiler
- # WARNING: To compile to HTML5, code must be redesigned
- # to use emscripten.h and emscripten_set_main_loop()
- CC = emcc
-endif
-
-# Define default make program: Mingw32-make
-MAKE = mingw32-make
-
-ifeq ($(PLATFORM),PLATFORM_DESKTOP)
- ifeq ($(PLATFORM_OS),LINUX)
- MAKE = make
- endif
- ifeq ($(PLATFORM_OS),OSX)
- MAKE = make
- endif
-endif
-
-# Define compiler flags:
-# -O1 defines optimization level
-# -g include debug information on compilation
-# -s strip unnecessary data from build
-# -Wall turns on most, but not all, compiler warnings
-# -std=c99 defines C language mode (standard C from 1999 revision)
-# -std=gnu99 defines C language mode (GNU C from 1999 revision)
-# -Wno-missing-braces ignore invalid warning (GCC bug 53119)
-# -D_DEFAULT_SOURCE use with -std=c99 on Linux and PLATFORM_WEB, required for timespec
-CFLAGS += -O1 -s -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces
-
-ifeq ($(BUILD_MODE),DEBUG)
- CFLAGS += -g
-endif
-
-# Additional flags for compiler (if desired)
-#CFLAGS += -Wextra -Wmissing-prototypes -Wstrict-prototypes
-ifeq ($(PLATFORM),PLATFORM_DESKTOP)
- ifeq ($(PLATFORM_OS),WINDOWS)
- # resource file contains windows executable icon and properties
- # -Wl,--subsystem,windows hides the console window
- CFLAGS += $(RAYLIB_PATH)/src/raylib.rc.data -Wl,--subsystem,windows
- endif
- ifeq ($(PLATFORM_OS),LINUX)
- ifeq ($(RAYLIB_LIBTYPE),STATIC)
- CFLAGS += -D_DEFAULT_SOURCE
- endif
- ifeq ($(RAYLIB_LIBTYPE),SHARED)
- # Explicitly enable runtime link to libraylib.so
- CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH)
- endif
- endif
-endif
-ifeq ($(PLATFORM),PLATFORM_RPI)
- CFLAGS += -std=gnu99
-endif
-ifeq ($(PLATFORM),PLATFORM_WEB)
- # -Os # size optimization
- # -O2 # optimization level 2, if used, also set --memory-init-file 0
- # -sUSE_GLFW=3 # Use glfw3 library (context/input management)
- # -sALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL!
- # -sTOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) (67108864 = 64MB)
- # -sUSE_PTHREADS=1 # multithreading support
- # -sWASM=0 # disable Web Assembly, emitted by default
- # -sASYNCIFY # lets synchronous C/C++ code interact with asynchronous JS
- # -sFORCE_FILESYSTEM=1 # force filesystem to load/save files data
- # -sASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off)
- # -sMINIFY_HTML=0 # minify generated html from shell.html
- # --profiling # include information for code profiling
- # --memory-init-file 0 # to avoid an external memory initialization code file (.mem)
- # --preload-file resources # specify a resources folder for data compilation
- # --source-map-base # allow debugging in browser with source map
- # --shell-file shell.html # define a custom shell .html and output extension
- CFLAGS += -Os -sUSE_GLFW=3 -sTOTAL_MEMORY=16777216 --preload-file resources -sMINIFY_HTML=0
- ifeq ($(BUILD_MODE), DEBUG)
- CFLAGS += -sASSERTIONS=1 --profiling
- endif
-
- # Define a custom shell .html and output extension
- CFLAGS += --shell-file $(RAYLIB_PATH)/src/shell.html
- EXT = .html
-endif
-
-# Define include paths for required headers
-# NOTE: Several external required libraries (stb and others)
-INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external
-
-# Define additional directories containing required header files
-ifeq ($(PLATFORM),PLATFORM_RPI)
- # RPI required libraries
- INCLUDE_PATHS += -I/opt/vc/include
- INCLUDE_PATHS += -I/opt/vc/include/interface/vmcs_host/linux
- INCLUDE_PATHS += -I/opt/vc/include/interface/vcos/pthreads
-endif
-ifeq ($(PLATFORM),PLATFORM_DESKTOP)
- ifeq ($(PLATFORM_OS),BSD)
- # Consider -L$(RAYLIB_H_INSTALL_PATH)
- INCLUDE_PATHS += -I/usr/local/include
- endif
- ifeq ($(PLATFORM_OS),LINUX)
- # Reset everything.
- # Precedence: immediately local, installed version, raysan5 provided libs -I$(RAYLIB_H_INSTALL_PATH) -I$(RAYLIB_PATH)/release/include
- INCLUDE_PATHS = -I$(RAYLIB_H_INSTALL_PATH) -isystem. -isystem$(RAYLIB_PATH)/src -isystem$(RAYLIB_PATH)/release/include -isystem$(RAYLIB_PATH)/src/external
- endif
-endif
-
-# Define library paths containing required libs.
-LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src
-
-ifeq ($(PLATFORM),PLATFORM_DESKTOP)
- ifeq ($(PLATFORM_OS),BSD)
- # Consider -L$(RAYLIB_INSTALL_PATH)
- LDFLAGS += -L. -Lsrc -L/usr/local/lib
- endif
- ifeq ($(PLATFORM_OS),LINUX)
- # Reset everything.
- # Precedence: immediately local, installed version, raysan5 provided libs
- LDFLAGS = -L. -L$(RAYLIB_INSTALL_PATH) -L$(RAYLIB_RELEASE_PATH)
- endif
-endif
-
-ifeq ($(PLATFORM),PLATFORM_RPI)
- LDFLAGS += -L/opt/vc/lib
-endif
-
-# Define any libraries required on linking
-# if you want to link libraries (libname.so or libname.a), use the -lname
-ifeq ($(PLATFORM),PLATFORM_DESKTOP)
- ifeq ($(PLATFORM_OS),WINDOWS)
- # Libraries for Windows desktop compilation
- # NOTE: WinMM library required to set high-res timer resolution
- LDLIBS = -lraylib -lopengl32 -lgdi32 -lwinmm
- endif
- ifeq ($(PLATFORM_OS),LINUX)
- # Libraries for Debian GNU/Linux desktop compiling
- # NOTE: Required packages: libegl1-mesa-dev
- LDLIBS = -lraylib -lGL -lm -lpthread -ldl -lrt
-
- # On X11 requires also below libraries
- LDLIBS += -lX11
- # NOTE: It seems additional libraries are not required any more, latest GLFW just dlopen them
- #LDLIBS += -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
-
- # On Wayland windowing system, additional libraries requires
- ifeq ($(USE_WAYLAND_DISPLAY),TRUE)
- LDLIBS += -lwayland-client -lwayland-cursor -lwayland-egl -lxkbcommon
- endif
- # Explicit link to libc
- ifeq ($(RAYLIB_LIBTYPE),SHARED)
- LDLIBS += -lc
- endif
- endif
- ifeq ($(PLATFORM_OS),OSX)
- # Libraries for OSX 10.9 desktop compiling
- # NOTE: Required packages: libopenal-dev libegl1-mesa-dev
- LDLIBS = -lraylib -framework OpenGL -framework OpenAL -framework Cocoa
- endif
- ifeq ($(PLATFORM_OS),BSD)
- # Libraries for FreeBSD, OpenBSD, NetBSD, DragonFly desktop compiling
- # NOTE: Required packages: mesa-libs
- LDLIBS = -lraylib -lGL -lpthread -lm
-
- # On XWindow requires also below libraries
- LDLIBS += -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
- endif
- ifeq ($(USE_EXTERNAL_GLFW),TRUE)
- # NOTE: It could require additional packages installed: libglfw3-dev
- LDLIBS += -lglfw
- 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
-endif
-ifeq ($(PLATFORM),PLATFORM_WEB)
- # Libraries for web (HTML5) compiling
- LDLIBS = $(RAYLIB_RELEASE_PATH)/libraylib.bc
-endif
-
-# Define a recursive wildcard function
-rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d))
-
-# Define all source files required
-SRC_DIR = src
-OBJ_DIR = obj
-
-# Define all object files from source files
-SRC = $(call rwildcard, *.c, *.h)
-#OBJS = $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
-OBJS = main.c
-
-# For Android platform we call a custom Makefile.Android
-ifeq ($(PLATFORM),PLATFORM_ANDROID)
- MAKEFILE_PARAMS = -f Makefile.Android
- export PROJECT_NAME
- export SRC_DIR
-else
- MAKEFILE_PARAMS = $(PROJECT_NAME)
-endif
-
-# Default target entry
-# NOTE: We call this Makefile target or Makefile.Android target
-all:
- $(MAKE) $(MAKEFILE_PARAMS)
-
-# Project target defined by PROJECT_NAME
-$(PROJECT_NAME): $(OBJS)
- $(CC) -o $(PROJECT_NAME)$(EXT) $(OBJS) $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
-
-# Compile source files
-# NOTE: This pattern will compile every module defined on $(OBJS)
-#%.o: %.c
-$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
- $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDE_PATHS) -D$(PLATFORM)
-
-# Clean everything
-clean:
-ifeq ($(PLATFORM),PLATFORM_DESKTOP)
- ifeq ($(PLATFORM_OS),WINDOWS)
- del *.o *.exe /s
- endif
- ifeq ($(PLATFORM_OS),LINUX)
- find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -fv
- endif
- ifeq ($(PLATFORM_OS),OSX)
- find . -type f -perm +ugo+x -delete
- rm -f *.o
- endif
-endif
-ifeq ($(PLATFORM),PLATFORM_RPI)
- find . -type f -executable -delete
- rm -fv *.o
-endif
-ifeq ($(PLATFORM),PLATFORM_WEB)
- del *.o *.html *.js
-endif
- @echo Cleaning done
-
diff --git a/projects/4coder/Makefile.Android b/projects/4coder/Makefile.Android
deleted file mode 100644
index 9e6773651..000000000
--- a/projects/4coder/Makefile.Android
+++ /dev/null
@@ -1,300 +0,0 @@
-#**************************************************************************************************
-#
-# raylib makefile for Android project (APK building)
-#
-# Copyright (c) 2017 Ramon Santamaria (@raysan5)
-#
-# This software is provided "as-is", without any express or implied warranty. In no event
-# will the authors be held liable for any damages arising from the use of this software.
-#
-# Permission is granted to anyone to use this software for any purpose, including commercial
-# applications, and to alter it and redistribute it freely, subject to the following restrictions:
-#
-# 1. The origin of this software must not be misrepresented; you must not claim that you
-# wrote the original software. If you use this software in a product, an acknowledgment
-# in the product documentation would be appreciated but is not required.
-#
-# 2. Altered source versions must be plainly marked as such, and must not be misrepresented
-# as being the original software.
-#
-# 3. This notice may not be removed or altered from any source distribution.
-#
-#**************************************************************************************************
-
-# Define required raylib variables
-PLATFORM ?= PLATFORM_ANDROID
-RAYLIB_PATH ?= ..\..
-
-# Define Android architecture (armeabi-v7a, arm64-v8a, x86, x86-64) and API version
-ANDROID_ARCH ?= ARM
-ANDROID_API_VERSION = 21
-ifeq ($(ANDROID_ARCH),ARM)
- ANDROID_ARCH_NAME = armeabi-v7a
-endif
-ifeq ($(ANDROID_ARCH),ARM64)
- ANDROID_ARCH_NAME = arm64-v8a
-endif
-
-# Required path variables
-# NOTE: JAVA_HOME must be set to JDK
-JAVA_HOME ?= C:/JavaJDK
-ANDROID_HOME = C:/android-sdk
-ANDROID_TOOLCHAIN = C:/android_toolchain_$(ANDROID_ARCH)_API$(ANDROID_API_VERSION)
-ANDROID_BUILD_TOOLS = $(ANDROID_HOME)/build-tools/28.0.1
-ANDROID_PLATFORM_TOOLS = $(ANDROID_HOME)/platform-tools
-
-# Android project configuration variables
-PROJECT_NAME ?= raylib_game
-PROJECT_LIBRARY_NAME ?= main
-PROJECT_BUILD_PATH ?= android.$(PROJECT_NAME)
-PROJECT_RESOURCES_PATH ?= resources
-PROJECT_SOURCE_FILES ?= raylib_game.c
-
-# Some source files are placed in directories, when compiling to some
-# output directory other than source, that directory must pre-exist.
-# Here we get a list of required folders that need to be created on
-# code output folder $(PROJECT_BUILD_PATH)\obj to avoid GCC errors.
-PROJECT_SOURCE_DIRS = $(sort $(dir $(PROJECT_SOURCE_FILES)))
-
-# Android app configuration variables
-APP_LABEL_NAME ?= rGame
-APP_COMPANY_NAME ?= raylib
-APP_PRODUCT_NAME ?= rgame
-APP_VERSION_CODE ?= 1
-APP_VERSION_NAME ?= 1.0
-APP_ICON_LDPI ?= $(RAYLIB_PATH)\logo\raylib_36x36.png
-APP_ICON_MDPI ?= $(RAYLIB_PATH)\logo\raylib_48x48.png
-APP_ICON_HDPI ?= $(RAYLIB_PATH)\logo\raylib_72x72.png
-APP_SCREEN_ORIENTATION ?= landscape
-APP_KEYSTORE_PASS ?= raylib
-
-# Library type used for raylib: STATIC (.a) or SHARED (.so/.dll)
-RAYLIB_LIBTYPE ?= STATIC
-
-# Library path for libraylib.a/libraylib.so
-RAYLIB_LIB_PATH = $(RAYLIB_PATH)\src
-
-# Shared libs must be added to APK if required
-# NOTE: Generated NativeLoader.java automatically load those libraries
-ifeq ($(RAYLIB_LIBTYPE),SHARED)
- PROJECT_SHARED_LIBS = lib/$(ANDROID_ARCH_NAME)/libraylib.so
-endif
-
-# Compiler and archiver
-# NOTE: GCC is being deprecated in Android NDK r16
-ifeq ($(ANDROID_ARCH),ARM)
- CC = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-clang
- AR = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-ar
-endif
-ifeq ($(ANDROID_ARCH),ARM64)
- CC = $(ANDROID_TOOLCHAIN)/bin/aarch64-linux-android-clang
- AR = $(ANDROID_TOOLCHAIN)/bin/aarch64-linux-android-ar
-endif
-
-# Compiler flags for arquitecture
-ifeq ($(ANDROID_ARCH),ARM)
- CFLAGS = -std=c99 -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16
-endif
-ifeq ($(ANDROID_ARCH),ARM64)
- CFLAGS = -std=c99 -mfix-cortex-a53-835769
-endif
-# Compilation functions attributes options
-CFLAGS += -ffunction-sections -funwind-tables -fstack-protector-strong -fPIC
-# Compiler options for the linker
-CFLAGS += -Wall -Wa,--noexecstack -Wformat -Werror=format-security -no-canonical-prefixes
-# Preprocessor macro definitions
-CFLAGS += -DANDROID -DPLATFORM_ANDROID -D__ANDROID_API__=$(ANDROID_API_VERSION)
-
-# Paths containing required header files
-INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external/android/native_app_glue
-
-# Linker options
-LDFLAGS = -Wl,-soname,lib$(PROJECT_LIBRARY_NAME).so -Wl,--exclude-libs,libatomic.a
-LDFLAGS += -Wl,--build-id -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--warn-shared-textrel -Wl,--fatal-warnings
-# Force linking of library module to define symbol
-LDFLAGS += -u ANativeActivity_onCreate
-# Library paths containing required libs
-LDFLAGS += -L. -L$(PROJECT_BUILD_PATH)/obj -L$(PROJECT_BUILD_PATH)/lib/$(ANDROID_ARCH_NAME) -L$(ANDROID_TOOLCHAIN)\sysroot\usr\lib
-
-# Define any libraries to link into executable
-# if you want to link libraries (libname.so or libname.a), use the -lname
-LDLIBS = -lm -lc -lraylib -llog -landroid -lEGL -lGLESv2 -lOpenSLES -ldl
-
-# Generate target objects list from PROJECT_SOURCE_FILES
-OBJS = $(patsubst %.c, $(PROJECT_BUILD_PATH)/obj/%.o, $(PROJECT_SOURCE_FILES))
-
-# Android APK building process... some steps required...
-# NOTE: typing 'make' will invoke the default target entry called 'all',
-all: create_temp_project_dirs \
- copy_project_required_libs \
- copy_project_resources \
- generate_loader_script \
- generate_android_manifest \
- generate_apk_keystore \
- config_project_package \
- compile_project_code \
- compile_project_class \
- compile_project_class_dex \
- create_project_apk_package \
- sign_project_apk_package \
- zipalign_project_apk_package
-
-# Create required temp directories for APK building
-create_temp_project_dirs:
- if not exist $(PROJECT_BUILD_PATH) mkdir $(PROJECT_BUILD_PATH)
- if not exist $(PROJECT_BUILD_PATH)\obj mkdir $(PROJECT_BUILD_PATH)\obj
- if not exist $(PROJECT_BUILD_PATH)\src mkdir $(PROJECT_BUILD_PATH)\src
- if not exist $(PROJECT_BUILD_PATH)\src\com mkdir $(PROJECT_BUILD_PATH)\src\com
- if not exist $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME) mkdir $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME)
- if not exist $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME)\$(APP_PRODUCT_NAME) mkdir $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME)\$(APP_PRODUCT_NAME)
- if not exist $(PROJECT_BUILD_PATH)\lib mkdir $(PROJECT_BUILD_PATH)\lib
- if not exist $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME) mkdir $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME)
- if not exist $(PROJECT_BUILD_PATH)\bin mkdir $(PROJECT_BUILD_PATH)\bin
- if not exist $(PROJECT_BUILD_PATH)\res mkdir $(PROJECT_BUILD_PATH)\res
- if not exist $(PROJECT_BUILD_PATH)\res\drawable-ldpi mkdir $(PROJECT_BUILD_PATH)\res\drawable-ldpi
- if not exist $(PROJECT_BUILD_PATH)\res\drawable-mdpi mkdir $(PROJECT_BUILD_PATH)\res\drawable-mdpi
- if not exist $(PROJECT_BUILD_PATH)\res\drawable-hdpi mkdir $(PROJECT_BUILD_PATH)\res\drawable-hdpi
- if not exist $(PROJECT_BUILD_PATH)\res\values mkdir $(PROJECT_BUILD_PATH)\res\values
- if not exist $(PROJECT_BUILD_PATH)\assets mkdir $(PROJECT_BUILD_PATH)\assets
- if not exist $(PROJECT_BUILD_PATH)\assets\$(PROJECT_RESOURCES_PATH) mkdir $(PROJECT_BUILD_PATH)\assets\$(PROJECT_RESOURCES_PATH)
- if not exist $(PROJECT_BUILD_PATH)\obj\screens mkdir $(PROJECT_BUILD_PATH)\obj\screens
- $(foreach dir, $(PROJECT_SOURCE_DIRS), $(call create_dir, $(dir)))
-
-define create_dir
- if not exist $(PROJECT_BUILD_PATH)\obj\$(1) mkdir $(PROJECT_BUILD_PATH)\obj\$(1)
-endef
-
-# Copy required shared libs for integration into APK
-# NOTE: If using shared libs they are loaded by generated NativeLoader.java
-copy_project_required_libs:
-ifeq ($(RAYLIB_LIBTYPE),SHARED)
- copy /Y $(RAYLIB_LIB_PATH)\libraylib.so $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME)\libraylib.so
-endif
-ifeq ($(RAYLIB_LIBTYPE),STATIC)
- copy /Y $(RAYLIB_LIB_PATH)\libraylib.a $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME)\libraylib.a
-endif
-
-# Copy project required resources: strings.xml, icon.png, assets
-# NOTE: Required strings.xml is generated and game resources are copied to assets folder
-# TODO: Review xcopy usage, it can not be found in some systems!
-copy_project_resources:
- copy $(APP_ICON_LDPI) $(PROJECT_BUILD_PATH)\res\drawable-ldpi\icon.png /Y
- copy $(APP_ICON_MDPI) $(PROJECT_BUILD_PATH)\res\drawable-mdpi\icon.png /Y
- copy $(APP_ICON_HDPI) $(PROJECT_BUILD_PATH)\res\drawable-hdpi\icon.png /Y
- @echo ^ > $(PROJECT_BUILD_PATH)/res/values/strings.xml
- @echo ^^$(APP_LABEL_NAME)^^ >> $(PROJECT_BUILD_PATH)/res/values/strings.xml
- if exist $(PROJECT_RESOURCES_PATH) C:\Windows\System32\xcopy $(PROJECT_RESOURCES_PATH) $(PROJECT_BUILD_PATH)\assets\$(PROJECT_RESOURCES_PATH) /Y /E /F
-
-# Generate NativeLoader.java to load required shared libraries
-# NOTE: Probably not the bet way to generate this file... but it works.
-generate_loader_script:
- @echo package com.$(APP_COMPANY_NAME).$(APP_PRODUCT_NAME); > $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
- @echo. >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
- @echo public class NativeLoader extends android.app.NativeActivity { >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
- @echo static { >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
-ifeq ($(RAYLIB_LIBTYPE),SHARED)
- @echo System.loadLibrary("raylib"); >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
-endif
- @echo System.loadLibrary("$(PROJECT_LIBRARY_NAME)"); >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
- @echo } >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
- @echo } >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
-
-# Generate AndroidManifest.xml with all the required options
-# NOTE: Probably not the bet way to generate this file... but it works.
-generate_android_manifest:
- @echo ^ > $(PROJECT_BUILD_PATH)/AndroidManifest.xml
- @echo ^> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
- @echo package="com.$(APP_COMPANY_NAME).$(APP_PRODUCT_NAME)" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
- @echo android:versionCode="$(APP_VERSION_CODE)" android:versionName="$(APP_VERSION_NAME)" ^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
- @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
- @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
- @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
- @echo ^> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
- @echo android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
- @echo android:configChanges="orientation|keyboardHidden|screenSize" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
- @echo android:screenOrientation="$(APP_SCREEN_ORIENTATION)" android:launchMode="singleTask" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
- @echo android:clearTaskOnLaunch="true"^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
- @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
- @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
- @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
- @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
- @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
- @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
- @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
- @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
-
-# Generate storekey for APK signing: $(PROJECT_NAME).keystore
-# NOTE: Configure here your Distinguished Names (-dname) if required!
-generate_apk_keystore:
- if not exist $(PROJECT_BUILD_PATH)/$(PROJECT_NAME).keystore $(JAVA_HOME)/bin/keytool -genkeypair -validity 1000 -dname "CN=$(APP_COMPANY_NAME),O=Android,C=ES" -keystore $(PROJECT_BUILD_PATH)/$(PROJECT_NAME).keystore -storepass $(APP_KEYSTORE_PASS) -keypass $(APP_KEYSTORE_PASS) -alias $(PROJECT_NAME)Key -keyalg RSA
-
-# Config project package and resource using AndroidManifest.xml and res/values/strings.xml
-# NOTE: Generates resources file: src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java
-config_project_package:
- $(ANDROID_BUILD_TOOLS)/aapt package -f -m -S $(PROJECT_BUILD_PATH)/res -J $(PROJECT_BUILD_PATH)/src -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -I $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar
-
-# Compile native_app_glue code as static library: obj/libnative_app_glue.a
-compile_native_app_glue:
- $(CC) -c $(RAYLIB_PATH)/src/external/android/native_app_glue/android_native_app_glue.c -o $(PROJECT_BUILD_PATH)/obj/native_app_glue.o $(CFLAGS)
- $(AR) rcs $(PROJECT_BUILD_PATH)/obj/libnative_app_glue.a $(PROJECT_BUILD_PATH)/obj/native_app_glue.o
-
-# Compile project code into a shared library: lib/lib$(PROJECT_LIBRARY_NAME).so
-compile_project_code: $(OBJS)
- $(CC) -o $(PROJECT_BUILD_PATH)/lib/$(ANDROID_ARCH_NAME)/lib$(PROJECT_LIBRARY_NAME).so $(OBJS) -shared $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS)
-
-# Compile all .c files required into object (.o) files
-# NOTE: Those files will be linked into a shared library
-$(PROJECT_BUILD_PATH)/obj/%.o:%.c
- $(CC) -c $^ -o $@ $(INCLUDE_PATHS) $(CFLAGS) --sysroot=$(ANDROID_TOOLCHAIN)/sysroot
-
-# Compile project .java code into .class (Java bytecode)
-compile_project_class:
- $(JAVA_HOME)/bin/javac -verbose -source 1.7 -target 1.7 -d $(PROJECT_BUILD_PATH)/obj -bootclasspath $(JAVA_HOME)/jre/lib/rt.jar -classpath $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar;$(PROJECT_BUILD_PATH)/obj -sourcepath $(PROJECT_BUILD_PATH)/src $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
-
-# Compile .class files into Dalvik executable bytecode (.dex)
-# NOTE: Since Android 5.0, Dalvik interpreter (JIT) has been replaced by ART (AOT)
-compile_project_class_dex:
- $(ANDROID_BUILD_TOOLS)/dx --verbose --dex --output=$(PROJECT_BUILD_PATH)/bin/classes.dex $(PROJECT_BUILD_PATH)/obj
-
-# Create Android APK package: bin/$(PROJECT_NAME).unsigned.apk
-# NOTE: Requires compiled classes.dex and lib$(PROJECT_LIBRARY_NAME).so
-# NOTE: Use -A resources to define additional directory in which to find raw asset files
-create_project_apk_package:
- $(ANDROID_BUILD_TOOLS)/aapt package -f -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -S $(PROJECT_BUILD_PATH)/res -A $(PROJECT_BUILD_PATH)/assets -I $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar -F $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).unsigned.apk $(PROJECT_BUILD_PATH)/bin
- cd $(PROJECT_BUILD_PATH) && $(ANDROID_BUILD_TOOLS)/aapt add bin/$(PROJECT_NAME).unsigned.apk lib/$(ANDROID_ARCH_NAME)/lib$(PROJECT_LIBRARY_NAME).so $(PROJECT_SHARED_LIBS)
-
-# Create signed APK package using generated Key: bin/$(PROJECT_NAME).signed.apk
-sign_project_apk_package:
- $(JAVA_HOME)/bin/jarsigner -keystore $(PROJECT_BUILD_PATH)/$(PROJECT_NAME).keystore -storepass $(APP_KEYSTORE_PASS) -keypass $(APP_KEYSTORE_PASS) -signedjar $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).signed.apk $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).unsigned.apk $(PROJECT_NAME)Key
-
-# Create zip-aligned APK package: $(PROJECT_NAME).apk
-zipalign_project_apk_package:
- $(ANDROID_BUILD_TOOLS)/zipalign -f 4 $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).signed.apk $(PROJECT_NAME).apk
-
-# Install $(PROJECT_NAME).apk to default emulator/device
-# NOTE: Use -e (emulator) or -d (device) parameters if required
-install:
- $(ANDROID_PLATFORM_TOOLS)/adb install --abi $(ANDROID_ARCH_NAME) -rds $(PROJECT_NAME).apk
-
-# Check supported ABI for the device (armeabi-v7a, arm64-v8a, x86, x86_64)
-check_device_abi:
- $(ANDROID_PLATFORM_TOOLS)/adb shell getprop ro.product.cpu.abi
-
-# Monitorize output log coming from device, only raylib tag
-logcat:
- $(ANDROID_PLATFORM_TOOLS)/adb logcat -c
- $(ANDROID_PLATFORM_TOOLS)/adb logcat raylib:V *:S
-
-# Install and monitorize $(PROJECT_NAME).apk to default emulator/device
-deploy:
- $(ANDROID_PLATFORM_TOOLS)/adb install -r $(PROJECT_NAME).apk
- $(ANDROID_PLATFORM_TOOLS)/adb logcat -c
- $(ANDROID_PLATFORM_TOOLS)/adb logcat raylib:V *:S
-
-#$(ANDROID_PLATFORM_TOOLS)/adb logcat *:W
-
-# Clean everything
-clean:
- del $(PROJECT_BUILD_PATH)\* /f /s /q
- rmdir $(PROJECT_BUILD_PATH) /s /q
- @echo Cleaning done
diff --git a/projects/4coder/main.c b/projects/4coder/main.c
deleted file mode 100644
index 78e1519cb..000000000
--- a/projects/4coder/main.c
+++ /dev/null
@@ -1,40 +0,0 @@
-#include
-#include "raylib.h"
-
-int main()
-{
- int screenWidth = 800;
- int screenHeight = 450;
-
- InitWindow(screenWidth, screenHeight, "raylib");
-
- Camera cam;
- cam.position = (Vector3){ 0.0f, 10.0f, 8.f };
- cam.target = (Vector3){ 0.0f, 0.0f, 0.0f };
- cam.up = (Vector3){ 0.0f, 1.f, 0.0f };
- cam.fovy = 60.0f;
-
- Vector3 cubePos = { 0.0f, 0.0f, 0.0f };
-
- SetTargetFPS(60);
-
- while (!WindowShouldClose())
- {
- cam.position.x = sin(GetTime())*10.0f;
- cam.position.z = cos(GetTime())*10.0f;
-
- BeginDrawing();
- ClearBackground(RAYWHITE);
- BeginMode3D(cam);
- DrawCube(cubePos, 2.f, 2.f, 2.f, RED);
- DrawCubeWires(cubePos, 2.f, 2.f, 2.f, MAROON);
- DrawGrid(10, 1.f);
- EndMode3D();
- DrawText("This is a raylib example", 10, 40, 20, DARKGRAY);
- DrawFPS(10, 10);
- EndDrawing();
- }
-
- CloseWindow();
- return 0;
-}
diff --git a/projects/4coder/project.4coder b/projects/4coder/project.4coder
deleted file mode 100644
index 568de79bd..000000000
--- a/projects/4coder/project.4coder
+++ /dev/null
@@ -1,54 +0,0 @@
-version(1);
-
-project_name = "raylib-example";
-
-patterns = {
-"*.cpp",
-"*.c",
-"*.h",
-"*.bat",
-"*.sh",
-"*.4coder",
-"Makefile",
-};
-
-blacklist_patterns = {
-".*",
-};
-
-load_paths = {
- { { {".", .relative = true, .recursive = true, } }, .os = "win" },
- { { {".", .relative = true, .recursive = true, } }, .os = "linux" },
- { { {".", .relative = true, .recursive = true, } }, .os = "mac" },
-};
-
-command_list = {
- { .name = "clean",
- .out = "*clean*", .footer_panel = true, .save_dirty_files = false, .cursor_at_end = true,
- .cmd = {
- {"mingw32-make clean", .os = "win"},
- {"make clean", .os = "linux"},
- {"make clean", .os = "mac"},
- },
- },
- { .name = "build",
- .out = "*compile*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false,
- .cmd = {
- {"mingw32-make", .os = "win"},
- {"make", .os = "linux"},
- {"make", .os = "mac"},
- },
- },
- { .name = "run",
- .out = "*run*", .footer_panel = true, .save_dirty_files = false, .cursor_at_end = true,
- .cmd = {
- {".\game.exe", .os = "win"},
- {"./game", .os = "linux"},
- {"./game", .os = "mac"},
- },
- },
-};
-
-fkey_command[3] = "clean";
-fkey_command[4] = "build";
-fkey_command[5] = "run";
diff --git a/projects/README.md b/projects/README.md
index 2758cb86e..b1f48cdf2 100644
--- a/projects/README.md
+++ b/projects/README.md
@@ -4,15 +4,14 @@ This folder contains raylib templates for some common IDEs.
IDE | Platform(s) | Source | Example(s)
----| ------------| :-------: | :-----:
-[4coder](http://4coder.net/) | Windows | ❌ | ✔️
[Builder](https://wiki.gnome.org/Apps/Builder) | Linux | ❌ | ✔️
[CMake](https://cmake.org/) | Windows, Linux, macOS, Web | ✔️ | ✔️
[CodeBlocks](http://www.codeblocks.org/) | Windows, Linux, macOS | ❌ | ✔️
[Geany](https://www.geany.org/) | Windows, Linux | ✔️ | ✔️
-[Notepad++](https://notepad-plus-plus.org/) | Windows | ✔️ | ✔️
+[Notepad++](https://notepad-plus-plus.org/) | Windows, Web | ✔️ | ✔️
[SublimeText](https://www.sublimetext.com/) | Windows, Linux, macOS | ✔️ | ✔️
-[VS2019](https://www.visualstudio.com) | Windows | ✔️ | ✔️
-[VSCode](https://code.visualstudio.com/) | Windows, macOS | ❌ | ✔️
+[VS2022](https://www.visualstudio.com) | Windows | ✔️ | ✔️
+[VSCode](https://code.visualstudio.com/) | Windows, Linux, macOS | ❌ | ✔️
[Zig](https://ziglang.org) | Windows, Linux, macOS, Web | ✔️ | ✔️
scripts | Windows, Linux, macOS | ✔️ | ✔️
diff --git a/projects/VS2019-Android/raylib_android.sln b/projects/VS2019-Android/raylib_android.sln
deleted file mode 100644
index ec1880c0e..000000000
--- a/projects/VS2019-Android/raylib_android.sln
+++ /dev/null
@@ -1,75 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.31702.278
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "raylib_android", "raylib_android", "{5C24BC76-8848-40EA-9BBB-A544648D8D5B}"
-EndProject
-Project("{39E2626F-3545-4960-A6E8-258AD8476CE5}") = "raylib_android.Packaging", "raylib_android\raylib_android.Packaging\raylib_android.Packaging.androidproj", "{B2231F0D-52DA-4C55-8998-5886F766553C}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "raylib_android.NativeActivity", "raylib_android\raylib_android.NativeActivity\raylib_android.NativeActivity.vcxproj", "{BFB31759-4FCA-4503-BC7C-A97F705EFDB2}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|ARM = Debug|ARM
- Debug|ARM64 = Debug|ARM64
- Debug|x64 = Debug|x64
- Debug|x86 = Debug|x86
- Release|ARM = Release|ARM
- Release|ARM64 = Release|ARM64
- Release|x64 = Release|x64
- Release|x86 = Release|x86
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {B2231F0D-52DA-4C55-8998-5886F766553C}.Debug|ARM.ActiveCfg = Debug|ARM
- {B2231F0D-52DA-4C55-8998-5886F766553C}.Debug|ARM.Build.0 = Debug|ARM
- {B2231F0D-52DA-4C55-8998-5886F766553C}.Debug|ARM.Deploy.0 = Debug|ARM
- {B2231F0D-52DA-4C55-8998-5886F766553C}.Debug|ARM64.ActiveCfg = Debug|ARM64
- {B2231F0D-52DA-4C55-8998-5886F766553C}.Debug|ARM64.Build.0 = Debug|ARM64
- {B2231F0D-52DA-4C55-8998-5886F766553C}.Debug|ARM64.Deploy.0 = Debug|ARM64
- {B2231F0D-52DA-4C55-8998-5886F766553C}.Debug|x64.ActiveCfg = Debug|x64
- {B2231F0D-52DA-4C55-8998-5886F766553C}.Debug|x64.Build.0 = Debug|x64
- {B2231F0D-52DA-4C55-8998-5886F766553C}.Debug|x64.Deploy.0 = Debug|x64
- {B2231F0D-52DA-4C55-8998-5886F766553C}.Debug|x86.ActiveCfg = Debug|x86
- {B2231F0D-52DA-4C55-8998-5886F766553C}.Debug|x86.Build.0 = Debug|x86
- {B2231F0D-52DA-4C55-8998-5886F766553C}.Debug|x86.Deploy.0 = Debug|x86
- {B2231F0D-52DA-4C55-8998-5886F766553C}.Release|ARM.ActiveCfg = Release|ARM
- {B2231F0D-52DA-4C55-8998-5886F766553C}.Release|ARM.Build.0 = Release|ARM
- {B2231F0D-52DA-4C55-8998-5886F766553C}.Release|ARM.Deploy.0 = Release|ARM
- {B2231F0D-52DA-4C55-8998-5886F766553C}.Release|ARM64.ActiveCfg = Release|ARM64
- {B2231F0D-52DA-4C55-8998-5886F766553C}.Release|ARM64.Build.0 = Release|ARM64
- {B2231F0D-52DA-4C55-8998-5886F766553C}.Release|ARM64.Deploy.0 = Release|ARM64
- {B2231F0D-52DA-4C55-8998-5886F766553C}.Release|x64.ActiveCfg = Release|x64
- {B2231F0D-52DA-4C55-8998-5886F766553C}.Release|x64.Build.0 = Release|x64
- {B2231F0D-52DA-4C55-8998-5886F766553C}.Release|x64.Deploy.0 = Release|x64
- {B2231F0D-52DA-4C55-8998-5886F766553C}.Release|x86.ActiveCfg = Release|x86
- {B2231F0D-52DA-4C55-8998-5886F766553C}.Release|x86.Build.0 = Release|x86
- {B2231F0D-52DA-4C55-8998-5886F766553C}.Release|x86.Deploy.0 = Release|x86
- {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Debug|ARM.ActiveCfg = Debug|ARM
- {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Debug|ARM.Build.0 = Debug|ARM
- {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Debug|ARM64.ActiveCfg = Debug|ARM64
- {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Debug|ARM64.Build.0 = Debug|ARM64
- {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Debug|x64.ActiveCfg = Debug|x64
- {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Debug|x64.Build.0 = Debug|x64
- {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Debug|x86.ActiveCfg = Debug|x86
- {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Debug|x86.Build.0 = Debug|x86
- {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Release|ARM.ActiveCfg = Release|ARM
- {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Release|ARM.Build.0 = Release|ARM
- {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Release|ARM64.ActiveCfg = Release|ARM64
- {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Release|ARM64.Build.0 = Release|ARM64
- {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Release|x64.ActiveCfg = Release|x64
- {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Release|x64.Build.0 = Release|x64
- {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Release|x86.ActiveCfg = Release|x86
- {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Release|x86.Build.0 = Release|x86
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(NestedProjects) = preSolution
- {B2231F0D-52DA-4C55-8998-5886F766553C} = {5C24BC76-8848-40EA-9BBB-A544648D8D5B}
- {BFB31759-4FCA-4503-BC7C-A97F705EFDB2} = {5C24BC76-8848-40EA-9BBB-A544648D8D5B}
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {B7ED0AA6-6B00-40AC-BF71-526D5BEEFC78}
- EndGlobalSection
-EndGlobal
diff --git a/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/android_native_app_glue.c b/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/android_native_app_glue.c
deleted file mode 100644
index 0b8379423..000000000
--- a/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/android_native_app_glue.c
+++ /dev/null
@@ -1,437 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * лицензировано по лицензии Apache License, версия 2.0 ( "Лицензия");
- *этот файл можно использовать только в соответствии с лицензией.
- *Копию лицензии можно получить на веб-сайте
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- *Если только не требуется в соответствии с применимым законодательством или согласовано в письменном виде, программное обеспечение
- * распространяется в рамках лицензии на УСЛОВИЯХ "КАК ЕСТЬ",
- * БЕЗ ГАРАНТИЙ И УСЛОВИЙ ЛЮБОГО РОДА, явно выраженных и подразумеваемых.
- * См. лицензию для получения информации об определенных разрешениях по использованию языка и
- * ограничениях в рамках лицензии.
- *
- */
-
-#include
-
-#include
-#include
-#include
-#include
-#include
-
-#include "android_native_app_glue.h"
-#include
-
-#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "threaded_app", __VA_ARGS__))
-#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "threaded_app", __VA_ARGS__))
-
-/* Для отладочных построений необходимо всегда включать трассировку отладки в этой библиотеке*/
-#ifndef NDEBUG
-# define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, "threaded_app", __VA_ARGS__))
-#else
-# define LOGV(...) ((void)0)
-#endif
-
-static void free_saved_state(struct android_app* android_app) {
- pthread_mutex_lock(&android_app->mutex);
- if (android_app->savedState != NULL) {
- free(android_app->savedState);
- android_app->savedState = NULL;
- android_app->savedStateSize = 0;
- }
- pthread_mutex_unlock(&android_app->mutex);
-}
-
-int8_t android_app_read_cmd(struct android_app* android_app) {
- int8_t cmd;
- if (read(android_app->msgread, &cmd, sizeof(cmd)) == sizeof(cmd)) {
- switch (cmd) {
- case APP_CMD_SAVE_STATE:
- free_saved_state(android_app);
- break;
- }
- return cmd;
- } else {
- LOGE("No data on command pipe!");
- }
- return -1;
-}
-
-static void print_cur_config(struct android_app* android_app) {
- char lang[2], country[2];
- AConfiguration_getLanguage(android_app->config, lang);
- AConfiguration_getCountry(android_app->config, country);
-
- LOGV("Config: mcc=%d mnc=%d lang=%c%c cnt=%c%c orien=%d touch=%d dens=%d "
- "keys=%d nav=%d keysHid=%d navHid=%d sdk=%d size=%d long=%d "
- "modetype=%d modenight=%d",
- AConfiguration_getMcc(android_app->config),
- AConfiguration_getMnc(android_app->config),
- lang[0], lang[1], country[0], country[1],
- AConfiguration_getOrientation(android_app->config),
- AConfiguration_getTouchscreen(android_app->config),
- AConfiguration_getDensity(android_app->config),
- AConfiguration_getKeyboard(android_app->config),
- AConfiguration_getNavigation(android_app->config),
- AConfiguration_getKeysHidden(android_app->config),
- AConfiguration_getNavHidden(android_app->config),
- AConfiguration_getSdkVersion(android_app->config),
- AConfiguration_getScreenSize(android_app->config),
- AConfiguration_getScreenLong(android_app->config),
- AConfiguration_getUiModeType(android_app->config),
- AConfiguration_getUiModeNight(android_app->config));
-}
-
-void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) {
- switch (cmd) {
- case APP_CMD_INPUT_CHANGED:
- LOGV("APP_CMD_INPUT_CHANGED\n");
- pthread_mutex_lock(&android_app->mutex);
- if (android_app->inputQueue != NULL) {
- AInputQueue_detachLooper(android_app->inputQueue);
- }
- android_app->inputQueue = android_app->pendingInputQueue;
- if (android_app->inputQueue != NULL) {
- LOGV("Attaching input queue to looper");
- AInputQueue_attachLooper(android_app->inputQueue,
- android_app->looper, LOOPER_ID_INPUT, NULL,
- &android_app->inputPollSource);
- }
- pthread_cond_broadcast(&android_app->cond);
- pthread_mutex_unlock(&android_app->mutex);
- break;
-
- case APP_CMD_INIT_WINDOW:
- LOGV("APP_CMD_INIT_WINDOW\n");
- pthread_mutex_lock(&android_app->mutex);
- android_app->window = android_app->pendingWindow;
- pthread_cond_broadcast(&android_app->cond);
- pthread_mutex_unlock(&android_app->mutex);
- break;
-
- case APP_CMD_TERM_WINDOW:
- LOGV("APP_CMD_TERM_WINDOW\n");
- pthread_cond_broadcast(&android_app->cond);
- break;
-
- case APP_CMD_RESUME:
- case APP_CMD_START:
- case APP_CMD_PAUSE:
- case APP_CMD_STOP:
- LOGV("activityState=%d\n", cmd);
- pthread_mutex_lock(&android_app->mutex);
- android_app->activityState = cmd;
- pthread_cond_broadcast(&android_app->cond);
- pthread_mutex_unlock(&android_app->mutex);
- break;
-
- case APP_CMD_CONFIG_CHANGED:
- LOGV("APP_CMD_CONFIG_CHANGED\n");
- AConfiguration_fromAssetManager(android_app->config,
- android_app->activity->assetManager);
- print_cur_config(android_app);
- break;
-
- case APP_CMD_DESTROY:
- LOGV("APP_CMD_DESTROY\n");
- android_app->destroyRequested = 1;
- break;
- }
-}
-
-void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd) {
- switch (cmd) {
- case APP_CMD_TERM_WINDOW:
- LOGV("APP_CMD_TERM_WINDOW\n");
- pthread_mutex_lock(&android_app->mutex);
- android_app->window = NULL;
- pthread_cond_broadcast(&android_app->cond);
- pthread_mutex_unlock(&android_app->mutex);
- break;
-
- case APP_CMD_SAVE_STATE:
- LOGV("APP_CMD_SAVE_STATE\n");
- pthread_mutex_lock(&android_app->mutex);
- android_app->stateSaved = 1;
- pthread_cond_broadcast(&android_app->cond);
- pthread_mutex_unlock(&android_app->mutex);
- break;
-
- case APP_CMD_RESUME:
- free_saved_state(android_app);
- break;
- }
-}
-
-static void android_app_destroy(struct android_app* android_app) {
- LOGV("android_app_destroy!");
- free_saved_state(android_app);
- pthread_mutex_lock(&android_app->mutex);
- if (android_app->inputQueue != NULL) {
- AInputQueue_detachLooper(android_app->inputQueue);
- }
- AConfiguration_delete(android_app->config);
- android_app->destroyed = 1;
- pthread_cond_broadcast(&android_app->cond);
- pthread_mutex_unlock(&android_app->mutex);
- // После этого нельзя изменять объект android_app.
-}
-
-static void process_input(struct android_app* app, struct android_poll_source* source) {
- AInputEvent* event = NULL;
- while (AInputQueue_getEvent(app->inputQueue, &event) >= 0) {
- LOGV("New input event: type=%d\n", AInputEvent_getType(event));
- if (AInputQueue_preDispatchEvent(app->inputQueue, event)) {
- continue;
- }
- int32_t handled = 0;
- if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event);
- AInputQueue_finishEvent(app->inputQueue, event, handled);
- }
-}
-
-static void process_cmd(struct android_app* app, struct android_poll_source* source) {
- int8_t cmd = android_app_read_cmd(app);
- android_app_pre_exec_cmd(app, cmd);
- if (app->onAppCmd != NULL) app->onAppCmd(app, cmd);
- android_app_post_exec_cmd(app, cmd);
-}
-
-static void* android_app_entry(void* param) {
- struct android_app* android_app = (struct android_app*)param;
-
- android_app->config = AConfiguration_new();
- AConfiguration_fromAssetManager(android_app->config, android_app->activity->assetManager);
-
- print_cur_config(android_app);
-
- android_app->cmdPollSource.id = LOOPER_ID_MAIN;
- android_app->cmdPollSource.app = android_app;
- android_app->cmdPollSource.process = process_cmd;
- android_app->inputPollSource.id = LOOPER_ID_INPUT;
- android_app->inputPollSource.app = android_app;
- android_app->inputPollSource.process = process_input;
-
- ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
- ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL,
- &android_app->cmdPollSource);
- android_app->looper = looper;
-
- pthread_mutex_lock(&android_app->mutex);
- android_app->running = 1;
- pthread_cond_broadcast(&android_app->cond);
- pthread_mutex_unlock(&android_app->mutex);
-
- android_main(android_app);
-
- android_app_destroy(android_app);
- return NULL;
-}
-
-// --------------------------------------------------------------------
-// Взаимодействие NativeАctivity (вызванное из основного потока)
-// --------------------------------------------------------------------
-
-static struct android_app* android_app_create(ANativeActivity* activity,
- void* savedState, size_t savedStateSize) {
- struct android_app* android_app = (struct android_app*)malloc(sizeof(struct android_app));
- memset(android_app, 0, sizeof(struct android_app));
- android_app->activity = activity;
-
- pthread_mutex_init(&android_app->mutex, NULL);
- pthread_cond_init(&android_app->cond, NULL);
-
- if (savedState != NULL) {
- android_app->savedState = malloc(savedStateSize);
- android_app->savedStateSize = savedStateSize;
- memcpy(android_app->savedState, savedState, savedStateSize);
- }
-
- int msgpipe[2];
- if (pipe(msgpipe)) {
- LOGE("could not create pipe: %s", strerror(errno));
- return NULL;
- }
- android_app->msgread = msgpipe[0];
- android_app->msgwrite = msgpipe[1];
-
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- pthread_create(&android_app->thread, &attr, android_app_entry, android_app);
-
- // Дождитесь запуска потока.
- pthread_mutex_lock(&android_app->mutex);
- while (!android_app->running) {
- pthread_cond_wait(&android_app->cond, &android_app->mutex);
- }
- pthread_mutex_unlock(&android_app->mutex);
-
- return android_app;
-}
-
-static void android_app_write_cmd(struct android_app* android_app, int8_t cmd) {
- if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) {
- LOGE("Failure writing android_app cmd: %s\n", strerror(errno));
- }
-}
-
-static void android_app_set_input(struct android_app* android_app, AInputQueue* inputQueue) {
- pthread_mutex_lock(&android_app->mutex);
- android_app->pendingInputQueue = inputQueue;
- android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED);
- while (android_app->inputQueue != android_app->pendingInputQueue) {
- pthread_cond_wait(&android_app->cond, &android_app->mutex);
- }
- pthread_mutex_unlock(&android_app->mutex);
-}
-
-static void android_app_set_window(struct android_app* android_app, ANativeWindow* window) {
- pthread_mutex_lock(&android_app->mutex);
- if (android_app->pendingWindow != NULL) {
- android_app_write_cmd(android_app, APP_CMD_TERM_WINDOW);
- }
- android_app->pendingWindow = window;
- if (window != NULL) {
- android_app_write_cmd(android_app, APP_CMD_INIT_WINDOW);
- }
- while (android_app->window != android_app->pendingWindow) {
- pthread_cond_wait(&android_app->cond, &android_app->mutex);
- }
- pthread_mutex_unlock(&android_app->mutex);
-}
-
-static void android_app_set_activity_state(struct android_app* android_app, int8_t cmd) {
- pthread_mutex_lock(&android_app->mutex);
- android_app_write_cmd(android_app, cmd);
- while (android_app->activityState != cmd) {
- pthread_cond_wait(&android_app->cond, &android_app->mutex);
- }
- pthread_mutex_unlock(&android_app->mutex);
-}
-
-static void android_app_free(struct android_app* android_app) {
- pthread_mutex_lock(&android_app->mutex);
- android_app_write_cmd(android_app, APP_CMD_DESTROY);
- while (!android_app->destroyed) {
- pthread_cond_wait(&android_app->cond, &android_app->mutex);
- }
- pthread_mutex_unlock(&android_app->mutex);
-
- close(android_app->msgread);
- close(android_app->msgwrite);
- pthread_cond_destroy(&android_app->cond);
- pthread_mutex_destroy(&android_app->mutex);
- free(android_app);
-}
-
-static void onDestroy(ANativeActivity* activity) {
- LOGV("Destroy: %p\n", activity);
- android_app_free((struct android_app*)activity->instance);
-}
-
-static void onStart(ANativeActivity* activity) {
- LOGV("Start: %p\n", activity);
- android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_START);
-}
-
-static void onResume(ANativeActivity* activity) {
- LOGV("Resume: %p\n", activity);
- android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_RESUME);
-}
-
-static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) {
- struct android_app* android_app = (struct android_app*)activity->instance;
- void* savedState = NULL;
-
- LOGV("SaveInstanceState: %p\n", activity);
- pthread_mutex_lock(&android_app->mutex);
- android_app->stateSaved = 0;
- android_app_write_cmd(android_app, APP_CMD_SAVE_STATE);
- while (!android_app->stateSaved) {
- pthread_cond_wait(&android_app->cond, &android_app->mutex);
- }
-
- if (android_app->savedState != NULL) {
- savedState = android_app->savedState;
- *outLen = android_app->savedStateSize;
- android_app->savedState = NULL;
- android_app->savedStateSize = 0;
- }
-
- pthread_mutex_unlock(&android_app->mutex);
-
- return savedState;
-}
-
-static void onPause(ANativeActivity* activity) {
- LOGV("Pause: %p\n", activity);
- android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_PAUSE);
-}
-
-static void onStop(ANativeActivity* activity) {
- LOGV("Stop: %p\n", activity);
- android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_STOP);
-}
-
-static void onConfigurationChanged(ANativeActivity* activity) {
- struct android_app* android_app = (struct android_app*)activity->instance;
- LOGV("ConfigurationChanged: %p\n", activity);
- android_app_write_cmd(android_app, APP_CMD_CONFIG_CHANGED);
-}
-
-static void onLowMemory(ANativeActivity* activity) {
- struct android_app* android_app = (struct android_app*)activity->instance;
- LOGV("LowMemory: %p\n", activity);
- android_app_write_cmd(android_app, APP_CMD_LOW_MEMORY);
-}
-
-static void onWindowFocusChanged(ANativeActivity* activity, int focused) {
- LOGV("WindowFocusChanged: %p -- %d\n", activity, focused);
- android_app_write_cmd((struct android_app*)activity->instance,
- focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS);
-}
-
-static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) {
- LOGV("NativeWindowCreated: %p -- %p\n", activity, window);
- android_app_set_window((struct android_app*)activity->instance, window);
-}
-
-static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) {
- LOGV("NativeWindowDestroyed: %p -- %p\n", activity, window);
- android_app_set_window((struct android_app*)activity->instance, NULL);
-}
-
-static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) {
- LOGV("InputQueueCreated: %p -- %p\n", activity, queue);
- android_app_set_input((struct android_app*)activity->instance, queue);
-}
-
-static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) {
- LOGV("InputQueueDestroyed: %p -- %p\n", activity, queue);
- android_app_set_input((struct android_app*)activity->instance, NULL);
-}
-
-void ANativeActivity_onCreate(ANativeActivity* activity,
- void* savedState, size_t savedStateSize) {
- LOGV("Creating: %p\n", activity);
- activity->callbacks->onDestroy = onDestroy;
- activity->callbacks->onStart = onStart;
- activity->callbacks->onResume = onResume;
- activity->callbacks->onSaveInstanceState = onSaveInstanceState;
- activity->callbacks->onPause = onPause;
- activity->callbacks->onStop = onStop;
- activity->callbacks->onConfigurationChanged = onConfigurationChanged;
- activity->callbacks->onLowMemory = onLowMemory;
- activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;
- activity->callbacks->onNativeWindowCreated = onNativeWindowCreated;
- activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;
- activity->callbacks->onInputQueueCreated = onInputQueueCreated;
- activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;
-
- activity->instance = android_app_create(activity, savedState, savedStateSize);
-}
diff --git a/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/android_native_app_glue.h b/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/android_native_app_glue.h
deleted file mode 100644
index c7269a444..000000000
--- a/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/android_native_app_glue.h
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- * © 2010 The Android Open Source Project
- *
- * Лицензировано по лицензии Apache License, версия 2.0 ( "Лицензия");
- *этот файл можно использовать только в соответствии с лицензией.
- *Копию лицензии можно получить на веб-сайте
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- *Если только не требуется в соответствии с применимым законодательством или согласовано в письменном виде, программное обеспечение
- * распространяется в рамках лицензии на УСЛОВИЯХ "КАК ЕСТЬ",
- * БЕЗ ГАРАНТИЙ И УСЛОВИЙ ЛЮБОГО РОДА, явно выраженных и подразумеваемых.
- * См. лицензию для получения информации об определенных разрешениях по использованию языка и
- * ограничениях в рамках лицензии.
- *
- */
-
-#ifndef _ANDROID_NATIVE_APP_GLUE_H
-#define _ANDROID_NATIVE_APP_GLUE_H
-
-#include
-#include
-#include
-
-#include
-#include
-#include
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Интерфейс NativeActivity, предоставленный ,
- * основан на наборе предоставленных приложением обратных вызовов, которые вызываются
- *основным потоком действия при возникновении определенных событий.
- *
- * Это означает, что ни один из данных обратных вызовов _не_ _должен_ блокироваться, иначе
- * существует риск принудительного закрытия приложения системой. Эта модель программирования
- * прямая, простая, но имеет ограничения.
- *
- * Статическая библиотека threaded_native_app используется для обеспечения другой
- * модели выполнения, в которой приложение может реализовать свой собственный цикл главного события
- * в другом потоке вместо этого. Это работает так:
- *
- * 1/ Приложение должно предоставить функцию с именем android_main(), которая
- * будет вызываться при создании действия в новом потоке,
- * отличающемся от основного потока действия.
- *
- * 2/ android_main() получает указатель на допустимую структуру android_app,
- * которая содержит ссылки на другие важные объекты, например экземпляр объекта
- * ANativeActivity, где выполняется приложение.
- *
- * 3/ Объект android_app содержит экземпляр ALooper, который уже
- * ожидает две важных вещи:
- *
- * - событий жизненного цикла действия (например, "pause", "resume"). См. объявления APP_CMD_XXX
- * ниже.
- *
- * - входных событий, поступающих из очереди AInputQueue, присоединенной к действию.
- *
- * Каждое из этих событий соответствует идентификатору ALooper, возвращенному
- * ALooper_pollOnce со значениями LOOPER_ID_MAIN и LOOPER_ID_INPUT,
- *, соответственно.
- *
- * Ваше приложение может использовать тот же ALooper для прослушивания дополнительных
- * дескрипторов файла. Они могут быть основаны либо на обратных вызовах, либо поступают с идентификаторами возврата,
- * начинающимися с LOOPER_ID_USER.
- *
- * 4/ При получении события LOOPER_ID_MAIN или LOOPER_ID_INPUT
- * возвращенные данные будут указывать на структуру android_poll_source. Для нее
- * можно вызвать функцию process() и заполнить android_app->onAppCmd
- * и android_app->onInputEvent, для того чтобы они вызывались для вашей собственной обработки
- * события.
- *
- * Вместо этого можно вызвать функции нижнего уровня для чтения и обработки
- * данных непосредственно... посмотрите на реализации process_cmd() и process_input()
- * в приклеивании, чтобы выяснить, как это делается.
- *
- * См. пример "native-activity" в NDK с
- * полной демонстрацией использования. Также посмотрите JavaDoc в NativeActivity.
- */
-
-struct android_app;
-
-/**
- * Данные, связанные с ALooper fd, которые будут возвращаться как outData
- * при готовности данных в этом источнике.
- */
-struct android_poll_source {
- // Идентификатор данного источника. Может быть LOOPER_ID_MAIN или
- // LOOPER_ID_INPUT.
- int32_t id;
-
- // android_app, с которым связан данный идентификатор.
- struct android_app* app;
-
- // Функция, вызываемая для стандартной обработки данных из
- // этого источника.
- void (*process)(struct android_app* app, struct android_poll_source* source);
-};
-
-/**
- * Это интерфейс стандартного кода приклеивания поточного
- * приложения. В этой модели код приложения выполняется
- * в своем собственном потоке, отдельном от основного потока процесса.
- * Не требуется связь данного потока с ВМ Java
- *, хотя это необходимо для выполнения вызовов JNI любых
- * объектов Java.
- */
-struct android_app {
- // Приложение может поместить указатель на свой собственный объект состояния
- // здесь, если нужно.
- void* userData;
-
- // Введите здесь код функции для обработки основных команд приложения (APP_CMD_*)
- void (*onAppCmd)(struct android_app* app, int32_t cmd);
-
- // Введите здесь код функции для обработки входных событий. Сейчас
- // событие уже было предварительно отправлено и будет завершено при
- // возврате. Верните 1, если событие обработано, 0 — для любой диспетчеризации
- // по умолчанию.
- int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event);
-
- // Экземпляр объекта ANativeActivity, в котором выполняется это приложение.
- ANativeActivity* activity;
-
- // Текущая конфигурация, в которой выполняется это приложение.
- AConfiguration* config;
-
- // Это последнее сохраненное состояние экземпляра, предоставленное во время создания.
- // Значение равно NULL, если состояния не было. Можно использовать это по мере необходимости;
- // память останется доступной до вызова android_app_exec_cmd() для
- // APP_CMD_RESUME, после чего она будет освобождена, а savedState получит значение NULL.
- // Эти переменные необходимо изменять только при обработке APP_CMD_SAVE_STATE,
- // когда их значения будут инициализироваться в NULL и можно будет выполнить malloc для
- // состояния и поместить здесь информацию. В этом случае память будет
- // освобождена позднее.
- void* savedState;
- size_t savedStateSize;
-
- // ALooper, связанный с потоком приложения.
- ALooper* looper;
-
- // Если значение не равно NULL, то это входная очередь, из которой приложение будет
- // получать входные события пользователя.
- AInputQueue* inputQueue;
-
- // Если значение не равно NULL, то это поверхность окна, в котором приложение может рисовать.
- ANativeWindow* window;
-
- // Текущий прямоугольник содержимого окна. Это область, в которой
- // должно помещаться содержимое окна, чтобы его видел пользователь.
- ARect contentRect;
-
- // Текущее состояние действия приложения. Может быть APP_CMD_START,
- // APP_CMD_RESUME, APP_CMD_PAUSE или APP_CMD_STOP; см. ниже.
- int activityState;
-
- // Значение не равно нулю, когда NativeActivity приложения
- // разрушается и ожидает завершения потока приложения.
- int destroyRequested;
-
- // -------------------------------------------------
- // Ниже показан "частная" реализация кода прилипания.
-
- pthread_mutex_t mutex;
- pthread_cond_t cond;
-
- int msgread;
- int msgwrite;
-
- pthread_t thread;
-
- struct android_poll_source cmdPollSource;
- struct android_poll_source inputPollSource;
-
- int running;
- int stateSaved;
- int destroyed;
- int redrawNeeded;
- AInputQueue* pendingInputQueue;
- ANativeWindow* pendingWindow;
- ARect pendingContentRect;
-};
-
-enum {
- /**
- * Идентификатор данных Looper команд, поступающих из основного потока приложения, который
- * возвращается как идентификатор от ALooper_pollOnce(). Данные для этого идентификатора
- * являются указателем на структуру android_poll_source.
- * Их можно извлечь и обработать с помощью android_app_read_cmd()
- * и android_app_exec_cmd().
- */
- LOOPER_ID_MAIN = 1,
-
- /**
- * Идентификатор данных Looper событий, поступающий из AInputQueue окна
- * приложения, который возвращается как идентификатор из
- * ALooper_pollOnce(). Данные этого идентификатора являются указателем на структуру
- * android_poll_source. Их можно прочитать через объект inputQueue
- * приложения android_app.
- */
- LOOPER_ID_INPUT = 2,
-
- /**
- * Запуск определяемых пользователем идентификаторов ALooper.
- */
- LOOPER_ID_USER = 3,
-};
-
-enum {
- /**
- * Команда из основного потока: AInputQueue изменена. После обработки
- * этой команды android_app->inputQueue будет обновлена в новую очередь
- * (или NULL).
- */
- APP_CMD_INPUT_CHANGED,
-
- /**
- * Команда из основного потока: новое окно ANativeWindow готово к использованию. После
- * получения этой команды окно android_app-> будет содержать новую поверхность
- *окна.
- */
- APP_CMD_INIT_WINDOW,
-
- /**
- * Команда из основного потока: существующее окно ANativeWindow необходимо
- * прекратить. После получения этой команды окно android_app->по-прежнему
- * содержит существующее окно; после вызова android_app_exec_cmd
- * оно получит значение NULL.
- */
- APP_CMD_TERM_WINDOW,
-
- /**
- * Команда из основного потока: текущее окно ANativeWindow изменило размер.
- * Перерисуйте согласно новом размеру.
- */
- APP_CMD_WINDOW_RESIZED,
-
- /**
- * Команда из основного потока: системе необходимо, чтобы текущее окно ANativeWindow
- * было перерисовано. Необходимо перерисовать окно перед ее передачей в
- * android_app_exec_cmd(), чтобы избежать переходных сбоев рисования.
- */
- APP_CMD_WINDOW_REDRAW_NEEDED,
-
- /**
- * Команда из основного потока: область содержимого окна изменена
- * таким образом, что из функционального ввода окно показывается или скрывается. Можно
- * найти новый прямоугольник содержимого в android_app::contentRect.
- */
- APP_CMD_CONTENT_RECT_CHANGED,
-
- /**
- * Команда из основного потока: окно действия приложения получило
- * фокус ввода.
- */
- APP_CMD_GAINED_FOCUS,
-
- /**
- * Команда из основного потока: окно действия приложения потеряло
- * фокус ввода.
- */
- APP_CMD_LOST_FOCUS,
-
- /**
- * Команда из основного потока: изменена текущая конфигурация устройства.
- */
- APP_CMD_CONFIG_CHANGED,
-
- /**
- * Команда из основного потока: системе не хватает памяти.
- * Попробуйте уменьшить использование памяти.
- */
- APP_CMD_LOW_MEMORY,
-
- /**
- * Команда из основного потока: действие приложения было запущено.
- */
- APP_CMD_START,
-
- /**
- * Команда из основного потока: действие приложения было возобновлено.
- */
- APP_CMD_RESUME,
-
- /**
- * Команда из основного потока: приложение должно создать новое сохраненное состояние
- * для себя, чтобы восстанавливаться из него позднее в случае необходимости. Если вы сохранили состояние,
- * выделите его с использованием malloc и поместите в android_app.savedState с
- * размером android_app.savedStateSize. Память будет освобождена
- * позднее.
- */
- APP_CMD_SAVE_STATE,
-
- /**
- * Команда из основного потока: пауза в действии приложения.
- */
- APP_CMD_PAUSE,
-
- /**
- * Команда из основного потока: действие приложения было остановлено.
- */
- APP_CMD_STOP,
-
- /**
- * Команда из основного потока: действие приложения уничтожается,
- * и ожидает очистки потока приложения и выхода перед обработкой.
- */
- APP_CMD_DESTROY,
-};
-
-/**
- * Вызовите, когда ALooper_pollAll() возвращает LOOPER_ID_MAIN, при чтении следующего сообщения команды
- *приложения.
- */
-int8_t android_app_read_cmd(struct android_app* android_app);
-
-/**
- * Вызовите с помощью команды, возвращенной android_app_read_cmd() для выполнения
- * начальной предварительной обработки данной команды. Можно выполнить собственные
- * действия для команды после вызова этой функции.
- */
-void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd);
-
-/**
- * Вызовите с помощью команды, возвращенной android_app_read_cmd(), для
- * окончательной предварительной обработки данной команды. Необходимо завершить собственные
- * действия с командой до вызова этой функции.
- */
-void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd);
-
-/**
- * Это функция, которую должен реализовать код приложения, представляет собой
- * главный вход в приложение.
- */
-extern void android_main(struct android_app* app);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _ANDROID_NATIVE_APP_GLUE_H */
diff --git a/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/main.c b/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/main.c
deleted file mode 100644
index dce3f503c..000000000
--- a/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/main.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*******************************************************************************************
-*
-* raylib [core] example - Basic window
-*
-* This example has been created using raylib 3.8 (www.raylib.com)
-* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
-*
-* Example contributed by (@) and reviewed by Ramon Santamaria (@raysan5)
-*
-* Copyright (c) 2021 (@)
-
-* Adapt for Visual Studio: Vadim Boev (Kronka Dev)
-*
-********************************************************************************************/
-#include "android_native_app_glue.h"
-
-#include "../../../../src/raylib.h"
-
-int main(void)
-{
- // Initialization
- //--------------------------------------------------------------------------------------
- const int screenWidth = 800;
- const int screenHeight = 450;
-
- InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window");
-
- // TODO: Load resources / Initialize variables at this point
-
- SetTargetFPS(60);
- //--------------------------------------------------------------------------------------
-
- // Main game loop
- while (!WindowShouldClose()) // Detect window close button or ESC key
- {
- // Update
- //----------------------------------------------------------------------------------
- // TODO: Update variables / Implement example logic at this point
- //----------------------------------------------------------------------------------
-
- // Draw
- //----------------------------------------------------------------------------------
- BeginDrawing();
-
- ClearBackground(RAYWHITE);
-
- // TODO: Draw everything that requires to be drawn at this point:
-
- DrawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY); // Example
-
- EndDrawing();
- //----------------------------------------------------------------------------------
- }
-
- // De-Initialization
- //--------------------------------------------------------------------------------------
-
- // TODO: Unload all loaded resources at this point
-
- CloseWindow(); // Close window and OpenGL context
- //--------------------------------------------------------------------------------------
-
- return 0;
-}
diff --git a/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj b/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj
deleted file mode 100644
index 6b7b5a085..000000000
--- a/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj
+++ /dev/null
@@ -1,226 +0,0 @@
-
-
-
-
- Debug
- ARM
-
-
- Release
- ARM
-
-
- Debug
- ARM64
-
-
- Release
- ARM64
-
-
- Debug
- x64
-
-
- Release
- x64
-
-
- Debug
- x86
-
-
- Release
- x86
-
-
-
- {bfb31759-4fca-4503-bc7c-a97f705efdb2}
- Android
- raylib_android
- en-US
- 14.0
- Android
- 3.0
-
-
-
- DynamicLibrary
- true
- Clang_5_0
-
-
- DynamicLibrary
- false
- Clang_5_0
-
-
- DynamicLibrary
- true
- Clang_5_0
-
-
- DynamicLibrary
- false
- Clang_5_0
-
-
- DynamicLibrary
- true
- Clang_5_0
- android-29
-
-
- DynamicLibrary
- false
- Clang_5_0
-
-
- DynamicLibrary
- true
- Clang_5_0
-
-
- DynamicLibrary
- false
- Clang_5_0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- libmain
-
-
-
-
-
-
-
-
-
-
- NotUsing
- pch.h
- CompileAsC
- c99
- Default
- CompileAsC
-
-
- %(LibraryDependencies);EGL;GLESv2;log;android;c;m;raylib
- ../../../../src/;%(AdditionalLibraryDirectories)
-
-
-
-
- NotUsing
- pch.h
- CompileAsC
- c99
- Default
- CompileAsC
-
-
- %(LibraryDependencies);GLESv1_CM;EGL;
- .;%(AdditionalLibraryDirectories)
-
-
-
-
- Use
- pch.h
- CompileAsCpp
-
-
- %(LibraryDependencies);GLESv1_CM;EGL;
-
-
-
-
- Use
- pch.h
- CompileAsCpp
-
-
- %(LibraryDependencies);GLESv1_CM;EGL;
-
-
-
-
- Use
- pch.h
- CompileAsCpp
-
-
- %(LibraryDependencies);GLESv1_CM;EGL;
-
-
-
-
- Use
- pch.h
- CompileAsCpp
-
-
- %(LibraryDependencies);GLESv1_CM;EGL;
-
-
-
-
- Use
- pch.h
- CompileAsCpp
-
-
- %(LibraryDependencies);GLESv1_CM;EGL;
-
-
-
-
- Use
- pch.h
- CompileAsCpp
-
-
- %(LibraryDependencies);GLESv1_CM;EGL;
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj.filters b/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj.filters
deleted file mode 100644
index e9a26e2dd..000000000
--- a/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj.filters
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj.user b/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj.user
deleted file mode 100644
index 0f14913f3..000000000
--- a/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj.user
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/projects/VS2019-Android/raylib_android/raylib_android.Packaging/AndroidManifest.xml b/projects/VS2019-Android/raylib_android/raylib_android.Packaging/AndroidManifest.xml
deleted file mode 100644
index 8d58d3756..000000000
--- a/projects/VS2019-Android/raylib_android/raylib_android.Packaging/AndroidManifest.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/projects/VS2019-Android/raylib_android/raylib_android.Packaging/build.xml b/projects/VS2019-Android/raylib_android/raylib_android.Packaging/build.xml
deleted file mode 100644
index 4dd78480d..000000000
--- a/projects/VS2019-Android/raylib_android/raylib_android.Packaging/build.xml
+++ /dev/null
@@ -1,90 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/projects/VS2019-Android/raylib_android/raylib_android.Packaging/project.properties b/projects/VS2019-Android/raylib_android/raylib_android.Packaging/project.properties
deleted file mode 100644
index 3c100376c..000000000
--- a/projects/VS2019-Android/raylib_android/raylib_android.Packaging/project.properties
+++ /dev/null
@@ -1,3 +0,0 @@
-# Project target
-target=$(androidapilevel)
-# Provide path to the directory where prebuilt external jar files are by setting jar.libs.dir=
diff --git a/projects/VS2019-Android/raylib_android/raylib_android.Packaging/raylib_android.Packaging.androidproj b/projects/VS2019-Android/raylib_android/raylib_android.Packaging/raylib_android.Packaging.androidproj
deleted file mode 100644
index 030d71747..000000000
--- a/projects/VS2019-Android/raylib_android/raylib_android.Packaging/raylib_android.Packaging.androidproj
+++ /dev/null
@@ -1,134 +0,0 @@
-
-
-
-
- Debug
- ARM
-
-
- Release
- ARM
-
-
- Debug
- ARM64
-
-
- Release
- ARM64
-
-
- Debug
- x64
-
-
- Release
- x64
-
-
- Debug
- x86
-
-
- Release
- x86
-
-
-
- raylib_android
- 14.0
- 1.0
- {b2231f0d-52da-4c55-8998-5886f766553c}
-
-
-
- true
- Application
-
-
- false
- Application
-
-
- true
- Application
-
-
- false
- Application
-
-
- true
- Application
-
-
- false
- Application
-
-
- true
- Application
-
-
- false
- Application
-
-
-
-
-
-
-
-
- $(RootNamespace)
-
-
-
-
- $(RootNamespace)
-
-
-
-
- $(RootNamespace)
-
-
-
-
- $(RootNamespace)
-
-
-
-
- $(RootNamespace)
-
-
-
-
- $(RootNamespace)
-
-
-
-
- $(RootNamespace)
-
-
-
-
- $(RootNamespace)
-
-
-
-
-
-
-
-
-
-
- {bfb31759-4fca-4503-bc7c-a97f705efdb2}
-
-
-
-
-
\ No newline at end of file
diff --git a/projects/VS2019-Android/raylib_android/raylib_android.Packaging/res/values/strings.xml b/projects/VS2019-Android/raylib_android/raylib_android.Packaging/res/values/strings.xml
deleted file mode 100644
index 98afc4675..000000000
--- a/projects/VS2019-Android/raylib_android/raylib_android.Packaging/res/values/strings.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
- raylib_android.Packaging
-
diff --git a/src/external/rlsw.h b/src/external/rlsw.h
index bb6e11679..db10bf2b4 100644
--- a/src/external/rlsw.h
+++ b/src/external/rlsw.h
@@ -3909,7 +3909,6 @@ static void sw_immediate_set_color(const float color[4])
RLSW.primitive.color[2] = color[2];
RLSW.primitive.color[3] = color[3];
- RLSW.primitive.hasColorAlpha |= (color[3] < 1.0f);
}
static void sw_immediate_set_texcoord(const float texcoord[2])
@@ -3948,6 +3947,9 @@ static void sw_immediate_push_vertex(const float position[4])
for (int i = 0; i < 4; i++) vertex->color[i] = RLSW.primitive.color[i];
for (int i = 0; i < 2; i++) vertex->texcoord[i] = RLSW.primitive.texcoord[i];
+ // Track whether any vertex in this primitive has alpha < 1.0
+ RLSW.primitive.hasColorAlpha |= (vertex->color[3] < 1.0f);
+
// Immediate rendering of the primitive if the required number is reached
if (RLSW.primitive.vertexCount == SW_PRIMITIVE_VERTEX_COUNT[RLSW.drawMode])
{
@@ -4307,8 +4309,8 @@ void swScissor(int x, int y, int width, int height)
RLSW.scClipMin[0] = (2.0f*(float)RLSW.scMin[0]/(float)RLSW.vpSize[0]) - 1.0f;
RLSW.scClipMax[0] = (2.0f*(float)RLSW.scMax[0]/(float)RLSW.vpSize[0]) - 1.0f;
- RLSW.scClipMax[1] = 1.0f - (2.0f*(float)RLSW.scMin[1]/(float)RLSW.vpSize[1]);
- RLSW.scClipMin[1] = 1.0f - (2.0f*(float)RLSW.scMax[1]/(float)RLSW.vpSize[1]);
+ RLSW.scClipMin[1] = (2.0f*(float)RLSW.scMin[1]/(float)RLSW.vpSize[1]) - 1.0f;
+ RLSW.scClipMax[1] = (2.0f*(float)RLSW.scMax[1]/(float)RLSW.vpSize[1]) - 1.0f;
}
void swClearColor(float r, float g, float b, float a)
diff --git a/src/external/tinyobj_loader_c.h b/src/external/tinyobj_loader_c.h
index 88b2acbdc..8d077d665 100644
--- a/src/external/tinyobj_loader_c.h
+++ b/src/external/tinyobj_loader_c.h
@@ -1020,7 +1020,12 @@ static int parseLine(Command *command, const char *p, unsigned int p_len,
int triangulate) {
char linebuf[4096];
const char *token;
- assert(p_len < 4095);
+
+ // @raysan5:
+ // WARNING: If -DNDEBUG is set when compiling, assertions will not
+ // be present in the compiled binary, replacing by a runtime check
+ //assert(p_len < 4095);
+ if (p_len > 4095) return 0;
memcpy(linebuf, p, p_len);
linebuf[p_len] = '\0';
@@ -1102,8 +1107,12 @@ static int parseLine(Command *command, const char *p, unsigned int p_len,
tinyobj_vertex_index_t i1;
tinyobj_vertex_index_t i2 = f[1];
- assert(3 * num_f < TINYOBJ_MAX_FACES_PER_F_LINE);
-
+ // @raysan5:
+ // WARNING: If -DNDEBUG is set when compiling, assertions will not
+ // be present in the compiled binary, replacing by a runtime check
+ //assert(3 * num_f < TINYOBJ_MAX_FACES_PER_F_LINE);
+ if (3*num_f > TINYOBJ_MAX_FACES_PER_F_LINE) return 0;
+
for (k = 2; k < num_f; k++) {
i1 = i2;
i2 = f[k];
@@ -1119,7 +1128,13 @@ static int parseLine(Command *command, const char *p, unsigned int p_len,
} else {
unsigned int k = 0;
- assert(num_f < TINYOBJ_MAX_FACES_PER_F_LINE);
+
+ // @raysan5:
+ // WARNING: If -DNDEBUG is set when compiling, assertions will not
+ // be present in the compiled binary, replacing by a runtime check
+ //assert(num_f < TINYOBJ_MAX_FACES_PER_F_LINE);
+ if (num_f > TINYOBJ_MAX_FACES_PER_F_LINE) return 0;
+
for (k = 0; k < num_f; k++) {
command->f[k] = f[k];
}
diff --git a/src/platforms/rcore_android.c b/src/platforms/rcore_android.c
index 78abe9ed6..7fb080153 100644
--- a/src/platforms/rcore_android.c
+++ b/src/platforms/rcore_android.c
@@ -663,13 +663,22 @@ double GetTime(void)
}
// Open URL with default system browser (if available)
-// NOTE: This function is only safe to use if the provided URL is safe
-// A user could craft a malicious string performing another action
-// Avoid calling this function with user input non-validated strings
+// WARNING: This function is only safe to use if you control the URL given,
+// a user could craft a malicious string to perform and undesired action
+// NOTE: Some safety checks have been added to mitigate security issues
void OpenURL(const char *url)
{
// Security check to (partially) avoid malicious code
- if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character");
+ if ((strchr(url, '\'') != NULL) || (strchr(url, '\"') != NULL))
+ {
+ // Filter characters: ' and "
+ TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'\"] characters");
+ }
+ else if ((strncmp(url, "http://", 7) != 0) && (strncmp(url, "https://", 8) != 0))
+ {
+ // Only allow URL starting with "http://" or "https://" protocols
+ TRACELOG(LOG_WARNING, "SYSTEM: Provided URL must start with 'http://' or 'https://' protocols");
+ }
else
{
JNIEnv *env = NULL;
@@ -717,7 +726,6 @@ void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float d
void SetMousePosition(int x, int y)
{
CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
- CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
}
// Set mouse cursor
diff --git a/src/platforms/rcore_desktop_glfw.c b/src/platforms/rcore_desktop_glfw.c
index 64596b376..934815c0f 100644
--- a/src/platforms/rcore_desktop_glfw.c
+++ b/src/platforms/rcore_desktop_glfw.c
@@ -1181,17 +1181,25 @@ double GetTime(void)
}
// Open URL with default system browser (if available)
-// NOTE: This function is only safe to use if you control the URL given
-// A user could craft a malicious string performing another action
-// Only call this function yourself not with user input or make sure to check the string yourself
-// REF: https://github.com/raysan5/raylib/issues/686
+// WARNING: This function is only safe to use if you control the URL given,
+// a user could craft a malicious string to perform and undesired action
+// NOTE: Some safety checks have been added to mitigate security issues
void OpenURL(const char *url)
{
// Security check to (partially) avoid malicious code
- if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character");
- else
+ if ((strchr(url, '\'') != NULL) || (strchr(url, '\"') != NULL))
{
- char *cmd = (char *)RL_CALLOC(strlen(url) + 32, sizeof(char));
+ // Filter characters: ' and "
+ TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'\"] characters");
+ }
+ else if ((strncmp(url, "http://", 7) != 0) && (strncmp(url, "https://", 8) != 0))
+ {
+ // Only allow URL starting with "http://" or "https://" protocols
+ TRACELOG(LOG_WARNING, "SYSTEM: Provided URL must start with 'http://' or 'https://' protocols");
+ }
+ else
+ {
+ char *cmd = (char *)RL_CALLOC(strlen(url) + 16, sizeof(char));
#if defined(_WIN32)
sprintf(cmd, "explorer \"%s\"", url);
#endif
@@ -1201,7 +1209,9 @@ void OpenURL(const char *url)
#if defined(__APPLE__)
sprintf(cmd, "open '%s'", url);
#endif
+ // TODO: Replace system() call by custom process
int result = system(cmd);
+
if (result == -1) TRACELOG(LOG_WARNING, "OpenURL() child process could not be created");
RL_FREE(cmd);
}
@@ -1227,7 +1237,6 @@ void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float d
void SetMousePosition(int x, int y)
{
CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
- CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
// NOTE: emscripten not implemented
glfwSetCursorPos(platform.handle, CORE.Input.Mouse.currentPosition.x, CORE.Input.Mouse.currentPosition.y);
@@ -1316,7 +1325,7 @@ void PollInputEvents(void)
// Register previous gamepad states
for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) CORE.Input.Gamepad.previousButtonState[i][k] = CORE.Input.Gamepad.currentButtonState[i][k];
- // Get current gamepad state
+ // Get current gamepad state using internal GLFW mapping, instead of the immediate joystick API
// NOTE: There is no callback available, getting it manually
GLFWgamepadstate state = { 0 };
int result = glfwGetGamepadState(i, &state); // This remaps all gamepads so they have their buttons mapped like an xbox controller
@@ -1331,7 +1340,7 @@ void PollInputEvents(void)
for (int k = 0; (buttons != NULL) && (k < MAX_GAMEPAD_BUTTONS); k++)
{
- int button = -1; // GamepadButton enum values assigned
+ int button = -1; // GamepadButton enum values assigned
switch (k)
{
@@ -1357,7 +1366,7 @@ void PollInputEvents(void)
default: break;
}
- if (button != -1) // Check for valid button
+ if (button != -1) // Check for valid button
{
if (buttons[k] == GLFW_PRESS)
{
@@ -1399,10 +1408,10 @@ void PollInputEvents(void)
if ((CORE.Window.eventWaiting) ||
(FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MINIMIZED) && !FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_ALWAYS_RUN)))
{
- glfwWaitEvents(); // Wait for in input events before continue (drawing is paused)
+ glfwWaitEvents(); // Wait for in input events before continue (drawing is paused)
CORE.Time.previous = GetTime();
}
- else glfwPollEvents(); // Poll input events: keyboard/mouse/window events (callbacks) -> Update keys state
+ else glfwPollEvents(); // Poll input events: keyboard/mouse/window events (callbacks) -> Update keys state
CORE.Window.shouldClose = glfwWindowShouldClose(platform.handle);
@@ -1683,6 +1692,14 @@ int InitPlatform(void)
return -1;
}
+#if defined(__APPLE__)
+ // AppKit can constrain the requested window size to the visible work area during creation
+ int windowWidth = 0;
+ int windowHeight = 0;
+ glfwGetWindowSize(platform.handle, &windowWidth, &windowHeight);
+ if ((windowWidth > 0) && (windowHeight > 0)) CORE.Window.screen = (Size){ windowWidth, windowHeight };
+#endif
+
// NOTE: Not considering scale factor now, considered below
CORE.Window.render.width = CORE.Window.screen.width;
CORE.Window.render.height = CORE.Window.screen.height;
@@ -1829,7 +1846,7 @@ int InitPlatform(void)
{
CORE.Input.Gamepad.ready[i] = true;
CORE.Input.Gamepad.axisCount[i] = GLFW_GAMEPAD_AXIS_LAST + 1;
- strncpy(CORE.Input.Gamepad.name[i], glfwGetJoystickName(i), MAX_GAMEPAD_NAME_LENGTH - 1);
+ snprintf(CORE.Input.Gamepad.name[i], MAX_GAMEPAD_NAME_LENGTH, "%s", glfwGetJoystickName(i));
}
}
//----------------------------------------------------------------------------
@@ -2044,7 +2061,7 @@ static void WindowDropCallback(GLFWwindow *window, int count, const char **paths
for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++)
{
CORE.Window.dropFilepaths[i] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
- strncpy(CORE.Window.dropFilepaths[i], paths[i], MAX_FILEPATH_LENGTH - 1);
+ snprintf(CORE.Window.dropFilepaths[i], MAX_FILEPATH_LENGTH, "%s", paths[i]);
}
}
}
@@ -2191,7 +2208,7 @@ static void JoystickCallback(int jid, int event)
// WARNING: If glfwGetJoystickName() is longer than MAX_GAMEPAD_NAME_LENGTH,
// only copy up to (MAX_GAMEPAD_NAME_LENGTH -1) to destination string
memset(CORE.Input.Gamepad.name[jid], 0, MAX_GAMEPAD_NAME_LENGTH);
- strncpy(CORE.Input.Gamepad.name[jid], glfwGetJoystickName(jid), MAX_GAMEPAD_NAME_LENGTH - 1);
+ snprintf(CORE.Input.Gamepad.name[jid], MAX_GAMEPAD_NAME_LENGTH, "%s", glfwGetJoystickName(jid));
}
else if (event == GLFW_DISCONNECTED)
{
diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c
index 211917359..9907e8a60 100644
--- a/src/platforms/rcore_desktop_rgfw.c
+++ b/src/platforms/rcore_desktop_rgfw.c
@@ -486,14 +486,14 @@ static void RGFW_cb_dropfunc(const RGFW_event *e)
CORE.Window.dropFilepaths = (char **)RL_CALLOC(1024, sizeof(char *));
CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
- strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], e->drop.value->data);
+ snprintf(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], MAX_FILEPATH_LENGTH, "%s", e->drop.value->data);
CORE.Window.dropFileCount++;
}
else if (CORE.Window.dropFileCount < 1024)
{
CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
- strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], e->drop.value->data);
+ snprintf(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], MAX_FILEPATH_LENGTH, "%s", e->drop.value->data);
CORE.Window.dropFileCount++;
}
@@ -1471,15 +1471,25 @@ double GetTime(void)
}
// Open URL with default system browser (if available)
-// NOTE: This function is only safe to use if you control the URL given
-// A user could craft a malicious string performing another action
+// WARNING: This function is only safe to use if you control the URL given,
+// a user could craft a malicious string to perform and undesired action
+// NOTE: Some safety checks have been added to mitigate security issues
void OpenURL(const char *url)
{
- // Security check to (partially) avoid malicious code on target platform
- if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character");
- else
+ // Security check to (partially) avoid malicious code
+ if ((strchr(url, '\'') != NULL) || (strchr(url, '\"') != NULL))
{
- char *cmd = (char *)RL_CALLOC(strlen(url) + 32, sizeof(char));
+ // Filter characters: ' and "
+ TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'\"] characters");
+ }
+ else if ((strncmp(url, "http://", 7) != 0) && (strncmp(url, "https://", 8) != 0))
+ {
+ // Only allow URL starting with "http://" or "https://" protocols
+ TRACELOG(LOG_WARNING, "SYSTEM: Provided URL must start with 'http://' or 'https://' protocols");
+ }
+ else
+ {
+ char *cmd = (char *)RL_CALLOC(strlen(url) + 16, sizeof(char));
#if defined(_WIN32)
sprintf(cmd, "explorer \"%s\"", url);
#endif
@@ -1516,7 +1526,6 @@ void SetMousePosition(int x, int y)
{
RGFW_window_moveMouse(platform.window, x, y);
CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
- CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
}
// Set mouse cursor
@@ -1609,74 +1618,76 @@ void PollInputEvents(void)
//-----------------------------------------------------------------------------
mg_event gamepad_event;
- while (mg_gamepads_check_event(&platform.minigamepad, &gamepad_event)) {
+ while (mg_gamepads_check_event(&platform.minigamepad, &gamepad_event))
+ {
int gamepadIndex = gamepad_event.gamepad->index;
- switch (gamepad_event.type) {
+
+ switch (gamepad_event.type)
+ {
case MG_EVENT_BUTTON_PRESS:
+ {
+ int button = mg_buttonConvertTable[gamepad_event.button];
+ if (button >= 0)
{
- int button = mg_buttonConvertTable[gamepad_event.button];
- if (button >= 0)
- {
- CORE.Input.Gamepad.currentButtonState[gamepadIndex][button] = 1;
- CORE.Input.Gamepad.lastButtonPressed = button;
- }
- } break;
+ CORE.Input.Gamepad.currentButtonState[gamepadIndex][button] = 1;
+ CORE.Input.Gamepad.lastButtonPressed = button;
+ }
+ } break;
case MG_EVENT_BUTTON_RELEASE:
+ {
+ int button = mg_buttonConvertTable[gamepad_event.button];
+ if (button >= 0)
{
- int button = mg_buttonConvertTable[gamepad_event.button];
- if (button >= 0)
- {
- CORE.Input.Gamepad.currentButtonState[gamepadIndex][button] = 0;
- if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
- }
- } break;
+ CORE.Input.Gamepad.currentButtonState[gamepadIndex][button] = 0;
+ if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
+ }
+ } break;
case MG_EVENT_AXIS_MOVE:
- {
- int axis = mg_axisConvertTable[gamepad_event.axis];
+ {
+ int axis = mg_axisConvertTable[gamepad_event.axis];
- switch (axis) {
- case GAMEPAD_AXIS_LEFT_X:
- case GAMEPAD_AXIS_LEFT_Y:
- case GAMEPAD_AXIS_RIGHT_X:
- case GAMEPAD_AXIS_RIGHT_Y:
- CORE.Input.Gamepad.axisState[gamepadIndex][axis] = platform.minigamepad.gamepads[gamepadIndex].axes[gamepad_event.axis].value;
- break;
- case GAMEPAD_AXIS_LEFT_TRIGGER:
- case GAMEPAD_AXIS_RIGHT_TRIGGER:
- CORE.Input.Gamepad.axisState[gamepadIndex][axis] = platform.minigamepad.gamepads[gamepadIndex].axes[gamepad_event.axis].value;
+ switch (axis) {
+ case GAMEPAD_AXIS_LEFT_X:
+ case GAMEPAD_AXIS_LEFT_Y:
+ case GAMEPAD_AXIS_RIGHT_X:
+ case GAMEPAD_AXIS_RIGHT_Y:
+ {
+ CORE.Input.Gamepad.axisState[gamepadIndex][axis] = platform.minigamepad.gamepads[gamepadIndex].axes[gamepad_event.axis].value;
+ } break;
+ case GAMEPAD_AXIS_LEFT_TRIGGER:
+ case GAMEPAD_AXIS_RIGHT_TRIGGER:
+ {
+ CORE.Input.Gamepad.axisState[gamepadIndex][axis] = platform.minigamepad.gamepads[gamepadIndex].axes[gamepad_event.axis].value;
- // Trigger button press when axis is all the way
- int button = (axis == GAMEPAD_AXIS_LEFT_TRIGGER) ? GAMEPAD_BUTTON_LEFT_TRIGGER_2 : GAMEPAD_BUTTON_RIGHT_TRIGGER_2;
- int pressed = (platform.minigamepad.gamepads[gamepadIndex].axes[gamepad_event.axis].value >= 1.0f);
+ // Trigger button press when axis is all the way
+ int button = (axis == GAMEPAD_AXIS_LEFT_TRIGGER) ? GAMEPAD_BUTTON_LEFT_TRIGGER_2 : GAMEPAD_BUTTON_RIGHT_TRIGGER_2;
+ int pressed = (platform.minigamepad.gamepads[gamepadIndex].axes[gamepad_event.axis].value >= 1.0f);
- CORE.Input.Gamepad.currentButtonState[gamepadIndex][button] = pressed;
- if (pressed) CORE.Input.Gamepad.lastButtonPressed = button;
- else if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
- break;
- }
- } break;
+ CORE.Input.Gamepad.currentButtonState[gamepadIndex][button] = pressed;
+ if (pressed) CORE.Input.Gamepad.lastButtonPressed = button;
+ else if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
+ } break;
+ default: break;
+ }
+ } break;
case MG_EVENT_GAMEPAD_CONNECT:
+ {
CORE.Input.Gamepad.ready[gamepadIndex] = true;
CORE.Input.Gamepad.axisState[gamepadIndex][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f;
CORE.Input.Gamepad.axisState[gamepadIndex][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f;
int axisCount = 0;
- for (int i = 0; i < MG_AXIS_COUNT; i += 1) {
- if (platform.minigamepad.gamepads[gamepadIndex].axes[i].supported)
- {
- axisCount += 1;
- }
- else
- {
- break;
- }
+ for (int i = 0; i < MG_AXIS_COUNT; i += 1)
+ {
+ if (platform.minigamepad.gamepads[gamepadIndex].axes[i].supported) axisCount += 1;
+ else break;
}
+
CORE.Input.Gamepad.axisCount[gamepadIndex] = axisCount;
- strcpy(CORE.Input.Gamepad.name[gamepadIndex], platform.minigamepad.gamepads[gamepadIndex].name);
- break;
- case MG_EVENT_GAMEPAD_DISCONNECT:
- CORE.Input.Gamepad.ready[gamepadIndex] = false;
- break;
+ snprintf(CORE.Input.Gamepad.name[gamepadIndex], MAX_GAMEPAD_NAME_LENGTH, "%s", platform.minigamepad.gamepads[gamepadIndex].name);
+
+ } break;
+ case MG_EVENT_GAMEPAD_DISCONNECT: CORE.Input.Gamepad.ready[gamepadIndex] = false; break;
default: break;
}
}
diff --git a/src/platforms/rcore_desktop_sdl.c b/src/platforms/rcore_desktop_sdl.c
index c96820475..bca579e41 100644
--- a/src/platforms/rcore_desktop_sdl.c
+++ b/src/platforms/rcore_desktop_sdl.c
@@ -1255,12 +1255,14 @@ Image GetClipboardImage(void)
for (int i = 0; i < SDL_arraysize(imageFormats); i++)
{
- // NOTE: This pointer should be free with SDL_free() at some point
fileData = SDL_GetClipboardData(imageFormats[i], &dataSize);
if (fileData)
{
image = LoadImageFromMemory(imageExtensions[i], fileData, (int)dataSize);
+
+ SDL_free(fileData);
+
if (IsImageValid(image))
{
TRACELOG(LOG_INFO, "Clipboard: Got image from clipboard successfully: %s", imageExtensions[i]);
@@ -1341,14 +1343,22 @@ double GetTime(void)
}
// Open URL with default system browser (if available)
-// NOTE: This function is only safe to use if the provided URL is safe
-// A user could craft a malicious string performing another action
-// Avoid calling this function with user input non-validated strings
-// REF: https://github.com/raysan5/raylib/issues/686
+// WARNING: This function is only safe to use if you control the URL given,
+// a user could craft a malicious string to perform and undesired action
+// NOTE: Some safety checks have been added to mitigate security issues
void OpenURL(const char *url)
{
// Security check to (partially) avoid malicious code
- if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character");
+ if ((strchr(url, '\'') != NULL) || (strchr(url, '\"') != NULL))
+ {
+ // Filter characters: ' and "
+ TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'\"] characters");
+ }
+ else if ((strncmp(url, "http://", 7) != 0) && (strncmp(url, "https://", 8) != 0))
+ {
+ // Only allow URL starting with "http://" or "https://" protocols
+ TRACELOG(LOG_WARNING, "SYSTEM: Provided URL must start with 'http://' or 'https://' protocols");
+ }
else SDL_OpenURL(url);
}
@@ -1401,7 +1411,6 @@ void SetMousePosition(int x, int y)
SDL_WarpMouseInWindow(platform.window, x, y);
CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
- CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
}
// Set mouse cursor
@@ -1512,9 +1521,9 @@ void PollInputEvents(void)
// Event memory is now managed by SDL, so it should not be freed in SDL_EVENT_DROP_FILE,
// in case data needs to be hold onto the text in SDL_EVENT_TEXT_EDITING and SDL_EVENT_TEXT_INPUT events,
// a copy is required, SDL_TEXTINPUTEVENT_TEXT_SIZE is no longer necessary and has been removed
- strncpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.data, MAX_FILEPATH_LENGTH - 1);
+ snprintf(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], MAX_FILEPATH_LENGTH, "%s", event.drop.data);
#else
- strncpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.file, MAX_FILEPATH_LENGTH - 1);
+ snprintf(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], MAX_FILEPATH_LENGTH, "%s", event.drop.file);
SDL_free(event.drop.file);
#endif
@@ -1525,9 +1534,9 @@ void PollInputEvents(void)
CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
#if defined(USING_VERSION_SDL3)
- strncpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.data, MAX_FILEPATH_LENGTH - 1);
+ snprintf(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], MAX_FILEPATH_LENGTH, "%s", event.drop.data);
#else
- strncpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.file, MAX_FILEPATH_LENGTH - 1);
+ snprintf(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], MAX_FILEPATH_LENGTH, "%s", event.drop.file);
SDL_free(event.drop.file);
#endif
@@ -1812,8 +1821,8 @@ void PollInputEvents(void)
CORE.Input.Gamepad.axisState[nextAvailableSlot][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f;
memset(CORE.Input.Gamepad.name[nextAvailableSlot], 0, MAX_GAMEPAD_NAME_LENGTH);
const char *controllerName = SDL_GameControllerNameForIndex(nextAvailableSlot);
- if (controllerName != NULL) strncpy(CORE.Input.Gamepad.name[nextAvailableSlot], controllerName, MAX_GAMEPAD_NAME_LENGTH - 1);
- else strncpy(CORE.Input.Gamepad.name[nextAvailableSlot], "noname", 6);
+ if (controllerName != NULL) snprintf(CORE.Input.Gamepad.name[nextAvailableSlot], MAX_GAMEPAD_NAME_LENGTH, "%s", controllerName);
+ else memcpy(CORE.Input.Gamepad.name[nextAvailableSlot], "noname", 6);
}
else TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError());
}
@@ -2164,11 +2173,20 @@ int InitPlatform(void)
platform.gamepadId[i] = -1; // Set all gamepad initial instance ids as invalid to not conflict with instance id zero
}
+#if defined(USING_VERSION_SDL3)
+ int numJoysticks;
+ SDL_JoystickID *joysticks = SDL_GetJoysticks(&numJoysticks);
+#else
int numJoysticks = SDL_NumJoysticks();
+#endif
for (int i = 0; (i < numJoysticks) && (i < MAX_GAMEPADS); i++)
{
+#if defined(USING_VERSION_SDL3)
+ platform.gamepad[i] = SDL_OpenGamepad(joysticks[i]);
+#else
platform.gamepad[i] = SDL_GameControllerOpen(i);
+#endif
platform.gamepadId[i] = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(platform.gamepad[i]));
if (platform.gamepad[i])
@@ -2177,7 +2195,12 @@ int InitPlatform(void)
CORE.Input.Gamepad.axisCount[i] = SDL_JoystickNumAxes(SDL_GameControllerGetJoystick(platform.gamepad[i]));
CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f;
CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f;
- strncpy(CORE.Input.Gamepad.name[i], SDL_GameControllerNameForIndex(i), MAX_GAMEPAD_NAME_LENGTH - 1);
+#if defined(USING_VERSION_SDL3)
+ const char *joystickName = SDL_GetJoystickNameForID(joysticks[i]);
+#else
+ const char *joystickName = SDL_GameControllerNameForIndex(i);
+#endif
+ snprintf(CORE.Input.Gamepad.name[i], MAX_GAMEPAD_NAME_LENGTH, "%s", joystickName);
CORE.Input.Gamepad.name[i][MAX_GAMEPAD_NAME_LENGTH - 1] = '\0';
}
else TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError());
diff --git a/src/platforms/rcore_desktop_win32.c b/src/platforms/rcore_desktop_win32.c
index 35347023d..a6e85a657 100644
--- a/src/platforms/rcore_desktop_win32.c
+++ b/src/platforms/rcore_desktop_win32.c
@@ -1247,19 +1247,28 @@ double GetTime(void)
}
// Open URL with default system browser (if available)
-// NOTE: This function is only safe to use if the provided URL is safe
-// A user could craft a malicious string performing another action
-// Avoid calling this function with user input non-validated strings
-// REF: https://github.com/raysan5/raylib/issues/686
+// WARNING: This function is only safe to use if you control the URL given,
+// a user could craft a malicious string to perform and undesired action
+// NOTE: Some safety checks have been added to mitigate security issues
void OpenURL(const char *url)
{
- // Security check to (partially) avoid malicious code on target platform
- if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character");
- else
+ // Security check to (partially) avoid malicious code
+ if ((strchr(url, '\'') != NULL) || (strchr(url, '\"') != NULL))
{
- int len = strlen(url) + 32;
+ // Filter characters: ' and "
+ TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'\"] characters");
+ }
+ else if ((strncmp(url, "http://", 7) != 0) && (strncmp(url, "https://", 8) != 0))
+ {
+ // Only allow URL starting with "http://" or "https://" protocols
+ TRACELOG(LOG_WARNING, "SYSTEM: Provided URL must start with 'http://' or 'https://' protocols");
+ }
+ else
+ {
+ int len = strlen(url) + 16;
char *cmd = (char *)RL_CALLOC(len, sizeof(char));
snprintf(cmd, len, "explorer \"%s\"", url);
+
int result = system(cmd);
if (result == -1) TRACELOG(LOG_WARNING, "OpenURL() child process could not be created");
RL_FREE(cmd);
@@ -1290,8 +1299,8 @@ void SetMousePosition(int x, int y)
if (!CORE.Input.Mouse.cursorLocked)
{
CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
- CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
- TRACELOG(LOG_WARNING, "SetMousePosition not implemented");
+
+ TRACELOG(LOG_WARNING, "SetMousePosition not implemented at platform level");
}
else TRACELOG(LOG_WARNING, "INPUT: MOUSE: Cursor not enabled");
}
diff --git a/src/platforms/rcore_drm.c b/src/platforms/rcore_drm.c
index 659c80011..4d4a4d3bf 100644
--- a/src/platforms/rcore_drm.c
+++ b/src/platforms/rcore_drm.c
@@ -1014,9 +1014,8 @@ double GetTime(void)
}
// Open URL with default system browser (if available)
-// NOTE: This function is only safe to use if the provided URL is safe
-// A user could craft a malicious string performing another action
-// Avoid calling this function with user input non-validated strings
+// WARNING: This function is only safe to use if you control the URL given,
+// a user could craft a malicious string to perform and undesired action
void OpenURL(const char *url)
{
TRACELOG(LOG_WARNING, "OpenURL() not implemented on target platform");
@@ -1043,7 +1042,6 @@ void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float d
void SetMousePosition(int x, int y)
{
CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
- CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
}
// Set mouse cursor
@@ -1446,7 +1444,9 @@ int InitPlatform(void)
return -1;
}
- if (!eglChooseConfig(platform.device, NULL, NULL, 0, &numConfigs))
+ // WARNING: Providing framebufferAttribs is not logically necessary,
+ // but it may prevent segfaults on some nvidia drivers
+ if (!eglChooseConfig(platform.device, framebufferAttribs, NULL, 0, &numConfigs))
{
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get EGL config count: 0x%x", eglGetError());
return -1;
@@ -2732,4 +2732,4 @@ static void SetupFramebuffer(int width, int height)
}
}
-// EOF
\ No newline at end of file
+// EOF
diff --git a/src/platforms/rcore_memory.c b/src/platforms/rcore_memory.c
index 14c56a591..03b787da6 100644
--- a/src/platforms/rcore_memory.c
+++ b/src/platforms/rcore_memory.c
@@ -420,7 +420,6 @@ void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float d
void SetMousePosition(int x, int y)
{
CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
- CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
}
// Set mouse cursor
diff --git a/src/platforms/rcore_template.c b/src/platforms/rcore_template.c
index 353d32d11..1866059e8 100644
--- a/src/platforms/rcore_template.c
+++ b/src/platforms/rcore_template.c
@@ -352,14 +352,22 @@ double GetTime(void)
}
// Open URL with default system browser (if available)
-// NOTE: This function is only safe to use if you control the URL given.
-// A user could craft a malicious string performing another action.
-// Only call this function yourself not with user input or make sure to check the string yourself.
-// Ref: https://github.com/raysan5/raylib/issues/686
+// WARNING: This function is only safe to use if you control the URL given,
+// a user could craft a malicious string to perform and undesired action
+// NOTE: Some safety checks have been added to mitigate security issues
void OpenURL(const char *url)
{
- // Security check to (partially) avoid malicious code on target platform
- if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character");
+ // Security check to (partially) avoid malicious code
+ if ((strchr(url, '\'') != NULL) || (strchr(url, '\"') != NULL))
+ {
+ // Filter characters: ' and "
+ TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'\"] characters");
+ }
+ else if ((strncmp(url, "http://", 7) != 0) && (strncmp(url, "https://", 8) != 0))
+ {
+ // Only allow URL starting with "http://" or "https://" protocols
+ TRACELOG(LOG_WARNING, "SYSTEM: Provided URL must start with 'http://' or 'https://' protocols");
+ }
else
{
// TODO: Load url using default browser
@@ -387,7 +395,6 @@ void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float d
void SetMousePosition(int x, int y)
{
CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
- CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
}
// Set mouse cursor
diff --git a/src/platforms/rcore_web.c b/src/platforms/rcore_web.c
index 9d16c3e87..b95121d2c 100644
--- a/src/platforms/rcore_web.c
+++ b/src/platforms/rcore_web.c
@@ -1047,7 +1047,6 @@ void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float d
void SetMousePosition(int x, int y)
{
CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
- CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
if (CORE.Input.Mouse.cursorLocked) CORE.Input.Mouse.lockedPosition = CORE.Input.Mouse.currentPosition;
@@ -1579,7 +1578,7 @@ static void WindowDropCallback(GLFWwindow *window, int count, const char **paths
for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++)
{
CORE.Window.dropFilepaths[i] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
- strncpy(CORE.Window.dropFilepaths[i], paths[i], MAX_FILEPATH_LENGTH - 1);
+ snprintf(CORE.Window.dropFilepaths[i], MAX_FILEPATH_LENGTH, "%s", paths[i]);
}
}
}
diff --git a/src/platforms/rcore_web_emscripten.c b/src/platforms/rcore_web_emscripten.c
index ff78ac547..fa967057a 100644
--- a/src/platforms/rcore_web_emscripten.c
+++ b/src/platforms/rcore_web_emscripten.c
@@ -968,13 +968,22 @@ double GetTime(void)
}
// Open URL with default system browser (if available)
-// NOTE: This function is only safe to use if the provided URL is safe
-// A user could craft a malicious string performing another action
-// Avoid calling this function with user input non-validated strings
+// WARNING: This function is only safe to use if you control the URL given,
+// a user could craft a malicious string to perform and undesired action
+// NOTE: Some safety checks have been added to mitigate security issues
void OpenURL(const char *url)
{
- // Security check to (partially) avoid malicious code on target platform
- if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character");
+ // Security check to (partially) avoid malicious code
+ if ((strchr(url, '\'') != NULL) || (strchr(url, '\"') != NULL))
+ {
+ // Filter characters: ' and "
+ TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'\"] characters");
+ }
+ else if ((strncmp(url, "http://", 7) != 0) && (strncmp(url, "https://", 8) != 0))
+ {
+ // Only allow URL starting with "http://" or "https://" protocols
+ TRACELOG(LOG_WARNING, "SYSTEM: Provided URL must start with 'http://' or 'https://' protocols");
+ }
else emscripten_run_script(TextFormat("window.open('%s', '_blank')", url));
}
@@ -1439,7 +1448,7 @@ static void WindowDropCallback(GLFWwindow *window, int count, const char **paths
for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++)
{
CORE.Window.dropFilepaths[i] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
- strncpy(CORE.Window.dropFilepaths[i], paths[i], MAX_FILEPATH_LENGTH - 1);
+ snprintf(CORE.Window.dropFilepaths[i], MAX_FILEPATH_LENGTH, "%s", paths[i]);
}
}
}
@@ -1498,8 +1507,16 @@ static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent
{
switch (eventType)
{
- case EMSCRIPTEN_EVENT_MOUSEENTER: CORE.Input.Mouse.cursorOnScreen = true; break;
- case EMSCRIPTEN_EVENT_MOUSELEAVE: CORE.Input.Mouse.cursorOnScreen = false; break;
+ case EMSCRIPTEN_EVENT_MOUSEENTER: {
+ // NOTE: Mouse position updated by EmscriptenMouseMoveCallback(),
+ // EmscriptenPointerlockCallback(), and EmscriptenTouchCallback()
+ CORE.Input.Mouse.cursorOnScreen = true;
+ } break;
+ case EMSCRIPTEN_EVENT_MOUSELEAVE:
+ {
+ CORE.Input.Mouse.cursorOnScreen = false;
+ CORE.Input.Mouse.currentPosition = (Vector2){ 0 };
+ } break;
case EMSCRIPTEN_EVENT_MOUSEDOWN:
{
// NOTE: Emscripten and raylib buttons indices are not aligned
diff --git a/src/raudio.c b/src/raudio.c
index 094ea7533..42ea410c8 100644
--- a/src/raudio.c
+++ b/src/raudio.c
@@ -822,7 +822,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
wave.sampleRate = wav.sampleRate;
wave.sampleSize = 16;
wave.channels = wav.channels;
- wave.data = (short *)RL_MALLOC((size_t)wave.frameCount*wave.channels*sizeof(short));
+ wave.data = (short *)RL_CALLOC((size_t)wave.frameCount*wave.channels, sizeof(short));
// NOTE: Forcing conversion to 16bit sample size on reading
drwav_read_pcm_frames_s16(&wav, wave.frameCount, (drwav_int16 *)wave.data);
@@ -845,7 +845,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
wave.sampleSize = 16; // By default, ogg data is 16 bit per sample (short)
wave.channels = info.channels;
wave.frameCount = (unsigned int)stb_vorbis_stream_length_in_samples(oggData); // NOTE: It returns frames!
- wave.data = (short *)RL_MALLOC(wave.frameCount*wave.channels*sizeof(short));
+ wave.data = (short *)RL_CALLOC(wave.frameCount*wave.channels, sizeof(short));
// NOTE: Get the number of samples to process (be careful! asking for number of shorts, not bytes!)
stb_vorbis_get_samples_short_interleaved(oggData, info.channels, (short *)wave.data, wave.frameCount*wave.channels);
@@ -1154,7 +1154,7 @@ bool ExportWaveAsCode(Wave wave, const char *fileName)
// Get file name from path and convert variable name to uppercase
char varFileName[256] = { 0 };
- strncpy(varFileName, GetFileNameWithoutExt(fileName), 256 - 1);
+ snprintf(varFileName, 256, "%s", GetFileNameWithoutExt(fileName)); // NOTE: Using function provided by [rcore] module
for (int i = 0; varFileName[i] != '\0'; i++) if (varFileName[i] >= 'a' && varFileName[i] <= 'z') { varFileName[i] = varFileName[i] - 32; }
// Add wave information
@@ -1258,7 +1258,7 @@ void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels)
return;
}
- void *data = RL_MALLOC(frameCount*channels*(sampleSize/8));
+ void *data = RL_CALLOC(frameCount*channels*(sampleSize/8), 1);
frameCount = (ma_uint32)ma_convert_frames(data, frameCount, formatOut, channels, sampleRate, wave->data, frameCountIn, formatIn, wave->channels, wave->sampleRate);
if (frameCount == 0)
@@ -1772,7 +1772,7 @@ void UnloadMusicStream(Music music)
{
if (false) { }
#if SUPPORT_FILEFORMAT_WAV
- else if (music.ctxType == MUSIC_AUDIO_WAV) drwav_uninit((drwav *)music.ctxData);
+ else if (music.ctxType == MUSIC_AUDIO_WAV) { drwav_uninit((drwav *)music.ctxData); RL_FREE(music.ctxData); }
#endif
#if SUPPORT_FILEFORMAT_OGG
else if (music.ctxType == MUSIC_AUDIO_OGG) stb_vorbis_close((stb_vorbis *)music.ctxData);
@@ -2827,7 +2827,7 @@ static const char *GetFileNameWithoutExt(const char *filePath)
static char fileName[MAX_FILENAMEWITHOUTEXT_LENGTH] = { 0 };
memset(fileName, 0, MAX_FILENAMEWITHOUTEXT_LENGTH);
- if (filePath != NULL) strncpy(fileName, GetFileName(filePath), MAX_FILENAMEWITHOUTEXT_LENGTH - 1); // Get filename with extension
+ if (filePath != NULL) snprintf(fileName, MAX_FILENAMEWITHOUTEXT_LENGTH, "%s", GetFileName(filePath));
int fileNameLength = (int)strlen(fileName); // Get size in bytes
diff --git a/src/raylib.h b/src/raylib.h
index e3b4289a3..58f233483 100644
--- a/src/raylib.h
+++ b/src/raylib.h
@@ -409,8 +409,8 @@ typedef struct BoneInfo {
// Skeleton, animation bones hierarchy
typedef struct ModelSkeleton {
- int boneCount; // Number of bones
- BoneInfo *bones; // Bones information (skeleton)
+ unsigned int boneCount; // Number of bones
+ BoneInfo *bones; // Bones information (skeleton)
ModelAnimPose bindPose; // Bones base transformation (Transform[])
} ModelSkeleton;
@@ -436,8 +436,8 @@ typedef struct Model {
typedef struct ModelAnimation {
char name[32]; // Animation name
- int boneCount; // Number of bones (per pose)
- int keyframeCount; // Number of animation key frames
+ unsigned int boneCount; // Number of bones (per pose)
+ int keyframeCount; // Number of animation key frames
ModelAnimPose *keyframePoses; // Animation sequence keyframe poses [keyframe][pose]
} ModelAnimation;
diff --git a/src/rcore.c b/src/rcore.c
index d1163a515..a368cabec 100644
--- a/src/rcore.c
+++ b/src/rcore.c
@@ -108,7 +108,7 @@
#include // Required for: srand(), rand(), exit()
#include // Required for: FILE, fopen(), fseek(), ftell(), fread(), fwrite(), fprintf(), vprintf(), fclose(), sprintf() [Used in OpenURL()]
-#include // Required for: strlen(), strncpy(), strcmp(), strrchr(), memset(), strcat()
+#include // Required for: strlen(), strcmp(), strrchr(), memset(), memcpy(), strcat()
#include // Required for: va_list, va_start(), va_end() [Used in TraceLog()]
#include // Required for: time() [Used in InitTimer()]
#include // Required for: tan() [Used in BeginMode3D()], atan2f() [Used in LoadVrStereoConfig()]
@@ -1819,7 +1819,7 @@ void TakeScreenshot(const char *fileName)
Image image = { imgData, (int)((float)CORE.Window.render.width*scale.x), (int)((float)CORE.Window.render.height*scale.y), 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };
char path[MAX_FILEPATH_LENGTH] = { 0 };
- strncpy(path, TextFormat("%s/%s", CORE.Storage.basePath, fileName), MAX_FILEPATH_LENGTH - 1);
+ snprintf(path, MAX_FILEPATH_LENGTH, "%s", TextFormat("%s/%s", CORE.Storage.basePath, fileName));
ExportImage(image, path); // WARNING: Module required: rtextures
RL_FREE(imgData);
@@ -1844,8 +1844,6 @@ void SetConfigFlags(unsigned int flags)
FLAG_SET(CORE.Window.flags, flags);
}
-// void OpenURL(const char *url); // Defined per platform
-
//----------------------------------------------------------------------------------
// Module Functions Definition: Logging system
//----------------------------------------------------------------------------------
@@ -1885,12 +1883,12 @@ void TraceLog(int logType, const char *text, ...)
switch (logType)
{
- case LOG_TRACE: strncpy(buffer, "TRACE: ", 8); break;
- case LOG_DEBUG: strncpy(buffer, "DEBUG: ", 8); break;
- case LOG_INFO: strncpy(buffer, "INFO: ", 7); break;
- case LOG_WARNING: strncpy(buffer, "WARNING: ", 10); break;
- case LOG_ERROR: strncpy(buffer, "ERROR: ", 8); break;
- case LOG_FATAL: strncpy(buffer, "FATAL: ", 8); break;
+ case LOG_TRACE: memcpy(buffer, "TRACE: ", 7); break;
+ case LOG_DEBUG: memcpy(buffer, "DEBUG: ", 7); break;
+ case LOG_INFO: memcpy(buffer, "INFO: ", 6); break;
+ case LOG_WARNING: memcpy(buffer, "WARNING: ", 9); break;
+ case LOG_ERROR: memcpy(buffer, "ERROR: ", 7); break;
+ case LOG_FATAL: memcpy(buffer, "FATAL: ", 7); break;
default: break;
}
@@ -2063,7 +2061,7 @@ bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileN
// Get file name from path
char varFileName[256] = { 0 };
- strncpy(varFileName, GetFileNameWithoutExt(fileName), 256 - 1);
+ snprintf(varFileName, 256, "%s", GetFileNameWithoutExt(fileName));
for (int i = 0; varFileName[i] != '\0'; i++)
{
// Convert variable name to uppercase
@@ -2507,7 +2505,7 @@ const char *GetFileNameWithoutExt(const char *filePath)
if (filePath != NULL)
{
- strncpy(fileName, GetFileName(filePath), MAX_FILENAME_LENGTH - 1); // Get filename.ext without path
+ snprintf(fileName, MAX_FILENAME_LENGTH, "%s", GetFileName(filePath)); // Get filename.ext without path
int fileNameLength = (int)strlen(fileName); // Get size in bytes
for (int i = fileNameLength; i > 0; i--) // Reverse search '.'
@@ -2561,7 +2559,6 @@ const char *GetDirectoryPath(const char *filePath)
}
else
{
- // NOTE: Be careful, strncpy() is not safe, it does not care about '\0'
char *dirPathPtr = dirPath;
if ((filePath[1] != ':') && (filePath[0] != '\\') && (filePath[0] != '/')) dirPathPtr += 2; // Skip drive letter, "C:"
memcpy(dirPathPtr, filePath, strlen(filePath) - (strlen(lastSlash) - 1));
@@ -2579,7 +2576,7 @@ const char *GetPrevDirectoryPath(const char *dirPath)
memset(prevDirPath, 0, MAX_FILEPATH_LENGTH);
int dirPathLength = (int)strlen(dirPath);
- if (dirPathLength <= 3) strncpy(prevDirPath, dirPath, MAX_FILEPATH_LENGTH - 1);
+ if (dirPathLength <= 3) snprintf(prevDirPath, MAX_FILEPATH_LENGTH, "%s", dirPath);
for (int i = (dirPathLength - 1); (i >= 0) && (dirPathLength > 3); i--)
{
@@ -2588,7 +2585,7 @@ const char *GetPrevDirectoryPath(const char *dirPath)
// Check for root: "C:\" or "/"
if (((i == 2) && (dirPath[1] ==':')) || (i == 0)) i++;
- strncpy(prevDirPath, dirPath, i);
+ memcpy(prevDirPath, dirPath, i);
break;
}
}
@@ -3276,7 +3273,7 @@ unsigned int *ComputeMD5(const unsigned char *data, int dataSize)
memcpy(msg + newDataSize, &bitsLen, 4); // Append the len in bits at the end of the buffer
// Process the message in successive 512-bit chunks for each 512-bit chunk of message
- for (int offset = 0; offset < newDataSize; offset += (512/8))
+ for (int offset = 0; offset < newDataSize; offset += 64) // 512/8
{
// Break chunk into sixteen 32-bit words w[j], 0 <= j <= 15
unsigned int *w = (unsigned int *)(msg + offset);
@@ -3373,16 +3370,16 @@ unsigned int *ComputeSHA1(const unsigned char *data, int dataSize)
msg[newDataSize - 8] = (unsigned char)(bitsLen >> 56);
// Process the message in successive 512-bit chunks
- for (int offset = 0; offset < newDataSize; offset += (512/8))
+ for (int offset = 0; offset < newDataSize; offset += 64) // 512/8
{
// Break chunk into sixteen 32-bit words w[j], 0 <= j <= 15
unsigned int w[80] = { 0 };
for (int i = 0; i < 16; i++)
{
- w[i] = (msg[offset + (i*4) + 0] << 24) |
- (msg[offset + (i*4) + 1] << 16) |
- (msg[offset + (i*4) + 2] << 8) |
- (msg[offset + (i*4) + 3]);
+ w[i] = ((unsigned int)msg[offset + (i*4) + 0] << 24) |
+ ((unsigned int)msg[offset + (i*4) + 1] << 16) |
+ ((unsigned int)msg[offset + (i*4) + 2] << 8) |
+ ((unsigned int)msg[offset + (i*4) + 3]);
}
// Message schedule: extend the sixteen 32-bit words into eighty 32-bit words:
@@ -3604,10 +3601,14 @@ AutomationEventList LoadAutomationEventList(const char *fileName)
case 'c': sscanf(buffer, "c %i", &list.count); break;
case 'e':
{
- sscanf(buffer, "e %d %d %d %d %d %d %[^\n]s", &list.events[counter].frame, &list.events[counter].type,
- &list.events[counter].params[0], &list.events[counter].params[1], &list.events[counter].params[2], &list.events[counter].params[3], eventDesc);
+ if (counter < list.capacity)
+ {
+ sscanf(buffer, "e %d %d %d %d %d %d %63[^\n]s", &list.events[counter].frame, &list.events[counter].type,
+ &list.events[counter].params[0], &list.events[counter].params[1], &list.events[counter].params[2], &list.events[counter].params[3], eventDesc);
- counter++;
+ counter++;
+ }
+ else TRACELOG(LOG_WARNING, "AUTOMATION: Event goes beyond automated list capacity (MAX: %u): %s", list.capacity, buffer);
} break;
default: break;
}
diff --git a/src/rlgl.h b/src/rlgl.h
index d72469e11..68eec7fdf 100644
--- a/src/rlgl.h
+++ b/src/rlgl.h
@@ -847,11 +847,11 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
#define SW_CALLOC(n,sz) RL_CALLOC(n, sz)
#define SW_REALLOC(ptr, newSz) RL_REALLOC(ptr, newSz)
#define SW_FREE(ptr) RL_FREE(ptr)
- #include "external/rlsw.h" // OpenGL 1.1 software implementation
+ #include "external/rlsw.h" // OpenGL 1.1 software implementation
#else
#if defined(__APPLE__)
- #include // OpenGL 1.1 library for OSX
- #include // OpenGL extensions library
+ #include // OpenGL 1.1 library for OSX
+ #include // OpenGL extensions library
#else
// APIENTRY for OpenGL function pointer declarations is required
#if !defined(APIENTRY)
@@ -866,7 +866,7 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
#define WINGDIAPI __declspec(dllimport)
#endif
- #include // OpenGL 1.1 library
+ #include // OpenGL 1.1 library
#endif
#endif
#endif
@@ -907,9 +907,10 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
#endif
#endif
-#include // Required for: calloc(), free()
-#include // Required for: strcmp(), strlen() [Used in rlglInit(), on extensions loading]
-#include // Required for: sqrtf(), sinf(), cosf(), floor(), log()
+#include // Required for: calloc(), free()
+#include // Required for: strcmp(), strlen() [Used in rlglInit(), on extensions loading]
+#include // Required for: sqrtf(), sinf(), cosf(), floor(), log()
+#include // Required for: INT_MAX
//----------------------------------------------------------------------------------
// Defines and Macros
@@ -2469,7 +2470,7 @@ void rlLoadExtensions(void *loader)
// NOTE: String duplication rquired because glGetString() returns a const string
int extensionsLength = (int)strlen(extensions); // Get extensions string size in bytes
char *extensionsDup = (char *)RL_CALLOC(extensionsLength + 1, sizeof(char)); // Allocate space for copy with additional EOL byte
- strncpy(extensionsDup, extensions, extensionsLength);
+ snprintf(extensionsDup, extensionsLength, "%s", extensions);
extList[numExt] = extensionsDup;
for (int i = 0; i < extensionsLength; i++)
@@ -5236,7 +5237,9 @@ static int rlGetPixelDataSize(int width, int height, int format)
{
int blockWidth = (width + 3)/4;
int blockHeight = (height + 3)/4;
- dataSize = blockWidth*blockHeight*8;
+ unsigned long long dataSizeBytes = (unsigned long long)blockWidth*blockHeight*8;
+ if (dataSizeBytes < INT_MAX) dataSize = (int)dataSizeBytes;
+
} break;
case RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA:
case RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA:
@@ -5245,13 +5248,17 @@ static int rlGetPixelDataSize(int width, int height, int format)
{
int blockWidth = (width + 3)/4;
int blockHeight = (height + 3)/4;
- dataSize = blockWidth*blockHeight*16;
+ unsigned long long dataSizeBytes = (unsigned long long)blockWidth*blockHeight*16;
+ if (dataSizeBytes < INT_MAX) dataSize = (int)dataSizeBytes;
+
} break;
case RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: // 4 bytes per each 4x4 block
{
int blockWidth = (width + 3)/4;
int blockHeight = (height + 3)/4;
- dataSize = blockWidth*blockHeight*4;
+ unsigned long long dataSizeBytes = (unsigned long long)blockWidth*blockHeight*4;
+ if (dataSizeBytes < INT_MAX) dataSize = (int)dataSizeBytes;
+
} break;
default: break;
}
@@ -5260,9 +5267,11 @@ static int rlGetPixelDataSize(int width, int height, int format)
if ((format >= RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) &&
(format <= RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16))
{
- double bytesPerPixel = (double)bpp/8.0;
- dataSize = (int)(bytesPerPixel*width*height); // Total data size in bytes
+ unsigned long long dataSizeBytes = ((unsigned long long)width*height*bpp) >> 3; // Get size in bytes (dividing by 8)
+ if (dataSizeBytes < INT_MAX) dataSize = (int)dataSizeBytes;
}
+
+ if (dataSize == 0) TRACELOG(LOG_WARNING, "Requested image size is larger than 2GB, it can not be allocated");
return dataSize;
}
diff --git a/src/rmodels.c b/src/rmodels.c
index 28fb3c9ec..0325f9b1b 100644
--- a/src/rmodels.c
+++ b/src/rmodels.c
@@ -50,9 +50,9 @@
#include "rlgl.h" // OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2
#include "raymath.h" // Required for: Vector3, Quaternion and Matrix functionality
-#include // Required for: sprintf()
+#include // Required for: sprintf(), snprintf()
#include // Required for: malloc(), calloc(), free()
-#include // Required for: memcmp(), strlen(), strncpy()
+#include // Required for: strlen(), memcmp()
#include // Required for: sinf(), cosf(), sqrtf(), fabsf()
#if SUPPORT_FILEFORMAT_OBJ || SUPPORT_FILEFORMAT_MTL
@@ -2073,7 +2073,7 @@ bool ExportMeshAsCode(Mesh mesh, const char *fileName)
// Get file name from path and convert variable name to uppercase
char varFileName[256] = { 0 };
- strncpy(varFileName, GetFileNameWithoutExt(fileName), 256 - 1); // NOTE: Using function provided by [rcore] module
+ snprintf(varFileName, 256, "%s", GetFileNameWithoutExt(fileName)); // NOTE: Using function provided by [rcore] module
for (int i = 0; varFileName[i] != '\0'; i++) if ((varFileName[i] >= 'a') && (varFileName[i] <= 'z')) { varFileName[i] = varFileName[i] - 32; }
// Add image information
@@ -2320,7 +2320,7 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, float frame)
Matrix currentPoseMatrix = { 0 };
// Update all bones and bone matrices of model
- for (int boneIndex = 0; boneIndex < model.skeleton.boneCount; boneIndex++)
+ for (unsigned int boneIndex = 0; boneIndex < model.skeleton.boneCount; boneIndex++)
{
// Compute interpolated pose between current and next frame
// NOTE: Storing animation frame data in model.currentPose
@@ -2390,7 +2390,7 @@ void UpdateModelAnimationEx(Model model, ModelAnimation animA, float frameA, Mod
Matrix bindPoseMatrix = { 0 };
Matrix currentPoseMatrix = { 0 };
- for (int boneIndex = 0; boneIndex < model.skeleton.boneCount; boneIndex++)
+ for (unsigned int boneIndex = 0; boneIndex < model.skeleton.boneCount; boneIndex++)
{
// Get frame-interpolation for first animation
Vector3 frameATranslation = Vector3Lerp(
@@ -4421,7 +4421,7 @@ static Model LoadOBJ(const char *fileName)
}
char currentDir[MAX_FILEPATH_LENGTH] = { 0 };
- strncpy(currentDir, GetWorkingDirectory(), MAX_FILEPATH_LENGTH - 1); // Save current working directory
+ snprintf(currentDir, MAX_FILEPATH_LENGTH, "%s", GetWorkingDirectory()); // Save current working directory
const char *workingDir = GetDirectoryPath(fileName); // Switch to OBJ directory for material path correctness
if (CHDIR(workingDir) != 0) TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to change working directory", workingDir);
@@ -5013,7 +5013,7 @@ static Model LoadIQM(const char *fileName)
// Initialize runtime animation data: current pose and bone matrices
model.currentPose = (Transform *)RL_CALLOC(model.skeleton.boneCount, sizeof(Transform));
model.boneMatrices = (Matrix *)RL_CALLOC(model.skeleton.boneCount, sizeof(Matrix));
- for (int j = 0; j < model.skeleton.boneCount; j++) model.boneMatrices[j] = MatrixIdentity();
+ for (unsigned int j = 0; j < model.skeleton.boneCount; j++) model.boneMatrices[j] = MatrixIdentity();
UnloadFileData(fileData);
@@ -5241,7 +5241,7 @@ static ModelAnimation *LoadModelAnimationsIQM(const char *fileName, int *animCou
// Build frameposes
for (unsigned int frame = 0; frame < anim[a].num_frames; frame++)
{
- for (int i = 0; i < animations[a].boneCount; i++)
+ for (unsigned int i = 0; i < animations[a].boneCount; i++)
{
if (bones[i].parent >= 0)
{
@@ -5316,8 +5316,8 @@ static Image LoadImageFromCgltfImage(cgltf_image *cgltfImage, const char *texPat
{
int base64Size = (int)strlen(cgltfImage->uri + i + 1);
while (cgltfImage->uri[i + base64Size] == '=') base64Size--; // Ignore optional paddings
- int numberOfEncodedBits = base64Size*6 - (base64Size*6) % 8 ; // Encoded bits minus extra bits, so it becomes a multiple of 8 bits
- int outSize = numberOfEncodedBits/8 ; // Actual encoded bytes
+ int numberOfEncodedBits = base64Size*6 - (base64Size*6)%8; // Encoded bits minus extra bits, so it becomes a multiple of 8 bits
+ int outSize = numberOfEncodedBits >> 3; // Actual encoded bytes
void *data = NULL;
cgltf_options options = { 0 };
@@ -5369,15 +5369,15 @@ static Image LoadImageFromCgltfImage(cgltf_image *cgltfImage, const char *texPat
}
// Load bone info from GLTF skin data
-static BoneInfo *LoadBoneInfoGLTF(cgltf_skin skin, int *boneCount)
+static BoneInfo *LoadBoneInfoGLTF(cgltf_skin skin, unsigned int *boneCount)
{
- *boneCount = (int)skin.joints_count;
+ *boneCount = (unsigned int)skin.joints_count;
BoneInfo *bones = (BoneInfo *)RL_CALLOC(skin.joints_count, sizeof(BoneInfo));
for (unsigned int i = 0; i < skin.joints_count; i++)
{
cgltf_node node = *skin.joints[i];
- if (node.name != NULL) strncpy(bones[i].name, node.name, sizeof(bones[i].name) - 1);
+ if (node.name != NULL) snprintf(bones[i].name, sizeof(bones[i].name), "%s", node.name);
// Find parent bone index by walking up the node tree past any
// non-joint ancestors (intermediate transform nodes used by some
@@ -6144,7 +6144,7 @@ static Model LoadGLTF(const char *fileName)
model.skeleton.bones = LoadBoneInfoGLTF(skin, &model.skeleton.boneCount);
model.skeleton.bindPose = (Transform *)RL_CALLOC(model.skeleton.boneCount, sizeof(Transform));
- for (int i = 0; i < model.skeleton.boneCount; i++)
+ for (unsigned int i = 0; i < model.skeleton.boneCount; i++)
{
Matrix bindMatrix = { 0 };
cgltf_float inverseBindTransform[16] = { 0 };
@@ -6309,7 +6309,7 @@ static Model LoadGLTF(const char *fileName)
if ((data->skins_count > 0) && !hasJoints && (node->parent != NULL) && (node->parent->mesh == NULL))
{
int parentBoneId = -1;
- for (int joint = 0; joint < model.skeleton.boneCount; joint++)
+ for (unsigned int joint = 0; joint < model.skeleton.boneCount; joint++)
{
if (data->skins[0].joints[joint] == node->parent)
{
@@ -6347,7 +6347,7 @@ static Model LoadGLTF(const char *fileName)
// Initialize runtime animation data: current pose and bone matrices
model.currentPose = (Transform *)RL_CALLOC(model.skeleton.boneCount, sizeof(Transform));
model.boneMatrices = (Matrix *)RL_CALLOC(model.skeleton.boneCount, sizeof(Matrix));
- for (int j = 0; j < model.skeleton.boneCount; j++) model.boneMatrices[j] = MatrixIdentity();
+ for (unsigned int j = 0; j < model.skeleton.boneCount; j++) model.boneMatrices[j] = MatrixIdentity();
//----------------------------------------------------------------------------------------------------
// Free unused allocated memory in case of no bones defined
@@ -6660,7 +6660,7 @@ static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCo
animDuration = (time > animDuration)? time : animDuration;
}
- if (animData.name != NULL) strncpy(animations[a].name, animData.name, sizeof(animations[a].name) - 1);
+ if (animData.name != NULL) snprintf(animations[a].name, sizeof(animations[a].name), "%s", animData.name);
animations[a].keyframeCount = (int)(animDuration*GLTF_FRAMERATE) + 1;
animations[a].keyframePoses = (Transform **)RL_CALLOC(animations[a].keyframeCount, sizeof(Transform *));
@@ -6670,7 +6670,7 @@ static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCo
animations[a].keyframePoses[j] = (Transform *)RL_CALLOC(animations[a].boneCount, sizeof(Transform));
float time = (float)j / GLTF_FRAMERATE;
- for (int k = 0; k < animations[a].boneCount; k++)
+ for (unsigned int k = 0; k < animations[a].boneCount; k++)
{
Vector3 translation = {skin.joints[k]->translation[0], skin.joints[k]->translation[1], skin.joints[k]->translation[2]};
Quaternion rotation = {skin.joints[k]->rotation[0], skin.joints[k]->rotation[1], skin.joints[k]->rotation[2], skin.joints[k]->rotation[3]};
@@ -7150,7 +7150,7 @@ static Model LoadM3D(const char *fileName)
for (i = 0; i < (int)m3d->numbone; i++)
{
model.skeleton.bones[i].parent = m3d->bone[i].parent;
- strncpy(model.skeleton.bones[i].name, m3d->bone[i].name, sizeof(model.skeleton.bones[i].name) - 1);
+ snprintf(model.skeleton.bones[i].name, sizeof(model.skeleton.bones[i].name), "%s", m3d->bone[i].name);
model.skeleton.bindPose[i].translation.x = m3d->vertex[m3d->bone[i].pos].x*m3d->scale;
model.skeleton.bindPose[i].translation.y = m3d->vertex[m3d->bone[i].pos].y*m3d->scale;
model.skeleton.bindPose[i].translation.z = m3d->vertex[m3d->bone[i].pos].z*m3d->scale;
@@ -7204,7 +7204,7 @@ static Model LoadM3D(const char *fileName)
// Initialize runtime animation data: current pose and bone matrices
model.currentPose = (Transform *)RL_CALLOC(model.skeleton.boneCount, sizeof(Transform));
model.boneMatrices = (Matrix *)RL_CALLOC(model.skeleton.boneCount, sizeof(Matrix));
- for (int j = 0; j < model.skeleton.boneCount; j++) model.boneMatrices[j] = MatrixIdentity();
+ for (unsigned int j = 0; j < model.skeleton.boneCount; j++) model.boneMatrices[j] = MatrixIdentity();
}
m3d_free(m3d);
@@ -7258,14 +7258,14 @@ static ModelAnimation *LoadModelAnimationsM3D(const char *fileName, int *animCou
animations[a].keyframeCount = m3d->action[a].durationmsec/M3D_ANIMDELAY;
animations[a].keyframePoses = (Transform **)RL_CALLOC(animations[a].keyframeCount, sizeof(Transform *));
- strncpy(animations[a].name, m3d->action[a].name, sizeof(animations[a].name) - 1);
+ snprintf(animations[a].name, sizeof(animations[a].name), "%s", m3d->action[a].name);
TRACELOG(LOG_INFO, "MODEL: [%s] Loaded animation: %s | Frames: %d | Duration: %fs", fileName, animations[a].name, animations[a].keyframeCount, m3d->action[a].durationmsec);
for (i = 0; i < (int)m3d->numbone; i++)
{
bones[i].parent = m3d->bone[i].parent;
- strncpy(bones[i].name, m3d->bone[i].name, sizeof(bones[i].name) - 1);
+ snprintf(bones[i].name, sizeof(bones[i].name), "%s", m3d->bone[i].name);
}
// A special, never transformed "no bone" bone, used for boneless vertices
diff --git a/src/rshapes.c b/src/rshapes.c
index 12ae6a164..def6d36b2 100644
--- a/src/rshapes.c
+++ b/src/rshapes.c
@@ -888,14 +888,13 @@ void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color co
// Draw rectangle with rounded edges
void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, Color color)
{
- // NOTE: For line thicknes <=1.0f using RL_LINES, otherwise using RL_QUADS/RL_TRIANGLES
DrawRectangleRoundedLinesEx(rec, roundness, segments, 1.0f, color);
}
// Draw rectangle with rounded edges outline with line thickness
void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, float thick, Color color)
{
- if (thick < 0) thick = 0;
+ if (thick <= 0) return;
// Not a rounded rectangle
if (roundness <= 0.0f)
@@ -966,176 +965,145 @@ void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, f
const float angles[4] = { 180.0f, 270.0f, 0.0f, 90.0f };
- if (thick > 1)
- {
#if SUPPORT_QUADS_DRAW_MODE
- rlSetTexture(GetShapesTexture().id);
- Rectangle shapeRect = GetShapesTextureRectangle();
+ rlSetTexture(GetShapesTexture().id);
+ Rectangle shapeRect = GetShapesTextureRectangle();
- rlBegin(RL_QUADS);
+ rlBegin(RL_QUADS);
- // Draw all the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner
- for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
- {
- float angle = angles[k];
- const Vector2 center = centers[k];
- for (int i = 0; i < segments; i++)
- {
- rlColor4ub(color.r, color.g, color.b, color.a);
-
- rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
- rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius);
-
- rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
- rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
-
- rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
- rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius);
-
- rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
- rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
-
- angle += stepLength;
- }
- }
-
- // Upper rectangle
- rlColor4ub(color.r, color.g, color.b, color.a);
- rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
- rlVertex2f(point[0].x, point[0].y);
- rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
- rlVertex2f(point[8].x, point[8].y);
- rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
- rlVertex2f(point[9].x, point[9].y);
- rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
- rlVertex2f(point[1].x, point[1].y);
-
- // Right rectangle
- rlColor4ub(color.r, color.g, color.b, color.a);
- rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
- rlVertex2f(point[2].x, point[2].y);
- rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
- rlVertex2f(point[10].x, point[10].y);
- rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
- rlVertex2f(point[11].x, point[11].y);
- rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
- rlVertex2f(point[3].x, point[3].y);
-
- // Lower rectangle
- rlColor4ub(color.r, color.g, color.b, color.a);
- rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
- rlVertex2f(point[13].x, point[13].y);
- rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
- rlVertex2f(point[5].x, point[5].y);
- rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
- rlVertex2f(point[4].x, point[4].y);
- rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
- rlVertex2f(point[12].x, point[12].y);
-
- // Left rectangle
- rlColor4ub(color.r, color.g, color.b, color.a);
- rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
- rlVertex2f(point[15].x, point[15].y);
- rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
- rlVertex2f(point[7].x, point[7].y);
- rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
- rlVertex2f(point[6].x, point[6].y);
- rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
- rlVertex2f(point[14].x, point[14].y);
-
- rlEnd();
- rlSetTexture(0);
-#else
- rlBegin(RL_TRIANGLES);
-
- // Draw all of the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner
- for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
- {
- float angle = angles[k];
- const Vector2 center = centers[k];
-
- for (int i = 0; i < segments; i++)
- {
- rlColor4ub(color.r, color.g, color.b, color.a);
-
- rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius);
- rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
- rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
-
- rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
- rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius);
- rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
-
- angle += stepLength;
- }
- }
-
- // Upper rectangle
- rlColor4ub(color.r, color.g, color.b, color.a);
- rlVertex2f(point[0].x, point[0].y);
- rlVertex2f(point[8].x, point[8].y);
- rlVertex2f(point[9].x, point[9].y);
- rlVertex2f(point[1].x, point[1].y);
- rlVertex2f(point[0].x, point[0].y);
- rlVertex2f(point[9].x, point[9].y);
-
- // Right rectangle
- rlColor4ub(color.r, color.g, color.b, color.a);
- rlVertex2f(point[10].x, point[10].y);
- rlVertex2f(point[11].x, point[11].y);
- rlVertex2f(point[3].x, point[3].y);
- rlVertex2f(point[2].x, point[2].y);
- rlVertex2f(point[10].x, point[10].y);
- rlVertex2f(point[3].x, point[3].y);
-
- // Lower rectangle
- rlColor4ub(color.r, color.g, color.b, color.a);
- rlVertex2f(point[13].x, point[13].y);
- rlVertex2f(point[5].x, point[5].y);
- rlVertex2f(point[4].x, point[4].y);
- rlVertex2f(point[12].x, point[12].y);
- rlVertex2f(point[13].x, point[13].y);
- rlVertex2f(point[4].x, point[4].y);
-
- // Left rectangle
- rlColor4ub(color.r, color.g, color.b, color.a);
- rlVertex2f(point[7].x, point[7].y);
- rlVertex2f(point[6].x, point[6].y);
- rlVertex2f(point[14].x, point[14].y);
- rlVertex2f(point[15].x, point[15].y);
- rlVertex2f(point[7].x, point[7].y);
- rlVertex2f(point[14].x, point[14].y);
- rlEnd();
-#endif
- }
- else
- {
- // Use LINES to draw the outline
- rlBegin(RL_LINES);
- // Draw all the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner
- for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
- {
- float angle = angles[k];
- const Vector2 center = centers[k];
-
- for (int i = 0; i < segments; i++)
- {
- rlColor4ub(color.r, color.g, color.b, color.a);
- rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
- rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius);
- angle += stepLength;
- }
- }
-
- // And now the remaining 4 lines
- for (int i = 0; i < 8; i += 2)
+ // Draw all the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner
+ for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
+ {
+ float angle = angles[k];
+ const Vector2 center = centers[k];
+ for (int i = 0; i < segments; i++)
{
rlColor4ub(color.r, color.g, color.b, color.a);
- rlVertex2f(point[i].x, point[i].y);
- rlVertex2f(point[i + 1].x, point[i + 1].y);
+
+ rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
+ rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius);
+
+ rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
+ rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
+
+ rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
+ rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius);
+
+ rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
+ rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
+
+ angle += stepLength;
}
- rlEnd();
- }
+ }
+
+ // Upper rectangle
+ rlColor4ub(color.r, color.g, color.b, color.a);
+ rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
+ rlVertex2f(point[0].x, point[0].y);
+ rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
+ rlVertex2f(point[8].x, point[8].y);
+ rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
+ rlVertex2f(point[9].x, point[9].y);
+ rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
+ rlVertex2f(point[1].x, point[1].y);
+
+ // Right rectangle
+ rlColor4ub(color.r, color.g, color.b, color.a);
+ rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
+ rlVertex2f(point[2].x, point[2].y);
+ rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
+ rlVertex2f(point[10].x, point[10].y);
+ rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
+ rlVertex2f(point[11].x, point[11].y);
+ rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
+ rlVertex2f(point[3].x, point[3].y);
+
+ // Lower rectangle
+ rlColor4ub(color.r, color.g, color.b, color.a);
+ rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
+ rlVertex2f(point[13].x, point[13].y);
+ rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
+ rlVertex2f(point[5].x, point[5].y);
+ rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
+ rlVertex2f(point[4].x, point[4].y);
+ rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
+ rlVertex2f(point[12].x, point[12].y);
+
+ // Left rectangle
+ rlColor4ub(color.r, color.g, color.b, color.a);
+ rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
+ rlVertex2f(point[15].x, point[15].y);
+ rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
+ rlVertex2f(point[7].x, point[7].y);
+ rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
+ rlVertex2f(point[6].x, point[6].y);
+ rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
+ rlVertex2f(point[14].x, point[14].y);
+
+ rlEnd();
+ rlSetTexture(0);
+#else
+ rlBegin(RL_TRIANGLES);
+
+ // Draw all of the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner
+ for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
+ {
+ float angle = angles[k];
+ const Vector2 center = centers[k];
+
+ for (int i = 0; i < segments; i++)
+ {
+ rlColor4ub(color.r, color.g, color.b, color.a);
+
+ rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius);
+ rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
+ rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
+
+ rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
+ rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius);
+ rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
+
+ angle += stepLength;
+ }
+ }
+
+ // Upper rectangle
+ rlColor4ub(color.r, color.g, color.b, color.a);
+ rlVertex2f(point[0].x, point[0].y);
+ rlVertex2f(point[8].x, point[8].y);
+ rlVertex2f(point[9].x, point[9].y);
+ rlVertex2f(point[1].x, point[1].y);
+ rlVertex2f(point[0].x, point[0].y);
+ rlVertex2f(point[9].x, point[9].y);
+
+ // Right rectangle
+ rlColor4ub(color.r, color.g, color.b, color.a);
+ rlVertex2f(point[10].x, point[10].y);
+ rlVertex2f(point[11].x, point[11].y);
+ rlVertex2f(point[3].x, point[3].y);
+ rlVertex2f(point[2].x, point[2].y);
+ rlVertex2f(point[10].x, point[10].y);
+ rlVertex2f(point[3].x, point[3].y);
+
+ // Lower rectangle
+ rlColor4ub(color.r, color.g, color.b, color.a);
+ rlVertex2f(point[13].x, point[13].y);
+ rlVertex2f(point[5].x, point[5].y);
+ rlVertex2f(point[4].x, point[4].y);
+ rlVertex2f(point[12].x, point[12].y);
+ rlVertex2f(point[13].x, point[13].y);
+ rlVertex2f(point[4].x, point[4].y);
+
+ // Left rectangle
+ rlColor4ub(color.r, color.g, color.b, color.a);
+ rlVertex2f(point[7].x, point[7].y);
+ rlVertex2f(point[6].x, point[6].y);
+ rlVertex2f(point[14].x, point[14].y);
+ rlVertex2f(point[15].x, point[15].y);
+ rlVertex2f(point[7].x, point[7].y);
+ rlVertex2f(point[14].x, point[14].y);
+ rlEnd();
+#endif
}
// Draw a polygon of n sides
diff --git a/src/rtext.c b/src/rtext.c
index df9978838..556aef95d 100644
--- a/src/rtext.c
+++ b/src/rtext.c
@@ -58,8 +58,8 @@
#include "rlgl.h" // OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2 -> Only DrawTextPro()
#include // Required for: malloc(), free()
-#include // Required for: vsprintf()
-#include // Required for: strcmp(), strstr(), strncpy() [Used in TextReplace()], sscanf() [Used in LoadBMFont()]
+#include // Required for: vsprintf(), snprintf()
+#include // Required for: strcmp(), strstr(), strncpy(), sscanf() [Used in LoadBMFont()]
#include // Required for: va_list, va_start(), vsprintf(), va_end() [Used in TextFormat()]
#include // Required for: toupper(), tolower() [Used in TextToUpper(), TextToLower()]
@@ -539,7 +539,7 @@ Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int
Font font = { 0 };
char fileExtLower[16] = { 0 };
- strncpy(fileExtLower, TextToLower(fileType), 16 - 1);
+ snprintf(fileExtLower, 16, "%s", TextToLower(fileType));
font.baseSize = fontSize;
font.glyphPadding = 0;
@@ -1043,7 +1043,7 @@ bool ExportFontAsCode(Font font, const char *fileName)
// Get file name from path
char fileNamePascal[256] = { 0 };
- strncpy(fileNamePascal, TextToPascal(GetFileNameWithoutExt(fileName)), 256 - 1);
+ snprintf(fileNamePascal, 256, "%s", TextToPascal(GetFileNameWithoutExt(fileName)));
// Get font atlas image and size, required to estimate code file size
// NOTE: This mechanism is highly coupled to raylib
@@ -1545,7 +1545,7 @@ char **LoadTextLines(const char *text, int *count)
if ((text[i] == '\n') || (text[i] == '\0'))
{
lines[l] = (char *)RL_CALLOC(lineLen + 1, 1);
- strncpy(lines[l], &text[i - lineLen], lineLen);
+ memcpy(lines[l], &text[i - lineLen], lineLen);
lineLen = 0;
l++;
}
@@ -1712,7 +1712,7 @@ const char *TextSubtext(const char *text, int position, int length)
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
- if (text != NULL)
+ if ((text != NULL) && (position >= 0) && (length > 0))
{
int textLength = TextLength(text);
@@ -1768,8 +1768,8 @@ char *GetTextBetween(const char *text, const char *begin, const char *end)
{
endIndex += (beginIndex + beginLen);
int len = (endIndex - beginIndex - beginLen);
- if (len < (MAX_TEXT_BUFFER_LENGTH - 1)) strncpy(buffer, text + beginIndex + beginLen, len);
- else strncpy(buffer, text + beginIndex + beginLen, MAX_TEXT_BUFFER_LENGTH - 1);
+ if (len < (MAX_TEXT_BUFFER_LENGTH - 1)) memcpy(buffer, text + beginIndex + beginLen, len);
+ else snprintf(buffer, MAX_TEXT_BUFFER_LENGTH, "%s", text + beginIndex + beginLen);
}
}
@@ -1777,7 +1777,7 @@ char *GetTextBetween(const char *text, const char *begin, const char *end)
}
// Replace text string
-// REQUIRES: strstr(), strncpy()
+// REQUIRES: strstr(), memcpy()
// NOTE: Limited text replace functionality, using static string
char *TextReplace(const char *text, const char *search, const char *replacement)
{
@@ -1834,7 +1834,7 @@ char *TextReplace(const char *text, const char *search, const char *replacement)
// Copy remaind text part after replacement to result (pointed by moving temp)
// NOTE: Text pointer internal copy has been updated along the process
- strncpy(tempPtr, text, TextLength(text));
+ memcpy(tempPtr, text, TextLength(text));
}
else TRACELOG(LOG_WARNING, "Text with replacement is longer than internal buffer, use TextReplaceAlloc()");
}
@@ -1843,7 +1843,7 @@ char *TextReplace(const char *text, const char *search, const char *replacement)
}
// Replace text string
-// REQUIRES: strstr(), strncpy()
+// REQUIRES: strstr(), memcpy()
// WARNING: Allocated memory must be manually freed
char *TextReplaceAlloc(const char *text, const char *search, const char *replacement)
{
@@ -1900,7 +1900,7 @@ char *TextReplaceAlloc(const char *text, const char *search, const char *replace
// Copy remaind text part after replacement to result (pointed by moving temp)
// NOTE: Text pointer internal copy has been updated along the process
- strncpy(temp, text, TextLength(text));
+ memcpy(temp, text, TextLength(text));
}
}
@@ -1988,10 +1988,11 @@ char *TextInsert(const char *text, const char *insert, int position)
{
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
+ int textLen = TextLength(text);
- if ((text != NULL) && (insert != NULL))
+ if ((text != NULL) && (insert != NULL) && (position >= 0))
{
- int textLen = TextLength(text);
+ if (position > textLen) position = textLen; // End of text string
int insertLen = TextLength(insert);
if ((textLen + insertLen) < (MAX_TEXT_BUFFER_LENGTH - 1))
@@ -2000,7 +2001,7 @@ char *TextInsert(const char *text, const char *insert, int position)
for (int i = 0; i < position; i++) buffer[i] = text[i];
for (int i = position; i < insertLen + position; i++) buffer[i] = insert[i - position];
- for (int i = (insertLen + position); i < (textLen + insertLen); i++) buffer[i] = text[i];
+ for (int i = (insertLen + position); i < (textLen + insertLen); i++) buffer[i] = text[i - insertLen];
buffer[textLen + insertLen] = '\0'; // Add EOL
}
@@ -2015,17 +2016,18 @@ char *TextInsert(const char *text, const char *insert, int position)
char *TextInsertAlloc(const char *text, const char *insert, int position)
{
char *result = NULL;
+ int textLen = TextLength(text);
- if ((text != NULL) && (insert != NULL))
+ if ((text != NULL) && (insert != NULL) && (position >= 0))
{
- int textLen = TextLength(text);
+ if (position > textLen) position = textLen; // End of text string
int insertLen = TextLength(insert);
result = (char *)RL_MALLOC(textLen + insertLen + 1);
for (int i = 0; i < position; i++) result[i] = text[i];
- for (int i = position; i < insertLen + position; i++) result[i] = insert[i - position];
- for (int i = (insertLen + position); i < (textLen + insertLen); i++) result[i] = text[i];
+ for (int i = position; i < (insertLen + position); i++) result[i] = insert[i - position];
+ for (int i = (insertLen + position); i < (textLen + insertLen); i++) result[i] = text[i - insertLen];
result[textLen + insertLen] = '\0'; // Add EOL
}
@@ -2049,7 +2051,7 @@ char *TextJoin(char **textList, int count, const char *delimiter)
int textLength = TextLength(textList[i]);
// Make sure joined text could fit inside MAX_TEXT_BUFFER_LENGTH
- if ((totalLength + textLength) < MAX_TEXT_BUFFER_LENGTH)
+ if ((totalLength + textLength + delimiterLen) < MAX_TEXT_BUFFER_LENGTH)
{
memcpy(textPtr, textList[i], textLength);
totalLength += textLength;
diff --git a/src/rtextures.c b/src/rtextures.c
index 6092cb57c..61e528d47 100644
--- a/src/rtextures.c
+++ b/src/rtextures.c
@@ -70,6 +70,7 @@
#include // Required for: strlen() [Used in ImageTextEx()], strcmp() [Used in LoadImageFromMemory()/LoadImageAnimFromMemory()/ExportImageToMemory()]
#include // Required for: fabsf() [Used in DrawTextureRec()]
#include // Required for: sprintf() [Used in ExportImageAsCode()]
+#include // Required for: INT_MAX
// Support only desired texture formats on stb_image
#if !SUPPORT_FILEFORMAT_BMP
@@ -813,7 +814,7 @@ bool ExportImageAsCode(Image image, const char *fileName)
// Get file name from path and convert variable name to uppercase
char varFileName[256] = { 0 };
- strncpy(varFileName, GetFileNameWithoutExt(fileName), 256 - 1); // NOTE: Using function provided by [rcore] module
+ snprintf(varFileName, 256, "%s", GetFileNameWithoutExt(fileName)); // NOTE: Using function provided by [rcore] module
for (int i = 0; varFileName[i] != '\0'; i++) if ((varFileName[i] >= 'a') && (varFileName[i] <= 'z')) { varFileName[i] = varFileName[i] - 32; }
// Add image information
@@ -843,9 +844,10 @@ bool ExportImageAsCode(Image image, const char *fileName)
// Generate image: plain color
Image GenImageColor(int width, int height, Color color)
{
- Color *pixels = (Color *)RL_CALLOC(width*height, sizeof(Color));
+ int dataSize = GetPixelDataSize(width, height, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8);
+ Color *pixels = (Color *)RL_CALLOC(dataSize, 1);
- for (int i = 0; i < width*height; i++) pixels[i] = color;
+ for (int i = 0; (pixels != NULL) && (i < width*height); i++) pixels[i] = color;
Image image = {
.data = pixels,
@@ -1228,18 +1230,25 @@ Image ImageFromImage(Image image, Rectangle rec)
{
Image result = { 0 };
- int bytesPerPixel = GetPixelDataSize(1, 1, image.format);
-
- result.width = (int)rec.width;
- result.height = (int)rec.height;
- result.data = RL_CALLOC((int)rec.width*(int)rec.height*bytesPerPixel, 1);
- result.format = image.format;
- result.mipmaps = 1;
-
- for (int y = 0; y < (int)rec.height; y++)
+ // Basic rectangle validation: size smaller than image size
+ if ((rec.x >= 0) && (rec.y >= 0) && (rec.width > 0) && (rec.height > 0) &&
+ (((int)rec.x + (int)rec.width) <= image.width) &&
+ (((int)rec.y + (int)rec.height) <= image.height))
{
- memcpy(((unsigned char *)result.data) + y*(int)rec.width*bytesPerPixel, ((unsigned char *)image.data) + ((y + (int)rec.y)*image.width + (int)rec.x)*bytesPerPixel, (int)rec.width*bytesPerPixel);
+ int bytesPerPixel = GetPixelDataSize(1, 1, image.format);
+
+ result.width = (int)rec.width;
+ result.height = (int)rec.height;
+ result.data = RL_CALLOC((int)rec.width*(int)rec.height*bytesPerPixel, 1);
+ result.format = image.format;
+ result.mipmaps = 1;
+
+ for (int y = 0; y < (int)rec.height; y++)
+ {
+ memcpy(((unsigned char *)result.data) + y*(int)rec.width*bytesPerPixel, ((unsigned char *)image.data) + ((y + (int)rec.y)*image.width + (int)rec.x)*bytesPerPixel, (int)rec.width*bytesPerPixel);
+ }
}
+ else TRACELOG(LOG_WARNING, "IMAGE: Rectangle provided for ImageToImage not valid");
return result;
}
@@ -2684,45 +2693,49 @@ void ImageRotate(Image *image, int degrees)
int width = (int)(fabsf(image->width*cosRadius) + fabsf(image->height*sinRadius));
int height = (int)(fabsf(image->height*cosRadius) + fabsf(image->width*sinRadius));
+ int dataSize = GetPixelDataSize(width, height, image->format);
int bytesPerPixel = GetPixelDataSize(1, 1, image->format);
- unsigned char *rotatedData = (unsigned char *)RL_CALLOC(width*height, bytesPerPixel);
+ unsigned char *rotatedData = (unsigned char *)RL_CALLOC(dataSize, 1);
- for (int y = 0; y < height; y++)
+ if (rotatedData != NULL)
{
- for (int x = 0; x < width; x++)
+ for (int y = 0; y < height; y++)
{
- float oldX = ((x - width/2.0f)*cosRadius + (y - height/2.0f)*sinRadius) + image->width/2.0f;
- float oldY = ((y - height/2.0f)*cosRadius - (x - width/2.0f)*sinRadius) + image->height/2.0f;
-
- if ((oldX >= 0) && (oldX < image->width) && (oldY >= 0) && (oldY < image->height))
+ for (int x = 0; x < width; x++)
{
- int x1 = (int)floorf(oldX);
- int y1 = (int)floorf(oldY);
- int x2 = MIN(x1 + 1, image->width - 1);
- int y2 = MIN(y1 + 1, image->height - 1);
+ float oldX = ((x - width/2.0f)*cosRadius + (y - height/2.0f)*sinRadius) + image->width/2.0f;
+ float oldY = ((y - height/2.0f)*cosRadius - (x - width/2.0f)*sinRadius) + image->height/2.0f;
- float px = oldX - x1;
- float py = oldY - y1;
-
- for (int i = 0; i < bytesPerPixel; i++)
+ if ((oldX >= 0) && (oldX < image->width) && (oldY >= 0) && (oldY < image->height))
{
- float f1 = ((unsigned char *)image->data)[(y1*image->width + x1)*bytesPerPixel + i];
- float f2 = ((unsigned char *)image->data)[(y1*image->width + x2)*bytesPerPixel + i];
- float f3 = ((unsigned char *)image->data)[(y2*image->width + x1)*bytesPerPixel + i];
- float f4 = ((unsigned char *)image->data)[(y2*image->width + x2)*bytesPerPixel + i];
+ int x1 = (int)floorf(oldX);
+ int y1 = (int)floorf(oldY);
+ int x2 = MIN(x1 + 1, image->width - 1);
+ int y2 = MIN(y1 + 1, image->height - 1);
- float val = f1*(1 - px)*(1 - py) + f2*px*(1 - py) + f3*(1 - px)*py + f4*px*py;
+ float px = oldX - x1;
+ float py = oldY - y1;
- rotatedData[(y*width + x)*bytesPerPixel + i] = (unsigned char)val;
+ for (int i = 0; i < bytesPerPixel; i++)
+ {
+ float f1 = ((unsigned char *)image->data)[(y1*image->width + x1)*bytesPerPixel + i];
+ float f2 = ((unsigned char *)image->data)[(y1*image->width + x2)*bytesPerPixel + i];
+ float f3 = ((unsigned char *)image->data)[(y2*image->width + x1)*bytesPerPixel + i];
+ float f4 = ((unsigned char *)image->data)[(y2*image->width + x2)*bytesPerPixel + i];
+
+ float val = f1*(1 - px)*(1 - py) + f2*px*(1 - py) + f3*(1 - px)*py + f4*px*py;
+
+ rotatedData[(y*width + x)*bytesPerPixel + i] = (unsigned char)val;
+ }
}
}
}
- }
- RL_FREE(image->data);
- image->data = rotatedData;
- image->width = width;
- image->height = height;
+ RL_FREE(image->data);
+ image->data = rotatedData;
+ image->width = width;
+ image->height = height;
+ }
}
}
@@ -3927,7 +3940,7 @@ void ImageDrawRectanglePro(Image *dst, Rectangle rec, Vector2 origin, float rota
// Draw rectangle lines within an image
void ImageDrawRectangleLines(Image *dst, int posX, int posY, int width, int height, Color color)
{
- Rectangle rec = { posX, posY, width, height };
+ Rectangle rec = { (float)posX, (float)posY, (float)width, (float)height };
ImageDrawRectangleLinesEx(dst, rec, 1, color);
}
@@ -4019,8 +4032,8 @@ void ImageDrawCircleGradient(Image *dst, Vector2 center, float radius, Color inn
// Draw an image within an image
void ImageDrawImage(Image *dst, Image src, int posX, int posY, Color tint)
{
- Rectangle srcRec = { 0, 0, src.width, src.height };
- Rectangle dstRec = { posX, posY, srcRec.width, srcRec.height };
+ Rectangle srcRec = { 0.0f, 0.0f, (float)src.width, (float)src.height };
+ Rectangle dstRec = { (float)posX, (float)posY, srcRec.width, srcRec.height };
ImageDrawImagePro(dst, src, srcRec, dstRec, (Vector2){ 0 }, 0.0f, tint);
}
@@ -5501,17 +5514,24 @@ int GetPixelDataSize(int width, int height, int format)
case PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: bpp = 2; break;
default: break;
}
+
+ unsigned long long dataSizeBytes = ((unsigned long long)width*height*bpp) >> 3; // Get size in bytes (dividing by 8)
- double bytesPerPixel = (double)bpp/8.0;
- dataSize = (int)(bytesPerPixel*width*height); // Total data size in bytes
-
- // Most compressed formats works on 4x4 blocks,
- // if texture is smaller, minimum dataSize is 8 or 16
- if ((width < 4) && (height < 4))
+ if (dataSizeBytes < INT_MAX)
{
- if ((format >= PIXELFORMAT_COMPRESSED_DXT1_RGB) && (format < PIXELFORMAT_COMPRESSED_DXT3_RGBA)) dataSize = 8;
- else if ((format >= PIXELFORMAT_COMPRESSED_DXT3_RGBA) && (format < PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA)) dataSize = 16;
+ dataSize = (int)dataSizeBytes;
+
+ // Most compressed formats works on 4x4 blocks,
+ // if texture is smaller, minimum dataSize is 8 or 16
+ if ((width < 4) && (height < 4))
+ {
+ if ((format >= PIXELFORMAT_COMPRESSED_DXT1_RGB) && (format < PIXELFORMAT_COMPRESSED_DXT3_RGBA)) dataSize = 8;
+ else if ((format >= PIXELFORMAT_COMPRESSED_DXT3_RGBA) && (format < PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA)) dataSize = 16;
+ }
}
+
+ // NOTE: In case required image data larger than 2GB, no memory allocated at all (NULL)
+ if (dataSize == 0) TRACELOG(LOG_WARNING, "Requested image size is larger than 2GB, it can not be allocated");
return dataSize;
}
diff --git a/tools/rexm/rexm.c b/tools/rexm/rexm.c
index f268a7d44..cb753e031 100644
--- a/tools/rexm/rexm.c
+++ b/tools/rexm/rexm.c
@@ -2331,7 +2331,7 @@ static rlExampleInfo *LoadExampleInfo(const char *exFileName)
// Example found in collection
exInfo = (rlExampleInfo *)RL_CALLOC(1, sizeof(rlExampleInfo));
- strncpy(exInfo->name, GetFileNameWithoutExt(exFileName), 128 - 1);
+ snprintf(exInfo->name, 128, "%s", GetFileNameWithoutExt(exFileName));
strncpy(exInfo->category, exInfo->name, TextFindIndex(exInfo->name, "_"));
char *exText = LoadFileText(exFileName);
@@ -2377,7 +2377,7 @@ static rlExampleInfo *LoadExampleInfo(const char *exFileName)
int copyrightIndex = TextFindIndex(exText, "Copyright (c) ");
int yearStartIndex = copyrightIndex + 14;
char yearText[5] = { 0 };
- strncpy(yearText, exText + yearStartIndex, 4);
+ snprintf(yearText, 5, "%s", exText + yearStartIndex);
exInfo->yearCreated = TextToInteger(yearText);
// Check for review year included (or just use creation year)
if (exText[yearStartIndex + 4] == '-') strncpy(yearText, exText + yearStartIndex + 5, 4);
@@ -2425,7 +2425,7 @@ static int ParseExampleInfoLine(const char *line, rlExampleInfo *entry)
#define MAX_EXAMPLE_INFO_LINE_LEN 512
char temp[MAX_EXAMPLE_INFO_LINE_LEN] = { 0 };
- strncpy(temp, line, MAX_EXAMPLE_INFO_LINE_LEN);
+ snprintf(temp, MAX_EXAMPLE_INFO_LINE_LEN, "%s", line);
temp[MAX_EXAMPLE_INFO_LINE_LEN - 1] = '\0'; // Ensure null termination
int tokenCount = 0;
@@ -2902,7 +2902,7 @@ static void UpdateWebMetadata(const char *exHtmlPath, const char *exFilePath)
char exTitle[64] = { 0 }; // Example title: fileName without extension, replacing underscores by spaces
// Get example name: replace underscore by spaces
- strncpy(exName, GetFileNameWithoutExt(exHtmlPathCopy), 64 - 1);
+ snprintf(exName, 64, "%s", GetFileNameWithoutExt(exHtmlPathCopy));
strcpy(exTitle, exName);
for (int i = 0; (i < 64) && (exTitle[i] != '\0'); i++) { if (exTitle[i] == '_') exTitle[i] = ' '; }
diff --git a/tools/rlparser/output/raylib_api.json b/tools/rlparser/output/raylib_api.json
index de1ebc884..2e6916737 100644
--- a/tools/rlparser/output/raylib_api.json
+++ b/tools/rlparser/output/raylib_api.json
@@ -968,7 +968,7 @@
"description": "Skeleton, animation bones hierarchy",
"fields": [
{
- "type": "int",
+ "type": "unsigned int",
"name": "boneCount",
"description": "Number of bones"
},
@@ -1045,7 +1045,7 @@
"description": "Animation name"
},
{
- "type": "int",
+ "type": "unsigned int",
"name": "boneCount",
"description": "Number of bones (per pose)"
},
diff --git a/tools/rlparser/output/raylib_api.lua b/tools/rlparser/output/raylib_api.lua
index 98308682d..574cfbf2d 100644
--- a/tools/rlparser/output/raylib_api.lua
+++ b/tools/rlparser/output/raylib_api.lua
@@ -968,7 +968,7 @@ return {
description = "Skeleton, animation bones hierarchy",
fields = {
{
- type = "int",
+ type = "unsigned int",
name = "boneCount",
description = "Number of bones"
},
@@ -1045,7 +1045,7 @@ return {
description = "Animation name"
},
{
- type = "int",
+ type = "unsigned int",
name = "boneCount",
description = "Number of bones (per pose)"
},
diff --git a/tools/rlparser/output/raylib_api.sexpr b/tools/rlparser/output/raylib_api.sexpr
index e4dee877c..e57c282a3 100644
--- a/tools/rlparser/output/raylib_api.sexpr
+++ b/tools/rlparser/output/raylib_api.sexpr
@@ -611,7 +611,7 @@
((name "ModelSkeleton")
(description "Skeleton, animation bones hierarchy")
(fields
- ((type "int")
+ ((type "unsigned int")
(name "boneCount")
(description "Number of bones"))
((type "BoneInfo *")
@@ -658,7 +658,7 @@
((type "char[32]")
(name "name")
(description "Animation name"))
- ((type "int")
+ ((type "unsigned int")
(name "boneCount")
(description "Number of bones (per pose)"))
((type "int")
diff --git a/tools/rlparser/output/raylib_api.txt b/tools/rlparser/output/raylib_api.txt
index 77a1dba1f..d0d60463c 100644
--- a/tools/rlparser/output/raylib_api.txt
+++ b/tools/rlparser/output/raylib_api.txt
@@ -448,7 +448,7 @@ Struct 20: BoneInfo (2 fields)
Struct 21: ModelSkeleton (3 fields)
Name: ModelSkeleton
Description: Skeleton, animation bones hierarchy
- Field[1]: int boneCount // Number of bones
+ Field[1]: unsigned int boneCount // Number of bones
Field[2]: BoneInfo * bones // Bones information (skeleton)
Field[3]: ModelAnimPose bindPose // Bones base transformation (Transform[])
Struct 22: Model (9 fields)
@@ -467,7 +467,7 @@ Struct 23: ModelAnimation (4 fields)
Name: ModelAnimation
Description: ModelAnimation, contains a full animation sequence
Field[1]: char[32] name // Animation name
- Field[2]: int boneCount // Number of bones (per pose)
+ Field[2]: unsigned int boneCount // Number of bones (per pose)
Field[3]: int keyframeCount // Number of animation key frames
Field[4]: ModelAnimPose * keyframePoses // Animation sequence keyframe poses [keyframe][pose]
Struct 24: Ray (2 fields)
diff --git a/tools/rlparser/output/raylib_api.xml b/tools/rlparser/output/raylib_api.xml
index b86c28b7a..77eb75c73 100644
--- a/tools/rlparser/output/raylib_api.xml
+++ b/tools/rlparser/output/raylib_api.xml
@@ -201,7 +201,7 @@
-
+
@@ -218,7 +218,7 @@
-
+