Merge branch 'master' of https://github.com/unklnik/raylib-go
This commit is contained in:
commit
64b853abaa
59 changed files with 38468 additions and 22154 deletions
60
.github/workflows/build.yml
vendored
60
.github/workflows/build.yml
vendored
|
@ -40,6 +40,66 @@ jobs:
|
||||||
run: go test -race -vet=off ./...
|
run: go test -race -vet=off ./...
|
||||||
working-directory: raylib
|
working-directory: raylib
|
||||||
|
|
||||||
|
test-drm:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
go-version: [1.19.x]
|
||||||
|
os: [ubuntu-latest]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- name: Install Go
|
||||||
|
uses: actions/setup-go@v3
|
||||||
|
with:
|
||||||
|
go-version: ${{ matrix.go-version }}
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Install package
|
||||||
|
run: |
|
||||||
|
sudo apt-get update -y; sudo apt-get -y install libegl1-mesa-dev libdrm-dev
|
||||||
|
- name: Build
|
||||||
|
run: go build -tags drm
|
||||||
|
working-directory: raylib
|
||||||
|
|
||||||
|
test-sdl:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
go-version: [1.19.x]
|
||||||
|
os: [ubuntu-latest]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- name: Install Go
|
||||||
|
uses: actions/setup-go@v3
|
||||||
|
with:
|
||||||
|
go-version: ${{ matrix.go-version }}
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Install package
|
||||||
|
run: |
|
||||||
|
sudo apt-get update -y; sudo apt-get -y install libgl1-mesa-dev libsdl2-dev
|
||||||
|
- name: Build
|
||||||
|
run: go build -tags sdl
|
||||||
|
working-directory: raylib
|
||||||
|
|
||||||
|
test-wayland:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
go-version: [1.19.x]
|
||||||
|
os: [ubuntu-latest]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- name: Install Go
|
||||||
|
uses: actions/setup-go@v3
|
||||||
|
with:
|
||||||
|
go-version: ${{ matrix.go-version }}
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Install package
|
||||||
|
run: |
|
||||||
|
sudo apt-get update -y; sudo apt-get -y install libgl1-mesa-dev libwayland-dev libxkbcommon-dev
|
||||||
|
- name: Build
|
||||||
|
run: go build -tags wayland
|
||||||
|
working-directory: raylib
|
||||||
|
|
||||||
test-examples:
|
test-examples:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
|
|
11
README.md
11
README.md
|
@ -42,19 +42,15 @@ You can also build binary in [MSYS2](https://msys2.github.io/) shell.
|
||||||
|
|
||||||
[Android example](https://github.com/gen2brain/raylib-go/tree/master/examples/others/android/example).
|
[Android example](https://github.com/gen2brain/raylib-go/tree/master/examples/others/android/example).
|
||||||
|
|
||||||
##### Raspberry Pi
|
|
||||||
|
|
||||||
[RPi example](https://github.com/gen2brain/raylib-go/tree/master/examples/others/rpi/basic_window).
|
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
|
|
||||||
go get -v -u github.com/gen2brain/raylib-go/raylib
|
go get -v -u github.com/gen2brain/raylib-go/raylib
|
||||||
|
|
||||||
### Build tags
|
### Build tags
|
||||||
|
|
||||||
* `drm` - build for Linux native mode, including Raspberry Pi 4 and other devices (PLATFORM_DRM)
|
* `drm` - build for Linux native DRM mode, including Raspberry Pi 4 and other devices (PLATFORM_DRM)
|
||||||
* `rpi` - build for Raspberry Pi platform (PLATFORM_RPI)
|
* `sdl` - build for SDL backend instead of internal GLFW (PLATFORM_DESKTOP_SDL)
|
||||||
* `wayland` - build against Wayland libraries
|
* `wayland` - build against Wayland libraries (internal GLFW)
|
||||||
* `noaudio` - disables audio functions
|
* `noaudio` - disables audio functions
|
||||||
* `opengl43` - uses OpenGL 4.3 backend
|
* `opengl43` - uses OpenGL 4.3 backend
|
||||||
* `opengl21` - uses OpenGL 2.1 backend (default is 3.3 on desktop)
|
* `opengl21` - uses OpenGL 2.1 backend (default is 3.3 on desktop)
|
||||||
|
@ -75,6 +71,7 @@ import rl "github.com/gen2brain/raylib-go/raylib"
|
||||||
func main() {
|
func main() {
|
||||||
rl.InitWindow(800, 450, "raylib [core] example - basic window")
|
rl.InitWindow(800, 450, "raylib [core] example - basic window")
|
||||||
defer rl.CloseWindow()
|
defer rl.CloseWindow()
|
||||||
|
|
||||||
rl.SetTargetFPS(60)
|
rl.SetTargetFPS(60)
|
||||||
|
|
||||||
for !rl.WindowShouldClose() {
|
for !rl.WindowShouldClose() {
|
||||||
|
|
|
@ -9,19 +9,22 @@ Export path to Android NDK, point to location where you have unpacked archive:
|
||||||
|
|
||||||
Add toolchain bin directory to PATH:
|
Add toolchain bin directory to PATH:
|
||||||
|
|
||||||
export PATH=${ANDROID_NDK_HOME}/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin:${PATH}
|
export PATH=${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin:${PATH}
|
||||||
|
|
||||||
Export sysroot and libdirs:
|
Export sysroot and libdirs:
|
||||||
|
|
||||||
export ANDROID_SYSROOT=${ANDROID_NDK_HOME}/sysroot
|
export ANDROID_SYSROOT=${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot
|
||||||
export ANDROID_PLATFORM=${ANDROID_NDK_HOME}/platforms/android-16/arch-arm
|
|
||||||
export ANDROID_TOOLCHAIN=${ANDROID_NDK_HOME}/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
|
export ANDROID_TOOLCHAIN=${ANDROID_NDK_HOME}/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
|
||||||
|
|
||||||
|
Export API version:
|
||||||
|
|
||||||
|
export ANDROID_API=16
|
||||||
|
|
||||||
And compile shared library:
|
And compile shared library:
|
||||||
|
|
||||||
CC="arm-linux-androideabi-gcc" \
|
CC="armv7a-linux-androideabi${ANDROID_API}-clang" \
|
||||||
CGO_CFLAGS="-I${ANDROID_SYSROOT}/usr/include -I${ANDROID_SYSROOT}/usr/include/arm-linux-androideabi --sysroot=${ANDROID_SYSROOT} -D__ANDROID_API__=16" \
|
CGO_CFLAGS="-I${ANDROID_SYSROOT}/usr/include -I${ANDROID_SYSROOT}/usr/include/arm-linux-androideabi --sysroot=${ANDROID_SYSROOT} -D__ANDROID_API__=${ANDROID_API}" \
|
||||||
CGO_LDFLAGS="-L${ANDROID_SYSROOT}/usr/lib/arm-linux-androideabi -L${ANDROID_PLATFORM}/usr/lib -L${ANDROID_TOOLCHAIN}/arm-linux-androideabi/lib -L${ANDROID_TOOLCHAIN}/lib/gcc/arm-linux-androideabi/4.9.x --sysroot=${ANDROID_PLATFORM}" \
|
CGO_LDFLAGS="-L${ANDROID_SYSROOT}/usr/lib/arm-linux-androideabi/${ANDROID_API} -L${ANDROID_TOOLCHAIN}/arm-linux-androideabi/lib -L${ANDROID_TOOLCHAIN}/lib/gcc/arm-linux-androideabi/4.9.x --sysroot=${ANDROID_SYSROOT}" \
|
||||||
CGO_ENABLED=1 GOOS=android GOARCH=arm \
|
CGO_ENABLED=1 GOOS=android GOARCH=arm \
|
||||||
go build -buildmode=c-shared -ldflags="-s -w -extldflags=-Wl,-soname,libexample.so" \
|
go build -buildmode=c-shared -ldflags="-s -w -extldflags=-Wl,-soname,libexample.so" \
|
||||||
-o=android/libs/armeabi-v7a/libexample.so
|
-o=android/libs/armeabi-v7a/libexample.so
|
||||||
|
@ -40,3 +43,6 @@ Or with gradle:
|
||||||
./gradlew assembleDebug
|
./gradlew assembleDebug
|
||||||
|
|
||||||
If everything is successfully built apk can be found in bin/ directory or in the android/build/outputs in case `gradle` is used.
|
If everything is successfully built apk can be found in bin/ directory or in the android/build/outputs in case `gradle` is used.
|
||||||
|
|
||||||
|
|
||||||
|
For aarch64/arm64 replace `arm-linux-androideabi` with `aarch64-linux-android`, set GOARCH to arm64 and use minimum `ANDROID_API=21`.
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
### Raspberry Pi example
|
|
||||||
|
|
||||||
To cross compile example for Raspberry Pi you will need [RPi toolchain](https://github.com/raspberrypi/tools/tree/master/arm-bcm2708) and [userspace libraries](https://github.com/raspberrypi/firmware) (opt/vc).
|
|
||||||
|
|
||||||
Export path to RPi toolchain:
|
|
||||||
|
|
||||||
export RPI_HOME=/opt/tools/arm-bcm2708/arm-linux-gnueabihf
|
|
||||||
|
|
||||||
Add toolchain bin directory to PATH:
|
|
||||||
|
|
||||||
export PATH=${RPI_HOME}/bin:${PATH}
|
|
||||||
|
|
||||||
And compile example:
|
|
||||||
|
|
||||||
CC=arm-linux-gnueabihf-gcc \
|
|
||||||
CGO_CFLAGS="-I/opt/vc/include -I/opt/vc/include/interface/vcos -I/opt/vc/include/interface/vmcs_host/linux -I/opt/vc/include/interface/vcos/pthreads --sysroot=${RPI_HOME}/arm-linux-gnueabihf/sysroot" \
|
|
||||||
CGO_LDFLAGS="-L/opt/vc/lib -L/opt/vc/lib64 --sysroot=${RPI_HOME}/arm-linux-gnueabihf/sysroot" \
|
|
||||||
CGO_ENABLED=1 GOOS=linux GOARCH=arm go build
|
|
|
@ -1,21 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import "github.com/gen2brain/raylib-go/raylib"
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
rl.InitWindow(800, 450, "raylib [rpi] example - basic window")
|
|
||||||
|
|
||||||
rl.SetTargetFPS(60)
|
|
||||||
|
|
||||||
for !rl.WindowShouldClose() {
|
|
||||||
rl.BeginDrawing()
|
|
||||||
|
|
||||||
rl.ClearBackground(rl.RayWhite)
|
|
||||||
|
|
||||||
rl.DrawText("Congrats! You created your first window!", 190, 200, 20, rl.LightGray)
|
|
||||||
|
|
||||||
rl.EndDrawing()
|
|
||||||
}
|
|
||||||
|
|
||||||
rl.CloseWindow()
|
|
||||||
}
|
|
141
raygui/raylib.h
141
raygui/raylib.h
|
@ -1,6 +1,6 @@
|
||||||
/**********************************************************************************************
|
/**********************************************************************************************
|
||||||
*
|
*
|
||||||
* raylib v4.5 - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com)
|
* raylib v4.6-dev - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com)
|
||||||
*
|
*
|
||||||
* FEATURES:
|
* FEATURES:
|
||||||
* - NO external dependencies, all required libraries included with raylib
|
* - NO external dependencies, all required libraries included with raylib
|
||||||
|
@ -81,10 +81,10 @@
|
||||||
|
|
||||||
#include <stdarg.h> // Required for: va_list - Only used by TraceLogCallback
|
#include <stdarg.h> // Required for: va_list - Only used by TraceLogCallback
|
||||||
|
|
||||||
#define RAYLIB_VERSION_MAJOR 4
|
#define RAYLIB_VERSION_MAJOR 5
|
||||||
#define RAYLIB_VERSION_MINOR 5
|
#define RAYLIB_VERSION_MINOR 0
|
||||||
#define RAYLIB_VERSION_PATCH 0
|
#define RAYLIB_VERSION_PATCH 0
|
||||||
#define RAYLIB_VERSION "4.5"
|
#define RAYLIB_VERSION "5.0"
|
||||||
|
|
||||||
// Function specifiers in case library is build/used as a shared library (Windows)
|
// Function specifiers in case library is build/used as a shared library (Windows)
|
||||||
// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
|
// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
|
||||||
|
@ -133,12 +133,20 @@
|
||||||
|
|
||||||
// NOTE: MSVC C++ compiler does not support compound literals (C99 feature)
|
// NOTE: MSVC C++ compiler does not support compound literals (C99 feature)
|
||||||
// Plain structures in C++ (without constructors) can be initialized with { }
|
// Plain structures in C++ (without constructors) can be initialized with { }
|
||||||
|
// This is called aggregate initialization (C++11 feature)
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
#define CLITERAL(type) type
|
#define CLITERAL(type) type
|
||||||
#else
|
#else
|
||||||
#define CLITERAL(type) (type)
|
#define CLITERAL(type) (type)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Some compilers (mostly macos clang) default to C++98,
|
||||||
|
// where aggregate initialization can't be used
|
||||||
|
// So, give a more clear error stating how to fix this
|
||||||
|
#if !defined(_MSC_VER) && (defined(__cplusplus) && __cplusplus < 201103L)
|
||||||
|
#error "C++11 or later is required. Add -std=c++11"
|
||||||
|
#endif
|
||||||
|
|
||||||
// NOTE: We set some defines with some data types declared by raylib
|
// NOTE: We set some defines with some data types declared by raylib
|
||||||
// Other modules (raymath, rlgl) also require some of those types, so,
|
// Other modules (raymath, rlgl) also require some of those types, so,
|
||||||
// to be able to use those other modules as standalone (not depending on raylib)
|
// to be able to use those other modules as standalone (not depending on raylib)
|
||||||
|
@ -402,6 +410,7 @@ typedef struct ModelAnimation {
|
||||||
int frameCount; // Number of animation frames
|
int frameCount; // Number of animation frames
|
||||||
BoneInfo *bones; // Bones information (skeleton)
|
BoneInfo *bones; // Bones information (skeleton)
|
||||||
Transform **framePoses; // Poses array by frame
|
Transform **framePoses; // Poses array by frame
|
||||||
|
char name[32]; // Animation name
|
||||||
} ModelAnimation;
|
} ModelAnimation;
|
||||||
|
|
||||||
// Ray, ray for raycasting
|
// Ray, ray for raycasting
|
||||||
|
@ -497,6 +506,20 @@ typedef struct FilePathList {
|
||||||
char **paths; // Filepaths entries
|
char **paths; // Filepaths entries
|
||||||
} FilePathList;
|
} FilePathList;
|
||||||
|
|
||||||
|
// Automation event
|
||||||
|
typedef struct AutomationEvent {
|
||||||
|
unsigned int frame; // Event frame
|
||||||
|
unsigned int type; // Event type (AutomationEventType)
|
||||||
|
int params[4]; // Event parameters (if required)
|
||||||
|
} AutomationEvent;
|
||||||
|
|
||||||
|
// Automation event list
|
||||||
|
typedef struct AutomationEventList {
|
||||||
|
unsigned int capacity; // Events max entries (MAX_AUTOMATION_EVENTS)
|
||||||
|
unsigned int count; // Events entries count
|
||||||
|
AutomationEvent *events; // Events entries
|
||||||
|
} AutomationEventList;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Enumerators Definition
|
// Enumerators Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
@ -517,6 +540,7 @@ typedef enum {
|
||||||
FLAG_WINDOW_TRANSPARENT = 0x00000010, // Set to allow transparent framebuffer
|
FLAG_WINDOW_TRANSPARENT = 0x00000010, // Set to allow transparent framebuffer
|
||||||
FLAG_WINDOW_HIGHDPI = 0x00002000, // Set to support HighDPI
|
FLAG_WINDOW_HIGHDPI = 0x00002000, // Set to support HighDPI
|
||||||
FLAG_WINDOW_MOUSE_PASSTHROUGH = 0x00004000, // Set to support mouse passthrough, only supported when FLAG_WINDOW_UNDECORATED
|
FLAG_WINDOW_MOUSE_PASSTHROUGH = 0x00004000, // Set to support mouse passthrough, only supported when FLAG_WINDOW_UNDECORATED
|
||||||
|
FLAG_BORDERLESS_WINDOWED_MODE = 0x00008000, // Set to run program in borderless windowed mode
|
||||||
FLAG_MSAA_4X_HINT = 0x00000020, // Set to try enabling MSAA 4X
|
FLAG_MSAA_4X_HINT = 0x00000020, // Set to try enabling MSAA 4X
|
||||||
FLAG_INTERLACED_HINT = 0x00010000 // Set to try enabling interlaced video format (for V3D)
|
FLAG_INTERLACED_HINT = 0x00010000 // Set to try enabling interlaced video format (for V3D)
|
||||||
} ConfigFlags;
|
} ConfigFlags;
|
||||||
|
@ -802,6 +826,9 @@ typedef enum {
|
||||||
PIXELFORMAT_UNCOMPRESSED_R32, // 32 bpp (1 channel - float)
|
PIXELFORMAT_UNCOMPRESSED_R32, // 32 bpp (1 channel - float)
|
||||||
PIXELFORMAT_UNCOMPRESSED_R32G32B32, // 32*3 bpp (3 channels - float)
|
PIXELFORMAT_UNCOMPRESSED_R32G32B32, // 32*3 bpp (3 channels - float)
|
||||||
PIXELFORMAT_UNCOMPRESSED_R32G32B32A32, // 32*4 bpp (4 channels - float)
|
PIXELFORMAT_UNCOMPRESSED_R32G32B32A32, // 32*4 bpp (4 channels - float)
|
||||||
|
PIXELFORMAT_UNCOMPRESSED_R16, // 16 bpp (1 channel - half float)
|
||||||
|
PIXELFORMAT_UNCOMPRESSED_R16G16B16, // 16*3 bpp (3 channels - half float)
|
||||||
|
PIXELFORMAT_UNCOMPRESSED_R16G16B16A16, // 16*4 bpp (4 channels - half float)
|
||||||
PIXELFORMAT_COMPRESSED_DXT1_RGB, // 4 bpp (no alpha)
|
PIXELFORMAT_COMPRESSED_DXT1_RGB, // 4 bpp (no alpha)
|
||||||
PIXELFORMAT_COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha)
|
PIXELFORMAT_COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha)
|
||||||
PIXELFORMAT_COMPRESSED_DXT3_RGBA, // 8 bpp
|
PIXELFORMAT_COMPRESSED_DXT3_RGBA, // 8 bpp
|
||||||
|
@ -905,8 +932,8 @@ typedef enum {
|
||||||
// Callbacks to hook some internal functions
|
// Callbacks to hook some internal functions
|
||||||
// WARNING: These callbacks are intended for advance users
|
// WARNING: These callbacks are intended for advance users
|
||||||
typedef void (*TraceLogCallback)(int logLevel, const char *text, va_list args); // Logging: Redirect trace log messages
|
typedef void (*TraceLogCallback)(int logLevel, const char *text, va_list args); // Logging: Redirect trace log messages
|
||||||
typedef unsigned char *(*LoadFileDataCallback)(const char *fileName, unsigned int *bytesRead); // FileIO: Load binary data
|
typedef unsigned char *(*LoadFileDataCallback)(const char *fileName, int *dataSize); // FileIO: Load binary data
|
||||||
typedef bool (*SaveFileDataCallback)(const char *fileName, void *data, unsigned int bytesToWrite); // FileIO: Save binary data
|
typedef bool (*SaveFileDataCallback)(const char *fileName, void *data, int dataSize); // FileIO: Save binary data
|
||||||
typedef char *(*LoadFileTextCallback)(const char *fileName); // FileIO: Load text data
|
typedef char *(*LoadFileTextCallback)(const char *fileName); // FileIO: Load text data
|
||||||
typedef bool (*SaveFileTextCallback)(const char *fileName, char *text); // FileIO: Save text data
|
typedef bool (*SaveFileTextCallback)(const char *fileName, char *text); // FileIO: Save text data
|
||||||
|
|
||||||
|
@ -925,8 +952,8 @@ extern "C" { // Prevents name mangling of functions
|
||||||
|
|
||||||
// Window-related functions
|
// Window-related functions
|
||||||
RLAPI void InitWindow(int width, int height, const char *title); // Initialize window and OpenGL context
|
RLAPI void InitWindow(int width, int height, const char *title); // Initialize window and OpenGL context
|
||||||
RLAPI bool WindowShouldClose(void); // Check if KEY_ESCAPE pressed or Close icon pressed
|
|
||||||
RLAPI void CloseWindow(void); // Close window and unload OpenGL context
|
RLAPI void CloseWindow(void); // Close window and unload OpenGL context
|
||||||
|
RLAPI bool WindowShouldClose(void); // Check if application should close (KEY_ESCAPE pressed or windows close icon clicked)
|
||||||
RLAPI bool IsWindowReady(void); // Check if window has been initialized successfully
|
RLAPI bool IsWindowReady(void); // Check if window has been initialized successfully
|
||||||
RLAPI bool IsWindowFullscreen(void); // Check if window is currently fullscreen
|
RLAPI bool IsWindowFullscreen(void); // Check if window is currently fullscreen
|
||||||
RLAPI bool IsWindowHidden(void); // Check if window is currently hidden (only PLATFORM_DESKTOP)
|
RLAPI bool IsWindowHidden(void); // Check if window is currently hidden (only PLATFORM_DESKTOP)
|
||||||
|
@ -938,17 +965,20 @@ RLAPI bool IsWindowState(unsigned int flag); // Check if on
|
||||||
RLAPI void SetWindowState(unsigned int flags); // Set window configuration state using flags (only PLATFORM_DESKTOP)
|
RLAPI void SetWindowState(unsigned int flags); // Set window configuration state using flags (only PLATFORM_DESKTOP)
|
||||||
RLAPI void ClearWindowState(unsigned int flags); // Clear window configuration state flags
|
RLAPI void ClearWindowState(unsigned int flags); // Clear window configuration state flags
|
||||||
RLAPI void ToggleFullscreen(void); // Toggle window state: fullscreen/windowed (only PLATFORM_DESKTOP)
|
RLAPI void ToggleFullscreen(void); // Toggle window state: fullscreen/windowed (only PLATFORM_DESKTOP)
|
||||||
|
RLAPI void ToggleBorderlessWindowed(void); // Toggle window state: borderless windowed (only PLATFORM_DESKTOP)
|
||||||
RLAPI void MaximizeWindow(void); // Set window state: maximized, if resizable (only PLATFORM_DESKTOP)
|
RLAPI void MaximizeWindow(void); // Set window state: maximized, if resizable (only PLATFORM_DESKTOP)
|
||||||
RLAPI void MinimizeWindow(void); // Set window state: minimized, if resizable (only PLATFORM_DESKTOP)
|
RLAPI void MinimizeWindow(void); // Set window state: minimized, if resizable (only PLATFORM_DESKTOP)
|
||||||
RLAPI void RestoreWindow(void); // Set window state: not minimized/maximized (only PLATFORM_DESKTOP)
|
RLAPI void RestoreWindow(void); // Set window state: not minimized/maximized (only PLATFORM_DESKTOP)
|
||||||
RLAPI void SetWindowIcon(Image image); // Set icon for window (single image, RGBA 32bit, only PLATFORM_DESKTOP)
|
RLAPI void SetWindowIcon(Image image); // Set icon for window (single image, RGBA 32bit, only PLATFORM_DESKTOP)
|
||||||
RLAPI void SetWindowIcons(Image *images, int count); // Set icon for window (multiple images, RGBA 32bit, only PLATFORM_DESKTOP)
|
RLAPI void SetWindowIcons(Image *images, int count); // Set icon for window (multiple images, RGBA 32bit, only PLATFORM_DESKTOP)
|
||||||
RLAPI void SetWindowTitle(const char *title); // Set title for window (only PLATFORM_DESKTOP)
|
RLAPI void SetWindowTitle(const char *title); // Set title for window (only PLATFORM_DESKTOP and PLATFORM_WEB)
|
||||||
RLAPI void SetWindowPosition(int x, int y); // Set window position on screen (only PLATFORM_DESKTOP)
|
RLAPI void SetWindowPosition(int x, int y); // Set window position on screen (only PLATFORM_DESKTOP)
|
||||||
RLAPI void SetWindowMonitor(int monitor); // Set monitor for the current window (fullscreen mode)
|
RLAPI void SetWindowMonitor(int monitor); // Set monitor for the current window
|
||||||
RLAPI void SetWindowMinSize(int width, int height); // Set window minimum dimensions (for FLAG_WINDOW_RESIZABLE)
|
RLAPI void SetWindowMinSize(int width, int height); // Set window minimum dimensions (for FLAG_WINDOW_RESIZABLE)
|
||||||
|
RLAPI void SetWindowMaxSize(int width, int height); // Set window maximum dimensions (for FLAG_WINDOW_RESIZABLE)
|
||||||
RLAPI void SetWindowSize(int width, int height); // Set window dimensions
|
RLAPI void SetWindowSize(int width, int height); // Set window dimensions
|
||||||
RLAPI void SetWindowOpacity(float opacity); // Set window opacity [0.0f..1.0f] (only PLATFORM_DESKTOP)
|
RLAPI void SetWindowOpacity(float opacity); // Set window opacity [0.0f..1.0f] (only PLATFORM_DESKTOP)
|
||||||
|
RLAPI void SetWindowFocused(void); // Set window focused (only PLATFORM_DESKTOP)
|
||||||
RLAPI void *GetWindowHandle(void); // Get native window handle
|
RLAPI void *GetWindowHandle(void); // Get native window handle
|
||||||
RLAPI int GetScreenWidth(void); // Get current screen width
|
RLAPI int GetScreenWidth(void); // Get current screen width
|
||||||
RLAPI int GetScreenHeight(void); // Get current screen height
|
RLAPI int GetScreenHeight(void); // Get current screen height
|
||||||
|
@ -964,20 +994,12 @@ RLAPI int GetMonitorPhysicalHeight(int monitor); // Get specifi
|
||||||
RLAPI int GetMonitorRefreshRate(int monitor); // Get specified monitor refresh rate
|
RLAPI int GetMonitorRefreshRate(int monitor); // Get specified monitor refresh rate
|
||||||
RLAPI Vector2 GetWindowPosition(void); // Get window position XY on monitor
|
RLAPI Vector2 GetWindowPosition(void); // Get window position XY on monitor
|
||||||
RLAPI Vector2 GetWindowScaleDPI(void); // Get window scale DPI factor
|
RLAPI Vector2 GetWindowScaleDPI(void); // Get window scale DPI factor
|
||||||
RLAPI const char *GetMonitorName(int monitor); // Get the human-readable, UTF-8 encoded name of the primary monitor
|
RLAPI const char *GetMonitorName(int monitor); // Get the human-readable, UTF-8 encoded name of the specified monitor
|
||||||
RLAPI void SetClipboardText(const char *text); // Set clipboard text content
|
RLAPI void SetClipboardText(const char *text); // Set clipboard text content
|
||||||
RLAPI const char *GetClipboardText(void); // Get clipboard text content
|
RLAPI const char *GetClipboardText(void); // Get clipboard text content
|
||||||
RLAPI void EnableEventWaiting(void); // Enable waiting for events on EndDrawing(), no automatic event polling
|
RLAPI void EnableEventWaiting(void); // Enable waiting for events on EndDrawing(), no automatic event polling
|
||||||
RLAPI void DisableEventWaiting(void); // Disable waiting for events on EndDrawing(), automatic events polling
|
RLAPI void DisableEventWaiting(void); // Disable waiting for events on EndDrawing(), automatic events polling
|
||||||
|
|
||||||
// Custom frame control functions
|
|
||||||
// NOTE: Those functions are intended for advance users that want full control over the frame processing
|
|
||||||
// By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timing + PollInputEvents()
|
|
||||||
// To avoid that behaviour and control frame processes manually, enable in config.h: SUPPORT_CUSTOM_FRAME_CONTROL
|
|
||||||
RLAPI void SwapScreenBuffer(void); // Swap back buffer with front buffer (screen drawing)
|
|
||||||
RLAPI void PollInputEvents(void); // Register all input events
|
|
||||||
RLAPI void WaitTime(double seconds); // Wait for some time (halt program execution)
|
|
||||||
|
|
||||||
// Cursor-related functions
|
// Cursor-related functions
|
||||||
RLAPI void ShowCursor(void); // Shows cursor
|
RLAPI void ShowCursor(void); // Shows cursor
|
||||||
RLAPI void HideCursor(void); // Hides cursor
|
RLAPI void HideCursor(void); // Hides cursor
|
||||||
|
@ -1033,24 +1055,37 @@ RLAPI Vector2 GetWorldToScreen2D(Vector2 position, Camera2D camera); // Get the
|
||||||
|
|
||||||
// Timing-related functions
|
// Timing-related functions
|
||||||
RLAPI void SetTargetFPS(int fps); // Set target FPS (maximum)
|
RLAPI void SetTargetFPS(int fps); // Set target FPS (maximum)
|
||||||
RLAPI int GetFPS(void); // Get current FPS
|
|
||||||
RLAPI float GetFrameTime(void); // Get time in seconds for last frame drawn (delta time)
|
RLAPI float GetFrameTime(void); // Get time in seconds for last frame drawn (delta time)
|
||||||
RLAPI double GetTime(void); // Get elapsed time in seconds since InitWindow()
|
RLAPI double GetTime(void); // Get elapsed time in seconds since InitWindow()
|
||||||
|
RLAPI int GetFPS(void); // Get current FPS
|
||||||
|
|
||||||
|
// Custom frame control functions
|
||||||
|
// NOTE: Those functions are intended for advance users that want full control over the frame processing
|
||||||
|
// By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timing + PollInputEvents()
|
||||||
|
// To avoid that behaviour and control frame processes manually, enable in config.h: SUPPORT_CUSTOM_FRAME_CONTROL
|
||||||
|
RLAPI void SwapScreenBuffer(void); // Swap back buffer with front buffer (screen drawing)
|
||||||
|
RLAPI void PollInputEvents(void); // Register all input events
|
||||||
|
RLAPI void WaitTime(double seconds); // Wait for some time (halt program execution)
|
||||||
|
|
||||||
|
// Random values generation functions
|
||||||
|
RLAPI void SetRandomSeed(unsigned int seed); // Set the seed for the random number generator
|
||||||
|
RLAPI int GetRandomValue(int min, int max); // Get a random value between min and max (both included)
|
||||||
|
RLAPI int *LoadRandomSequence(unsigned int count, int min, int max); // Load random values sequence, no values repeated
|
||||||
|
RLAPI void UnloadRandomSequence(int *sequence); // Unload random values sequence
|
||||||
|
|
||||||
// Misc. functions
|
// Misc. functions
|
||||||
RLAPI int GetRandomValue(int min, int max); // Get a random value between min and max (both included)
|
|
||||||
RLAPI void SetRandomSeed(unsigned int seed); // Set the seed for the random number generator
|
|
||||||
RLAPI void TakeScreenshot(const char *fileName); // Takes a screenshot of current screen (filename extension defines format)
|
RLAPI void TakeScreenshot(const char *fileName); // Takes a screenshot of current screen (filename extension defines format)
|
||||||
RLAPI void SetConfigFlags(unsigned int flags); // Setup init configuration flags (view FLAGS)
|
RLAPI void SetConfigFlags(unsigned int flags); // Setup init configuration flags (view FLAGS)
|
||||||
|
RLAPI void OpenURL(const char *url); // Open URL with default system browser (if available)
|
||||||
|
|
||||||
|
// NOTE: Following functions implemented in module [utils]
|
||||||
|
//------------------------------------------------------------------
|
||||||
RLAPI void TraceLog(int logLevel, const char *text, ...); // Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...)
|
RLAPI void TraceLog(int logLevel, const char *text, ...); // Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...)
|
||||||
RLAPI void SetTraceLogLevel(int logLevel); // Set the current threshold (minimum) log level
|
RLAPI void SetTraceLogLevel(int logLevel); // Set the current threshold (minimum) log level
|
||||||
RLAPI void *MemAlloc(unsigned int size); // Internal memory allocator
|
RLAPI void *MemAlloc(unsigned int size); // Internal memory allocator
|
||||||
RLAPI void *MemRealloc(void *ptr, unsigned int size); // Internal memory reallocator
|
RLAPI void *MemRealloc(void *ptr, unsigned int size); // Internal memory reallocator
|
||||||
RLAPI void MemFree(void *ptr); // Internal memory free
|
RLAPI void MemFree(void *ptr); // Internal memory free
|
||||||
|
|
||||||
RLAPI void OpenURL(const char *url); // Open URL with default system browser (if available)
|
|
||||||
|
|
||||||
// Set custom callbacks
|
// Set custom callbacks
|
||||||
// WARNING: Callbacks setup is intended for advance users
|
// WARNING: Callbacks setup is intended for advance users
|
||||||
RLAPI void SetTraceLogCallback(TraceLogCallback callback); // Set custom trace log
|
RLAPI void SetTraceLogCallback(TraceLogCallback callback); // Set custom trace log
|
||||||
|
@ -1060,13 +1095,16 @@ RLAPI void SetLoadFileTextCallback(LoadFileTextCallback callback); // Set custom
|
||||||
RLAPI void SetSaveFileTextCallback(SaveFileTextCallback callback); // Set custom file text data saver
|
RLAPI void SetSaveFileTextCallback(SaveFileTextCallback callback); // Set custom file text data saver
|
||||||
|
|
||||||
// Files management functions
|
// Files management functions
|
||||||
RLAPI unsigned char *LoadFileData(const char *fileName, unsigned int *bytesRead); // Load file data as byte array (read)
|
RLAPI unsigned char *LoadFileData(const char *fileName, int *dataSize); // Load file data as byte array (read)
|
||||||
RLAPI void UnloadFileData(unsigned char *data); // Unload file data allocated by LoadFileData()
|
RLAPI void UnloadFileData(unsigned char *data); // Unload file data allocated by LoadFileData()
|
||||||
RLAPI bool SaveFileData(const char *fileName, void *data, unsigned int bytesToWrite); // Save data to file from byte array (write), returns true on success
|
RLAPI bool SaveFileData(const char *fileName, void *data, int dataSize); // Save data to file from byte array (write), returns true on success
|
||||||
RLAPI bool ExportDataAsCode(const unsigned char *data, unsigned int size, const char *fileName); // Export data to code (.h), returns true on success
|
RLAPI bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileName); // Export data to code (.h), returns true on success
|
||||||
RLAPI char *LoadFileText(const char *fileName); // Load text data from file (read), returns a '\0' terminated string
|
RLAPI char *LoadFileText(const char *fileName); // Load text data from file (read), returns a '\0' terminated string
|
||||||
RLAPI void UnloadFileText(char *text); // Unload file text data allocated by LoadFileText()
|
RLAPI void UnloadFileText(char *text); // Unload file text data allocated by LoadFileText()
|
||||||
RLAPI bool SaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated, returns true on success
|
RLAPI bool SaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated, returns true on success
|
||||||
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
|
// File system functions
|
||||||
RLAPI bool FileExists(const char *fileName); // Check if file exists
|
RLAPI bool FileExists(const char *fileName); // Check if file exists
|
||||||
RLAPI bool DirectoryExists(const char *dirPath); // Check if a directory path exists
|
RLAPI bool DirectoryExists(const char *dirPath); // Check if a directory path exists
|
||||||
RLAPI bool IsFileExtension(const char *fileName, const char *ext); // Check file extension (including point: .png, .wav)
|
RLAPI bool IsFileExtension(const char *fileName, const char *ext); // Check file extension (including point: .png, .wav)
|
||||||
|
@ -1077,7 +1115,7 @@ RLAPI const char *GetFileNameWithoutExt(const char *filePath); // Get filenam
|
||||||
RLAPI const char *GetDirectoryPath(const char *filePath); // Get full path for a given fileName with path (uses static string)
|
RLAPI const char *GetDirectoryPath(const char *filePath); // Get full path for a given fileName with path (uses static string)
|
||||||
RLAPI const char *GetPrevDirectoryPath(const char *dirPath); // Get previous directory path for a given path (uses static string)
|
RLAPI const char *GetPrevDirectoryPath(const char *dirPath); // Get previous directory path for a given path (uses static string)
|
||||||
RLAPI const char *GetWorkingDirectory(void); // Get current working directory (uses static string)
|
RLAPI const char *GetWorkingDirectory(void); // Get current working directory (uses static string)
|
||||||
RLAPI const char *GetApplicationDirectory(void); // Get the directory if the running application (uses static string)
|
RLAPI const char *GetApplicationDirectory(void); // Get the directory of the running application (uses static string)
|
||||||
RLAPI bool ChangeDirectory(const char *dir); // Change working directory, return true on success
|
RLAPI bool ChangeDirectory(const char *dir); // Change working directory, return true on success
|
||||||
RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory
|
RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory
|
||||||
RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths
|
RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths
|
||||||
|
@ -1094,18 +1132,29 @@ RLAPI unsigned char *DecompressData(const unsigned char *compData, int compDataS
|
||||||
RLAPI char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize); // Encode data to Base64 string, memory must be MemFree()
|
RLAPI char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize); // Encode data to Base64 string, memory must be MemFree()
|
||||||
RLAPI unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize); // Decode Base64 string data, memory must be MemFree()
|
RLAPI unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize); // Decode Base64 string data, memory must be MemFree()
|
||||||
|
|
||||||
|
// Automation events functionality
|
||||||
|
RLAPI AutomationEventList LoadAutomationEventList(const char *fileName); // Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS
|
||||||
|
RLAPI void UnloadAutomationEventList(AutomationEventList *list); // Unload automation events list from file
|
||||||
|
RLAPI bool ExportAutomationEventList(AutomationEventList list, const char *fileName); // Export automation events list as text file
|
||||||
|
RLAPI void SetAutomationEventList(AutomationEventList *list); // Set automation event list to record to
|
||||||
|
RLAPI void SetAutomationEventBaseFrame(int frame); // Set automation event internal base frame to start recording
|
||||||
|
RLAPI void StartAutomationEventRecording(void); // Start recording automation events (AutomationEventList must be set)
|
||||||
|
RLAPI void StopAutomationEventRecording(void); // Stop recording automation events
|
||||||
|
RLAPI void PlayAutomationEvent(AutomationEvent event); // Play a recorded automation event
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Input Handling Functions (Module: core)
|
// Input Handling Functions (Module: core)
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Input-related functions: keyboard
|
// Input-related functions: keyboard
|
||||||
RLAPI bool IsKeyPressed(int key); // Check if a key has been pressed once
|
RLAPI bool IsKeyPressed(int key); // Check if a key has been pressed once
|
||||||
|
RLAPI bool IsKeyPressedRepeat(int key); // Check if a key has been pressed again (Only PLATFORM_DESKTOP)
|
||||||
RLAPI bool IsKeyDown(int key); // Check if a key is being pressed
|
RLAPI bool IsKeyDown(int key); // Check if a key is being pressed
|
||||||
RLAPI bool IsKeyReleased(int key); // Check if a key has been released once
|
RLAPI bool IsKeyReleased(int key); // Check if a key has been released once
|
||||||
RLAPI bool IsKeyUp(int key); // Check if a key is NOT being pressed
|
RLAPI bool IsKeyUp(int key); // Check if a key is NOT being pressed
|
||||||
RLAPI void SetExitKey(int key); // Set a custom key to exit program (default is ESC)
|
|
||||||
RLAPI int GetKeyPressed(void); // Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty
|
RLAPI int GetKeyPressed(void); // Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty
|
||||||
RLAPI int GetCharPressed(void); // Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty
|
RLAPI int GetCharPressed(void); // Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty
|
||||||
|
RLAPI void SetExitKey(int key); // Set a custom key to exit program (default is ESC)
|
||||||
|
|
||||||
// Input-related functions: gamepads
|
// Input-related functions: gamepads
|
||||||
RLAPI bool IsGamepadAvailable(int gamepad); // Check if a gamepad is available
|
RLAPI bool IsGamepadAvailable(int gamepad); // Check if a gamepad is available
|
||||||
|
@ -1146,7 +1195,7 @@ RLAPI int GetTouchPointCount(void); // Get number of t
|
||||||
// Gestures and Touch Handling Functions (Module: rgestures)
|
// Gestures and Touch Handling Functions (Module: rgestures)
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
RLAPI void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
|
RLAPI void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
|
||||||
RLAPI bool IsGestureDetected(int gesture); // Check if a gesture have been detected
|
RLAPI bool IsGestureDetected(unsigned int gesture); // Check if a gesture have been detected
|
||||||
RLAPI int GetGestureDetected(void); // Get latest detected gesture
|
RLAPI int GetGestureDetected(void); // Get latest detected gesture
|
||||||
RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds
|
RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds
|
||||||
RLAPI Vector2 GetGestureDragVector(void); // Get gesture drag vector
|
RLAPI Vector2 GetGestureDragVector(void); // Get gesture drag vector
|
||||||
|
@ -1177,6 +1226,8 @@ RLAPI void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color
|
||||||
RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line using cubic-bezier curves in-out
|
RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line using cubic-bezier curves in-out
|
||||||
RLAPI void DrawLineBezierQuad(Vector2 startPos, Vector2 endPos, Vector2 controlPos, float thick, Color color); // Draw line using quadratic bezier curves with a control point
|
RLAPI void DrawLineBezierQuad(Vector2 startPos, Vector2 endPos, Vector2 controlPos, float thick, Color color); // Draw line using quadratic bezier curves with a control point
|
||||||
RLAPI void DrawLineBezierCubic(Vector2 startPos, Vector2 endPos, Vector2 startControlPos, Vector2 endControlPos, float thick, Color color); // Draw line using cubic bezier curves with 2 control points
|
RLAPI void DrawLineBezierCubic(Vector2 startPos, Vector2 endPos, Vector2 startControlPos, Vector2 endControlPos, float thick, Color color); // Draw line using cubic bezier curves with 2 control points
|
||||||
|
RLAPI void DrawLineBSpline(Vector2 *points, int pointCount, float thick, Color color); // Draw a B-Spline line, minimum 4 points
|
||||||
|
RLAPI void DrawLineCatmullRom(Vector2 *points, int pointCount, float thick, Color color); // Draw a Catmull Rom spline line, minimum 4 points
|
||||||
RLAPI void DrawLineStrip(Vector2 *points, int pointCount, Color color); // Draw lines sequence
|
RLAPI void DrawLineStrip(Vector2 *points, int pointCount, Color color); // Draw lines sequence
|
||||||
RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle
|
RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle
|
||||||
RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle
|
RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle
|
||||||
|
@ -1184,6 +1235,7 @@ RLAPI void DrawCircleSectorLines(Vector2 center, float radius, float startAngle,
|
||||||
RLAPI void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2); // Draw a gradient-filled circle
|
RLAPI void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2); // Draw a gradient-filled circle
|
||||||
RLAPI void DrawCircleV(Vector2 center, float radius, Color color); // Draw a color-filled circle (Vector version)
|
RLAPI void DrawCircleV(Vector2 center, float radius, Color color); // Draw a color-filled circle (Vector version)
|
||||||
RLAPI void DrawCircleLines(int centerX, int centerY, float radius, Color color); // Draw circle outline
|
RLAPI void DrawCircleLines(int centerX, int centerY, float radius, Color color); // Draw circle outline
|
||||||
|
RLAPI void DrawCircleLinesV(Vector2 center, float radius, Color color); // Draw circle outline (Vector version)
|
||||||
RLAPI void DrawEllipse(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse
|
RLAPI void DrawEllipse(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse
|
||||||
RLAPI void DrawEllipseLines(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse outline
|
RLAPI void DrawEllipseLines(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse outline
|
||||||
RLAPI void DrawRing(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color); // Draw ring
|
RLAPI void DrawRing(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color); // Draw ring
|
||||||
|
@ -1227,6 +1279,7 @@ RLAPI Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2);
|
||||||
// NOTE: These functions do not require GPU access
|
// NOTE: These functions do not require GPU access
|
||||||
RLAPI Image LoadImage(const char *fileName); // Load image from file into CPU memory (RAM)
|
RLAPI Image LoadImage(const char *fileName); // Load image from file into CPU memory (RAM)
|
||||||
RLAPI Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize); // Load image from RAW file data
|
RLAPI Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize); // Load image from RAW file data
|
||||||
|
RLAPI Image LoadImageSvg(const char *fileNameOrString, int width, int height); // Load image from SVG file data or string with specified size
|
||||||
RLAPI Image LoadImageAnim(const char *fileName, int *frames); // Load image sequence from file (frames appended to image.data)
|
RLAPI Image LoadImageAnim(const char *fileName, int *frames); // Load image sequence from file (frames appended to image.data)
|
||||||
RLAPI Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load image from memory buffer, fileType refers to extension: i.e. '.png'
|
RLAPI Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load image from memory buffer, fileType refers to extension: i.e. '.png'
|
||||||
RLAPI Image LoadImageFromTexture(Texture2D texture); // Load image from GPU texture data
|
RLAPI Image LoadImageFromTexture(Texture2D texture); // Load image from GPU texture data
|
||||||
|
@ -1234,13 +1287,14 @@ RLAPI Image LoadImageFromScreen(void);
|
||||||
RLAPI bool IsImageReady(Image image); // Check if an image is ready
|
RLAPI bool IsImageReady(Image image); // Check if an image is ready
|
||||||
RLAPI void UnloadImage(Image image); // Unload image from CPU memory (RAM)
|
RLAPI void UnloadImage(Image image); // Unload image from CPU memory (RAM)
|
||||||
RLAPI bool ExportImage(Image image, const char *fileName); // Export image data to file, returns true on success
|
RLAPI bool ExportImage(Image image, const char *fileName); // Export image data to file, returns true on success
|
||||||
|
RLAPI unsigned char *ExportImageToMemory(Image image, const char *fileType, int *fileSize); // Export image to memory buffer
|
||||||
RLAPI bool ExportImageAsCode(Image image, const char *fileName); // Export image as code file defining an array of bytes, returns true on success
|
RLAPI bool ExportImageAsCode(Image image, const char *fileName); // Export image as code file defining an array of bytes, returns true on success
|
||||||
|
|
||||||
// Image generation functions
|
// Image generation functions
|
||||||
RLAPI Image GenImageColor(int width, int height, Color color); // Generate image: plain color
|
RLAPI Image GenImageColor(int width, int height, Color color); // Generate image: plain color
|
||||||
RLAPI Image GenImageGradientV(int width, int height, Color top, Color bottom); // Generate image: vertical gradient
|
RLAPI Image GenImageGradientLinear(int width, int height, int direction, Color start, Color end); // Generate image: linear gradient, direction in degrees [0..360], 0=Vertical gradient
|
||||||
RLAPI Image GenImageGradientH(int width, int height, Color left, Color right); // Generate image: horizontal gradient
|
|
||||||
RLAPI Image GenImageGradientRadial(int width, int height, float density, Color inner, Color outer); // Generate image: radial gradient
|
RLAPI Image GenImageGradientRadial(int width, int height, float density, Color inner, Color outer); // Generate image: radial gradient
|
||||||
|
RLAPI Image GenImageGradientSquare(int width, int height, float density, Color inner, Color outer); // Generate image: square gradient
|
||||||
RLAPI Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2); // Generate image: checked
|
RLAPI Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2); // Generate image: checked
|
||||||
RLAPI Image GenImageWhiteNoise(int width, int height, float factor); // Generate image: white noise
|
RLAPI Image GenImageWhiteNoise(int width, int height, float factor); // Generate image: white noise
|
||||||
RLAPI Image GenImagePerlinNoise(int width, int height, int offsetX, int offsetY, float scale); // Generate image: perlin noise
|
RLAPI Image GenImagePerlinNoise(int width, int height, int offsetX, int offsetY, float scale); // Generate image: perlin noise
|
||||||
|
@ -1267,6 +1321,7 @@ RLAPI void ImageMipmaps(Image *image);
|
||||||
RLAPI void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp); // Dither image data to 16bpp or lower (Floyd-Steinberg dithering)
|
RLAPI void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp); // Dither image data to 16bpp or lower (Floyd-Steinberg dithering)
|
||||||
RLAPI void ImageFlipVertical(Image *image); // Flip image vertically
|
RLAPI void ImageFlipVertical(Image *image); // Flip image vertically
|
||||||
RLAPI void ImageFlipHorizontal(Image *image); // Flip image horizontally
|
RLAPI void ImageFlipHorizontal(Image *image); // Flip image horizontally
|
||||||
|
RLAPI void ImageRotate(Image *image, int degrees); // Rotate image by input angle in degrees (-359 to 359)
|
||||||
RLAPI void ImageRotateCW(Image *image); // Rotate image clockwise 90deg
|
RLAPI void ImageRotateCW(Image *image); // Rotate image clockwise 90deg
|
||||||
RLAPI void ImageRotateCCW(Image *image); // Rotate image counter-clockwise 90deg
|
RLAPI void ImageRotateCCW(Image *image); // Rotate image counter-clockwise 90deg
|
||||||
RLAPI void ImageColorTint(Image *image, Color color); // Modify image color: tint
|
RLAPI void ImageColorTint(Image *image, Color color); // Modify image color: tint
|
||||||
|
@ -1351,13 +1406,13 @@ RLAPI int GetPixelDataSize(int width, int height, int format); // G
|
||||||
// Font loading/unloading functions
|
// Font loading/unloading functions
|
||||||
RLAPI Font GetFontDefault(void); // Get the default Font
|
RLAPI Font GetFontDefault(void); // Get the default Font
|
||||||
RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM)
|
RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM)
|
||||||
RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int glyphCount); // Load font from file with extended parameters, use NULL for fontChars and 0 for glyphCount to load the default character set
|
RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set
|
||||||
RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style)
|
RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style)
|
||||||
RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int glyphCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf'
|
RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf'
|
||||||
RLAPI bool IsFontReady(Font font); // Check if a font is ready
|
RLAPI bool IsFontReady(Font font); // Check if a font is ready
|
||||||
RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int glyphCount, int type); // Load font data for further use
|
RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount, int type); // Load font data for further use
|
||||||
RLAPI Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **recs, int glyphCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info
|
RLAPI Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyphCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info
|
||||||
RLAPI void UnloadFontData(GlyphInfo *chars, int glyphCount); // Unload font chars info data (RAM)
|
RLAPI void UnloadFontData(GlyphInfo *glyphs, int glyphCount); // Unload font chars info data (RAM)
|
||||||
RLAPI void UnloadFont(Font font); // Unload font from GPU memory (VRAM)
|
RLAPI void UnloadFont(Font font); // Unload font from GPU memory (VRAM)
|
||||||
RLAPI bool ExportFontAsCode(Font font, const char *fileName); // Export font as code file, returns true on success
|
RLAPI bool ExportFontAsCode(Font font, const char *fileName); // Export font as code file, returns true on success
|
||||||
|
|
||||||
|
@ -1367,9 +1422,10 @@ RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color co
|
||||||
RLAPI void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters
|
RLAPI void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters
|
||||||
RLAPI void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint); // Draw text using Font and pro parameters (rotation)
|
RLAPI void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint); // Draw text using Font and pro parameters (rotation)
|
||||||
RLAPI void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSize, Color tint); // Draw one character (codepoint)
|
RLAPI void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSize, Color tint); // Draw one character (codepoint)
|
||||||
RLAPI void DrawTextCodepoints(Font font, const int *codepoints, int count, Vector2 position, float fontSize, float spacing, Color tint); // Draw multiple character (codepoint)
|
RLAPI void DrawTextCodepoints(Font font, const int *codepoints, int codepointCount, Vector2 position, float fontSize, float spacing, Color tint); // Draw multiple character (codepoint)
|
||||||
|
|
||||||
// Text font info functions
|
// Text font info functions
|
||||||
|
RLAPI void SetTextLineSpacing(int spacing); // Set vertical line spacing when drawing with line-breaks
|
||||||
RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font
|
RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font
|
||||||
RLAPI Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // Measure string size for Font
|
RLAPI Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // Measure string size for Font
|
||||||
RLAPI int GetGlyphIndex(Font font, int codepoint); // Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found
|
RLAPI int GetGlyphIndex(Font font, int codepoint); // Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found
|
||||||
|
@ -1485,10 +1541,10 @@ RLAPI void SetMaterialTexture(Material *material, int mapType, Texture2D texture
|
||||||
RLAPI void SetModelMeshMaterial(Model *model, int meshId, int materialId); // Set material for a mesh
|
RLAPI void SetModelMeshMaterial(Model *model, int meshId, int materialId); // Set material for a mesh
|
||||||
|
|
||||||
// Model animations loading/unloading functions
|
// Model animations loading/unloading functions
|
||||||
RLAPI ModelAnimation *LoadModelAnimations(const char *fileName, unsigned int *animCount); // Load model animations from file
|
RLAPI ModelAnimation *LoadModelAnimations(const char *fileName, int *animCount); // Load model animations from file
|
||||||
RLAPI void UpdateModelAnimation(Model model, ModelAnimation anim, int frame); // Update model animation pose
|
RLAPI void UpdateModelAnimation(Model model, ModelAnimation anim, int frame); // Update model animation pose
|
||||||
RLAPI void UnloadModelAnimation(ModelAnimation anim); // Unload animation data
|
RLAPI void UnloadModelAnimation(ModelAnimation anim); // Unload animation data
|
||||||
RLAPI void UnloadModelAnimations(ModelAnimation *animations, unsigned int count); // Unload animation array data
|
RLAPI void UnloadModelAnimations(ModelAnimation *animations, int animCount); // Unload animation array data
|
||||||
RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match
|
RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match
|
||||||
|
|
||||||
// Collision detection functions
|
// Collision detection functions
|
||||||
|
@ -1511,6 +1567,7 @@ RLAPI void InitAudioDevice(void); // Initial
|
||||||
RLAPI void CloseAudioDevice(void); // Close the audio device and context
|
RLAPI void CloseAudioDevice(void); // Close the audio device and context
|
||||||
RLAPI bool IsAudioDeviceReady(void); // Check if audio device has been initialized successfully
|
RLAPI bool IsAudioDeviceReady(void); // Check if audio device has been initialized successfully
|
||||||
RLAPI void SetMasterVolume(float volume); // Set master volume (listener)
|
RLAPI void SetMasterVolume(float volume); // Set master volume (listener)
|
||||||
|
RLAPI float GetMasterVolume(void); // Get master volume (listener)
|
||||||
|
|
||||||
// Wave/Sound loading/unloading functions
|
// Wave/Sound loading/unloading functions
|
||||||
RLAPI Wave LoadWave(const char *fileName); // Load wave data from file
|
RLAPI Wave LoadWave(const char *fileName); // Load wave data from file
|
||||||
|
@ -1518,10 +1575,12 @@ RLAPI Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileDat
|
||||||
RLAPI bool IsWaveReady(Wave wave); // Checks if wave data is ready
|
RLAPI bool IsWaveReady(Wave wave); // Checks if wave data is ready
|
||||||
RLAPI Sound LoadSound(const char *fileName); // Load sound from file
|
RLAPI Sound LoadSound(const char *fileName); // Load sound from file
|
||||||
RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound from wave data
|
RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound from wave data
|
||||||
|
RLAPI Sound LoadSoundAlias(Sound source); // Create a new sound that shares the same sample data as the source sound, does not own the sound data
|
||||||
RLAPI bool IsSoundReady(Sound sound); // Checks if a sound is ready
|
RLAPI bool IsSoundReady(Sound sound); // Checks if a sound is ready
|
||||||
RLAPI void UpdateSound(Sound sound, const void *data, int sampleCount); // Update sound buffer with new data
|
RLAPI void UpdateSound(Sound sound, const void *data, int sampleCount); // Update sound buffer with new data
|
||||||
RLAPI void UnloadWave(Wave wave); // Unload wave data
|
RLAPI void UnloadWave(Wave wave); // Unload wave data
|
||||||
RLAPI void UnloadSound(Sound sound); // Unload sound
|
RLAPI void UnloadSound(Sound sound); // Unload sound
|
||||||
|
RLAPI void UnloadSoundAlias(Sound alias); // Unload a sound alias (does not deallocate sample data)
|
||||||
RLAPI bool ExportWave(Wave wave, const char *fileName); // Export wave data to file, returns true on success
|
RLAPI bool ExportWave(Wave wave, const char *fileName); // Export wave data to file, returns true on success
|
||||||
RLAPI bool ExportWaveAsCode(Wave wave, const char *fileName); // Export wave sample data to code (.h), returns true on success
|
RLAPI bool ExportWaveAsCode(Wave wave, const char *fileName); // Export wave sample data to code (.h), returns true on success
|
||||||
|
|
||||||
|
@ -1575,10 +1634,10 @@ RLAPI void SetAudioStreamPan(AudioStream stream, float pan); // Set pan
|
||||||
RLAPI void SetAudioStreamBufferSizeDefault(int size); // Default size for new audio streams
|
RLAPI void SetAudioStreamBufferSizeDefault(int size); // Default size for new audio streams
|
||||||
RLAPI void SetAudioStreamCallback(AudioStream stream, AudioCallback callback); // Audio thread callback to request new data
|
RLAPI void SetAudioStreamCallback(AudioStream stream, AudioCallback callback); // Audio thread callback to request new data
|
||||||
|
|
||||||
RLAPI void AttachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Attach audio stream processor to stream
|
RLAPI void AttachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Attach audio stream processor to stream, receives the samples as <float>s
|
||||||
RLAPI void DetachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Detach audio stream processor from stream
|
RLAPI void DetachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Detach audio stream processor from stream
|
||||||
|
|
||||||
RLAPI void AttachAudioMixedProcessor(AudioCallback processor); // Attach audio stream processor to the entire audio pipeline
|
RLAPI void AttachAudioMixedProcessor(AudioCallback processor); // Attach audio stream processor to the entire audio pipeline, receives the samples as <float>s
|
||||||
RLAPI void DetachAudioMixedProcessor(AudioCallback processor); // Detach audio stream processor from the entire audio pipeline
|
RLAPI void DetachAudioMixedProcessor(AudioCallback processor); // Detach audio stream processor from the entire audio pipeline
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
|
|
|
@ -7,6 +7,8 @@ package rl
|
||||||
#include "external/android/native_app_glue/android_native_app_glue.c"
|
#include "external/android/native_app_glue/android_native_app_glue.c"
|
||||||
|
|
||||||
#cgo android LDFLAGS: -llog -landroid -lEGL -lGLESv2 -lOpenSLES -lm
|
#cgo android LDFLAGS: -llog -landroid -lEGL -lGLESv2 -lOpenSLES -lm
|
||||||
#cgo android CFLAGS: -DPLATFORM_ANDROID -DGRAPHICS_API_OPENGL_ES2 -Iexternal/android/native_app_glue
|
#cgo android CFLAGS: -DPLATFORM_ANDROID -DGRAPHICS_API_OPENGL_ES2 -Iexternal/android/native_app_glue -Wno-implicit-const-int-float-conversion
|
||||||
|
|
||||||
|
#cgo android,arm CFLAGS: -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//go:build darwin
|
//go:build darwin && !sdl
|
||||||
// +build darwin
|
// +build darwin,!sdl
|
||||||
|
|
||||||
package rl
|
package rl
|
||||||
|
|
||||||
|
|
19
raylib/cgo_darwin_sdl.go
Normal file
19
raylib/cgo_darwin_sdl.go
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
//go:build darwin && sdl
|
||||||
|
// +build darwin,sdl
|
||||||
|
|
||||||
|
package rl
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo darwin LDFLAGS: -framework Cocoa -framework IOKit -framework CoreVideo -framework CoreFoundation
|
||||||
|
#cgo darwin CFLAGS: -x objective-c -Wno-deprecated-declarations -Wno-implicit-const-int-float-conversion -DPLATFORM_DESKTOP_SDL
|
||||||
|
#cgo darwin pkg-config: sdl2
|
||||||
|
|
||||||
|
#cgo darwin,!angle LDFLAGS: -framework OpenGL
|
||||||
|
|
||||||
|
#cgo darwin,opengl11,!angle CFLAGS: -DGRAPHICS_API_OPENGL_11
|
||||||
|
#cgo darwin,opengl21,!angle CFLAGS: -DGRAPHICS_API_OPENGL_21
|
||||||
|
#cgo darwin,opengl43,!angle CFLAGS: -DGRAPHICS_API_OPENGL_43
|
||||||
|
#cgo darwin,!opengl11,!opengl21,!opengl43,!angle CFLAGS: -DGRAPHICS_API_OPENGL_33
|
||||||
|
#cgo darwin,angle CFLAGS: -DGRAPHICS_API_OPENGL_ES2
|
||||||
|
*/
|
||||||
|
import "C"
|
|
@ -1,5 +1,5 @@
|
||||||
//go:build freebsd && !linux && !drm && !rpi && !android
|
//go:build freebsd && !linux && !drm && !sdl && !android
|
||||||
// +build freebsd,!linux,!drm,!rpi,!android
|
// +build freebsd,!linux,!drm,!sdl,!android
|
||||||
|
|
||||||
package rl
|
package rl
|
||||||
|
|
||||||
|
|
20
raylib/cgo_freebsd_sdl.go
Normal file
20
raylib/cgo_freebsd_sdl.go
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
//go:build freebsd && !linux && !drm && sdl && !android
|
||||||
|
// +build freebsd,!linux,!drm,sdl,!android
|
||||||
|
|
||||||
|
package rl
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo freebsd CFLAGS: -I. -I/usr/local/include -DPLATFORM_DESKTOP_SDL
|
||||||
|
#cgo freebsd LDFLAGS: -L/usr/local/lib
|
||||||
|
|
||||||
|
#cgo freebsd pkg-config: sdl2
|
||||||
|
|
||||||
|
#cgo freebsd,!angle LDFLAGS: -lGL
|
||||||
|
|
||||||
|
#cgo freebsd,opengl11,!angle CFLAGS: -DGRAPHICS_API_OPENGL_11
|
||||||
|
#cgo freebsd,opengl21,!angle CFLAGS: -DGRAPHICS_API_OPENGL_21
|
||||||
|
#cgo freebsd,opengl43,!angle CFLAGS: -DGRAPHICS_API_OPENGL_43
|
||||||
|
#cgo freebsd,!opengl11,!opengl21,!opengl43,!angle CFLAGS: -DGRAPHICS_API_OPENGL_33
|
||||||
|
#cgo freebsd,angle CFLAGS: -DGRAPHICS_API_OPENGL_ES2
|
||||||
|
*/
|
||||||
|
import "C"
|
|
@ -1,5 +1,5 @@
|
||||||
//go:build linux && !drm && !rpi && !android
|
//go:build linux && !drm && !sdl && !android
|
||||||
// +build linux,!drm,!rpi,!android
|
// +build linux,!drm,!sdl,!android
|
||||||
|
|
||||||
package rl
|
package rl
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//go:build linux && drm && !rpi && !android
|
//go:build linux && drm && !sdl && !android
|
||||||
// +build linux,drm,!rpi,!android
|
// +build linux,drm,!sdl,!android
|
||||||
|
|
||||||
package rl
|
package rl
|
||||||
|
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
//go:build linux && rpi && !drm && !android
|
|
||||||
// +build linux,rpi,!drm,!android
|
|
||||||
|
|
||||||
package rl
|
|
||||||
|
|
||||||
/*
|
|
||||||
#cgo linux,rpi LDFLAGS: -L/opt/vc/lib -L/opt/vc/lib64 -lbrcmGLESv2 -lbrcmEGL -lpthread -lrt -lm -lbcm_host -lvcos -lvchiq_arm -ldl
|
|
||||||
#cgo linux,rpi CFLAGS: -DPLATFORM_RPI -DGRAPHICS_API_OPENGL_ES2 -I/opt/vc/include -I/opt/vc/include/interface/vcos -I/opt/vc/include/interface/vmcs_host/linux -I/opt/vc/include/interface/vcos/pthreads
|
|
||||||
*/
|
|
||||||
import "C"
|
|
19
raylib/cgo_linux_sdl.go
Normal file
19
raylib/cgo_linux_sdl.go
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
//go:build linux && !drm && sdl && !android
|
||||||
|
// +build linux,!drm,sdl,!android
|
||||||
|
|
||||||
|
package rl
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo linux,!angle LDFLAGS: -lm
|
||||||
|
#cgo linux CFLAGS: -DPLATFORM_DESKTOP_SDL -Wno-stringop-overflow
|
||||||
|
#cgo linux pkg-config: sdl2
|
||||||
|
|
||||||
|
#cgo linux,!angle LDFLAGS: -lGL
|
||||||
|
|
||||||
|
#cgo linux,opengl11,!angle CFLAGS: -DGRAPHICS_API_OPENGL_11
|
||||||
|
#cgo linux,opengl21,!angle CFLAGS: -DGRAPHICS_API_OPENGL_21
|
||||||
|
#cgo linux,opengl43,!angle CFLAGS: -DGRAPHICS_API_OPENGL_43
|
||||||
|
#cgo linux,!opengl11,!opengl21,!opengl43,!angle CFLAGS: -DGRAPHICS_API_OPENGL_33
|
||||||
|
#cgo linux,angle CFLAGS: -DGRAPHICS_API_OPENGL_ES2
|
||||||
|
*/
|
||||||
|
import "C"
|
|
@ -1,5 +1,5 @@
|
||||||
//go:build openbsd && !linux && !drm && !rpi && !android
|
//go:build openbsd && !linux && !drm && !sdl && !android
|
||||||
// +build openbsd,!linux,!drm,!rpi,!android
|
// +build openbsd,!linux,!drm,!sdl,!android
|
||||||
|
|
||||||
package rl
|
package rl
|
||||||
|
|
||||||
|
|
20
raylib/cgo_openbsd_sdl.go
Normal file
20
raylib/cgo_openbsd_sdl.go
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
//go:build openbsd && !linux && !drm && sdl && !android
|
||||||
|
// +build openbsd,!linux,!drm,sdl,!android
|
||||||
|
|
||||||
|
package rl
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo openbsd CFLAGS: -I. -I/usr/X11R6/include -DPLATFORM_DESKTOP_SDL
|
||||||
|
#cgo openbsd LDFLAGS: -L/usr/X11R6/lib
|
||||||
|
|
||||||
|
#cgo openbsd pkg-config: sdl2
|
||||||
|
|
||||||
|
#cgo openbsd,!angle LDFLAGS: -lGL
|
||||||
|
|
||||||
|
#cgo openbsd,opengl11,!angle CFLAGS: -DGRAPHICS_API_OPENGL_11
|
||||||
|
#cgo openbsd,opengl21,!angle CFLAGS: -DGRAPHICS_API_OPENGL_21
|
||||||
|
#cgo openbsd,opengl43,!angle CFLAGS: -DGRAPHICS_API_OPENGL_43
|
||||||
|
#cgo openbsd,!opengl11,!opengl21,!opengl43,!angle CFLAGS: -DGRAPHICS_API_OPENGL_33
|
||||||
|
#cgo openbsd,angle CFLAGS: -DGRAPHICS_API_OPENGL_ES2
|
||||||
|
*/
|
||||||
|
import "C"
|
|
@ -1,5 +1,5 @@
|
||||||
//go:build windows
|
//go:build windows && !sdl
|
||||||
// +build windows
|
// +build windows,!sdl
|
||||||
|
|
||||||
package rl
|
package rl
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ package rl
|
||||||
#include "external/glfw/src/osmesa_context.c"
|
#include "external/glfw/src/osmesa_context.c"
|
||||||
|
|
||||||
#cgo windows LDFLAGS: -lgdi32 -lwinmm -lole32
|
#cgo windows LDFLAGS: -lgdi32 -lwinmm -lole32
|
||||||
#cgo windows CFLAGS: -D_GLFW_WIN32 -Iexternal -Iexternal/glfw/include -Iexternal/glfw/deps/mingw -DPLATFORM_DESKTOP
|
#cgo windows CFLAGS: -D_GLFW_WIN32 -Iexternal -Iexternal/glfw/include -Iexternal/glfw/deps/mingw -DPLATFORM_DESKTOP -Wno-stringop-overflow
|
||||||
|
|
||||||
#cgo windows,!angle LDFLAGS: -lopengl32
|
#cgo windows,!angle LDFLAGS: -lopengl32
|
||||||
|
|
||||||
|
|
18
raylib/cgo_windows_sdl.go
Normal file
18
raylib/cgo_windows_sdl.go
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
//go:build windows && sdl
|
||||||
|
// +build windows,sdl
|
||||||
|
|
||||||
|
package rl
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo windows LDFLAGS: -lgdi32 -lwinmm -lole32 -lSDL2
|
||||||
|
#cgo windows CFLAGS: -Iexternal -DPLATFORM_DESKTOP_SDL -Wno-stringop-overflow
|
||||||
|
|
||||||
|
#cgo windows,!angle LDFLAGS: -lopengl32
|
||||||
|
|
||||||
|
#cgo windows,opengl11,!angle CFLAGS: -DGRAPHICS_API_OPENGL_11
|
||||||
|
#cgo windows,opengl21,!angle CFLAGS: -DGRAPHICS_API_OPENGL_21
|
||||||
|
#cgo windows,opengl43,!angle CFLAGS: -DGRAPHICS_API_OPENGL_43
|
||||||
|
#cgo windows,!opengl11,!opengl21,!opengl43,!angle CFLAGS: -DGRAPHICS_API_OPENGL_33
|
||||||
|
#cgo windows,angle CFLAGS: -DGRAPHICS_API_OPENGL_ES2
|
||||||
|
*/
|
||||||
|
import "C"
|
|
@ -45,6 +45,8 @@
|
||||||
#define SUPPORT_CAMERA_SYSTEM 1
|
#define SUPPORT_CAMERA_SYSTEM 1
|
||||||
// Gestures module is included (rgestures.h) to support gestures detection: tap, hold, swipe, drag
|
// Gestures module is included (rgestures.h) to support gestures detection: tap, hold, swipe, drag
|
||||||
#define SUPPORT_GESTURES_SYSTEM 1
|
#define SUPPORT_GESTURES_SYSTEM 1
|
||||||
|
// Include pseudo-random numbers generator (rprand.h), based on Xoshiro128** and SplitMix64
|
||||||
|
#define SUPPORT_RPRAND_GENERATOR 1
|
||||||
// Mouse gestures are directly mapped like touches and processed by gestures system
|
// Mouse gestures are directly mapped like touches and processed by gestures system
|
||||||
#define SUPPORT_MOUSE_GESTURES 1
|
#define SUPPORT_MOUSE_GESTURES 1
|
||||||
// Reconfigure standard input to receive key inputs, works with SSH connection.
|
// Reconfigure standard input to receive key inputs, works with SSH connection.
|
||||||
|
@ -55,9 +57,7 @@
|
||||||
// Use busy wait loop for timing sync, if not defined, a high-resolution timer is set up and used
|
// Use busy wait loop for timing sync, if not defined, a high-resolution timer is set up and used
|
||||||
//#define SUPPORT_BUSY_WAIT_LOOP 1
|
//#define SUPPORT_BUSY_WAIT_LOOP 1
|
||||||
// Use a partial-busy wait loop, in this case frame sleeps for most of the time, but then runs a busy loop at the end for accuracy
|
// Use a partial-busy wait loop, in this case frame sleeps for most of the time, but then runs a busy loop at the end for accuracy
|
||||||
#define SUPPORT_PARTIALBUSY_WAIT_LOOP
|
#define SUPPORT_PARTIALBUSY_WAIT_LOOP 1
|
||||||
// Wait for events passively (sleeping while no events) instead of polling them actively every frame
|
|
||||||
//#define SUPPORT_EVENTS_WAITING 1
|
|
||||||
// Allow automatic screen capture of current screen pressing F12, defined in KeyCallback()
|
// Allow automatic screen capture of current screen pressing F12, defined in KeyCallback()
|
||||||
#define SUPPORT_SCREEN_CAPTURE 1
|
#define SUPPORT_SCREEN_CAPTURE 1
|
||||||
// Allow automatic gif recording of current screen pressing CTRL+F12, defined in KeyCallback()
|
// Allow automatic gif recording of current screen pressing CTRL+F12, defined in KeyCallback()
|
||||||
|
@ -65,7 +65,7 @@
|
||||||
// Support CompressData() and DecompressData() functions
|
// Support CompressData() and DecompressData() functions
|
||||||
#define SUPPORT_COMPRESSION_API 1
|
#define SUPPORT_COMPRESSION_API 1
|
||||||
// Support automatic generated events, loading and recording of those events when required
|
// Support automatic generated events, loading and recording of those events when required
|
||||||
//#define SUPPORT_EVENTS_AUTOMATION 1
|
#define SUPPORT_AUTOMATION_EVENTS 1
|
||||||
// Support custom frame control, only for advance users
|
// Support custom frame control, only for advance users
|
||||||
// By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timing + PollInputEvents()
|
// By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timing + PollInputEvents()
|
||||||
// Enabling this flag allows manual control of the frame processes, use at your own risk
|
// Enabling this flag allows manual control of the frame processes, use at your own risk
|
||||||
|
@ -87,6 +87,7 @@
|
||||||
|
|
||||||
#define MAX_DECOMPRESSION_SIZE 64 // Max size allocated for decompression in MB
|
#define MAX_DECOMPRESSION_SIZE 64 // Max size allocated for decompression in MB
|
||||||
|
|
||||||
|
#define MAX_AUTOMATION_EVENTS 16384 // Maximum number of automation events to record
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Module: rlgl - Configuration values
|
// Module: rlgl - Configuration values
|
||||||
|
@ -141,7 +142,7 @@
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Module: rtextures - Configuration Flags
|
// Module: rtextures - Configuration Flags
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Select the desired fileformats to be supported for image data loading
|
// Selecte desired fileformats to be supported for image data loading
|
||||||
#define SUPPORT_FILEFORMAT_PNG 1
|
#define SUPPORT_FILEFORMAT_PNG 1
|
||||||
#define SUPPORT_FILEFORMAT_BMP 1
|
#define SUPPORT_FILEFORMAT_BMP 1
|
||||||
//#define SUPPORT_FILEFORMAT_TGA 1
|
//#define SUPPORT_FILEFORMAT_TGA 1
|
||||||
|
@ -150,13 +151,13 @@
|
||||||
#define SUPPORT_FILEFORMAT_QOI 1
|
#define SUPPORT_FILEFORMAT_QOI 1
|
||||||
//#define SUPPORT_FILEFORMAT_PSD 1
|
//#define SUPPORT_FILEFORMAT_PSD 1
|
||||||
#define SUPPORT_FILEFORMAT_DDS 1
|
#define SUPPORT_FILEFORMAT_DDS 1
|
||||||
#define SUPPORT_FILEFORMAT_HDR 1
|
//#define SUPPORT_FILEFORMAT_HDR 1
|
||||||
//#define SUPPORT_FILEFORMAT_PIC 1
|
//#define SUPPORT_FILEFORMAT_PIC 1
|
||||||
//#define SUPPORT_FILEFORMAT_PNM 1
|
|
||||||
//#define SUPPORT_FILEFORMAT_KTX 1
|
//#define SUPPORT_FILEFORMAT_KTX 1
|
||||||
//#define SUPPORT_FILEFORMAT_ASTC 1
|
//#define SUPPORT_FILEFORMAT_ASTC 1
|
||||||
//#define SUPPORT_FILEFORMAT_PKM 1
|
//#define SUPPORT_FILEFORMAT_PKM 1
|
||||||
//#define SUPPORT_FILEFORMAT_PVR 1
|
//#define SUPPORT_FILEFORMAT_PVR 1
|
||||||
|
//#define SUPPORT_FILEFORMAT_SVG 1
|
||||||
|
|
||||||
// Support image export functionality (.png, .bmp, .tga, .jpg, .qoi)
|
// Support image export functionality (.png, .bmp, .tga, .jpg, .qoi)
|
||||||
#define SUPPORT_IMAGE_EXPORT 1
|
#define SUPPORT_IMAGE_EXPORT 1
|
||||||
|
@ -181,6 +182,11 @@
|
||||||
// If not defined, still some functions are supported: TextLength(), TextFormat()
|
// If not defined, still some functions are supported: TextLength(), TextFormat()
|
||||||
#define SUPPORT_TEXT_MANIPULATION 1
|
#define SUPPORT_TEXT_MANIPULATION 1
|
||||||
|
|
||||||
|
// On font atlas image generation [GenImageFontAtlas()], add a 3x3 pixels white rectangle
|
||||||
|
// at the bottom-right corner of the atlas. It can be useful to for shapes drawing, to allow
|
||||||
|
// drawing text and shapes with a single draw call [SetShapesTexture()].
|
||||||
|
#define SUPPORT_FONT_ATLAS_WHITE_REC 1
|
||||||
|
|
||||||
// rtext: Configuration values
|
// rtext: Configuration values
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
#define MAX_TEXT_BUFFER_LENGTH 1024 // Size of internal static buffers used on some functions:
|
#define MAX_TEXT_BUFFER_LENGTH 1024 // Size of internal static buffers used on some functions:
|
||||||
|
|
15
raylib/external/cgltf.h
vendored
15
raylib/external/cgltf.h
vendored
|
@ -65,7 +65,8 @@
|
||||||
*
|
*
|
||||||
* `cgltf_num_components` is a tiny utility that tells you the dimensionality of
|
* `cgltf_num_components` is a tiny utility that tells you the dimensionality of
|
||||||
* a certain accessor type. This can be used before `cgltf_accessor_unpack_floats` to help allocate
|
* a certain accessor type. This can be used before `cgltf_accessor_unpack_floats` to help allocate
|
||||||
* the necessary amount of memory.
|
* the necessary amount of memory. `cgltf_component_size` and `cgltf_calc_size` exist for
|
||||||
|
* similar purposes.
|
||||||
*
|
*
|
||||||
* `cgltf_accessor_read_float` reads a certain element from a non-sparse accessor and converts it to
|
* `cgltf_accessor_read_float` reads a certain element from a non-sparse accessor and converts it to
|
||||||
* floating point, assuming that `cgltf_load_buffers` has already been called. The passed-in element
|
* floating point, assuming that `cgltf_load_buffers` has already been called. The passed-in element
|
||||||
|
@ -837,6 +838,8 @@ cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size i
|
||||||
cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size index);
|
cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size index);
|
||||||
|
|
||||||
cgltf_size cgltf_num_components(cgltf_type type);
|
cgltf_size cgltf_num_components(cgltf_type type);
|
||||||
|
cgltf_size cgltf_component_size(cgltf_component_type component_type);
|
||||||
|
cgltf_size cgltf_calc_size(cgltf_type type, cgltf_component_type component_type);
|
||||||
|
|
||||||
cgltf_size cgltf_accessor_unpack_floats(const cgltf_accessor* accessor, cgltf_float* out, cgltf_size float_count);
|
cgltf_size cgltf_accessor_unpack_floats(const cgltf_accessor* accessor, cgltf_float* out, cgltf_size float_count);
|
||||||
|
|
||||||
|
@ -1488,8 +1491,6 @@ cgltf_result cgltf_load_buffers(const cgltf_options* options, cgltf_data* data,
|
||||||
return cgltf_result_success;
|
return cgltf_result_success;
|
||||||
}
|
}
|
||||||
|
|
||||||
static cgltf_size cgltf_calc_size(cgltf_type type, cgltf_component_type component_type);
|
|
||||||
|
|
||||||
static cgltf_size cgltf_calc_index_bound(cgltf_buffer_view* buffer_view, cgltf_size offset, cgltf_component_type component_type, cgltf_size count)
|
static cgltf_size cgltf_calc_index_bound(cgltf_buffer_view* buffer_view, cgltf_size offset, cgltf_component_type component_type, cgltf_size count)
|
||||||
{
|
{
|
||||||
char* data = (char*)buffer_view->buffer->data + offset + buffer_view->offset;
|
char* data = (char*)buffer_view->buffer->data + offset + buffer_view->offset;
|
||||||
|
@ -2217,7 +2218,7 @@ static cgltf_size cgltf_component_read_index(const void* in, cgltf_component_typ
|
||||||
case cgltf_component_type_r_32u:
|
case cgltf_component_type_r_32u:
|
||||||
return *((const uint32_t*) in);
|
return *((const uint32_t*) in);
|
||||||
case cgltf_component_type_r_32f:
|
case cgltf_component_type_r_32f:
|
||||||
return (cgltf_size)*((const float*) in);
|
return (cgltf_size)((cgltf_ssize)*((const float*) in));
|
||||||
case cgltf_component_type_r_8u:
|
case cgltf_component_type_r_8u:
|
||||||
return *((const uint8_t*) in);
|
return *((const uint8_t*) in);
|
||||||
default:
|
default:
|
||||||
|
@ -2253,8 +2254,6 @@ static cgltf_float cgltf_component_read_float(const void* in, cgltf_component_ty
|
||||||
return (cgltf_float)cgltf_component_read_integer(in, component_type);
|
return (cgltf_float)cgltf_component_read_integer(in, component_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
static cgltf_size cgltf_component_size(cgltf_component_type component_type);
|
|
||||||
|
|
||||||
static cgltf_bool cgltf_element_read_float(const uint8_t* element, cgltf_type type, cgltf_component_type component_type, cgltf_bool normalized, cgltf_float* out, cgltf_size element_size)
|
static cgltf_bool cgltf_element_read_float(const uint8_t* element, cgltf_type type, cgltf_component_type component_type, cgltf_bool normalized, cgltf_float* out, cgltf_size element_size)
|
||||||
{
|
{
|
||||||
cgltf_size num_components = cgltf_num_components(type);
|
cgltf_size num_components = cgltf_num_components(type);
|
||||||
|
@ -5965,7 +5964,7 @@ cgltf_size cgltf_num_components(cgltf_type type) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static cgltf_size cgltf_component_size(cgltf_component_type component_type) {
|
cgltf_size cgltf_component_size(cgltf_component_type component_type) {
|
||||||
switch (component_type)
|
switch (component_type)
|
||||||
{
|
{
|
||||||
case cgltf_component_type_r_8:
|
case cgltf_component_type_r_8:
|
||||||
|
@ -5983,7 +5982,7 @@ static cgltf_size cgltf_component_size(cgltf_component_type component_type) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static cgltf_size cgltf_calc_size(cgltf_type type, cgltf_component_type component_type)
|
cgltf_size cgltf_calc_size(cgltf_type type, cgltf_component_type component_type)
|
||||||
{
|
{
|
||||||
cgltf_size component_size = cgltf_component_size(component_type);
|
cgltf_size component_size = cgltf_component_size(component_type);
|
||||||
if (type == cgltf_type_mat2 && component_size == 1)
|
if (type == cgltf_type_mat2 && component_size == 1)
|
||||||
|
|
4
raylib/external/jar_xm.h
vendored
4
raylib/external/jar_xm.h
vendored
|
@ -518,6 +518,10 @@ int jar_xm_create_context(jar_xm_context_t** ctxp, const char* moddata, uint32_t
|
||||||
return jar_xm_create_context_safe(ctxp, moddata, SIZE_MAX, rate);
|
return jar_xm_create_context_safe(ctxp, moddata, SIZE_MAX, rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ALIGN
|
||||||
|
#undef ALIGN
|
||||||
|
#endif
|
||||||
|
|
||||||
#define ALIGN(x, b) (((x) + ((b) - 1)) & ~((b) - 1))
|
#define ALIGN(x, b) (((x) + ((b) - 1)) & ~((b) - 1))
|
||||||
#define ALIGN_PTR(x, b) (void*)(((uintptr_t)(x) + ((b) - 1)) & ~((b) - 1))
|
#define ALIGN_PTR(x, b) (void*)(((uintptr_t)(x) + ((b) - 1)) & ~((b) - 1))
|
||||||
int jar_xm_create_context_safe(jar_xm_context_t** ctxp, const char* moddata, size_t moddata_length, uint32_t rate) {
|
int jar_xm_create_context_safe(jar_xm_context_t** ctxp, const char* moddata, size_t moddata_length, uint32_t rate) {
|
||||||
|
|
25510
raylib/external/miniaudio.h
vendored
25510
raylib/external/miniaudio.h
vendored
File diff suppressed because it is too large
Load diff
10
raylib/external/msf_gif.h
vendored
10
raylib/external/msf_gif.h
vendored
|
@ -256,16 +256,16 @@ static void msf_cook_frame(MsfCookedFrame * frame, uint8_t * raw, uint8_t * used
|
||||||
int width, int height, int pitch, int depth)
|
int width, int height, int pitch, int depth)
|
||||||
{ MsfTimeFunc
|
{ MsfTimeFunc
|
||||||
//bit depth for each channel
|
//bit depth for each channel
|
||||||
const static int rdepthsArray[17] = { 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5 };
|
static const int rdepthsArray[17] = { 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5 };
|
||||||
const static int gdepthsArray[17] = { 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6 };
|
static const int gdepthsArray[17] = { 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6 };
|
||||||
const static int bdepthsArray[17] = { 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5 };
|
static const int bdepthsArray[17] = { 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5 };
|
||||||
//this extra level of indirection looks unnecessary but we need to explicitly decay the arrays to pointers
|
//this extra level of indirection looks unnecessary but we need to explicitly decay the arrays to pointers
|
||||||
//in order to be able to swap them because of C's annoying not-quite-pointers, not-quite-value-types stack arrays.
|
//in order to be able to swap them because of C's annoying not-quite-pointers, not-quite-value-types stack arrays.
|
||||||
const int * rdepths = msf_gif_bgra_flag? bdepthsArray : rdepthsArray;
|
const int * rdepths = msf_gif_bgra_flag? bdepthsArray : rdepthsArray;
|
||||||
const int * gdepths = gdepthsArray;
|
const int * gdepths = gdepthsArray;
|
||||||
const int * bdepths = msf_gif_bgra_flag? rdepthsArray : bdepthsArray;
|
const int * bdepths = msf_gif_bgra_flag? rdepthsArray : bdepthsArray;
|
||||||
|
|
||||||
const static int ditherKernel[16] = {
|
static const int ditherKernel[16] = {
|
||||||
0 << 12, 8 << 12, 2 << 12, 10 << 12,
|
0 << 12, 8 << 12, 2 << 12, 10 << 12,
|
||||||
12 << 12, 4 << 12, 14 << 12, 6 << 12,
|
12 << 12, 4 << 12, 14 << 12, 6 << 12,
|
||||||
3 << 12, 11 << 12, 1 << 12, 9 << 12,
|
3 << 12, 11 << 12, 1 << 12, 9 << 12,
|
||||||
|
@ -404,7 +404,7 @@ static MsfGifBuffer * msf_compress_frame(void * allocContext, int width, int hei
|
||||||
MsfGifBuffer * buffer = (MsfGifBuffer *) MSF_GIF_MALLOC(allocContext, maxBufSize);
|
MsfGifBuffer * buffer = (MsfGifBuffer *) MSF_GIF_MALLOC(allocContext, maxBufSize);
|
||||||
if (!buffer) { return NULL; }
|
if (!buffer) { return NULL; }
|
||||||
uint8_t * writeHead = buffer->data;
|
uint8_t * writeHead = buffer->data;
|
||||||
MsfStridedList lzw = { lzwMem };
|
MsfStridedList lzw = { lzwMem, 0, 0 };
|
||||||
|
|
||||||
//allocate tlb
|
//allocate tlb
|
||||||
int totalBits = frame.rbits + frame.gbits + frame.bbits;
|
int totalBits = frame.rbits + frame.gbits + frame.bbits;
|
||||||
|
|
3053
raylib/external/nanosvg.h
vendored
Normal file
3053
raylib/external/nanosvg.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
1458
raylib/external/nanosvgrast.h
vendored
Normal file
1458
raylib/external/nanosvgrast.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
9
raylib/external/rl_gputex.h
vendored
9
raylib/external/rl_gputex.h
vendored
|
@ -261,11 +261,9 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
|
||||||
}
|
}
|
||||||
else if (((header->ddspf.flags == 0x04) || (header->ddspf.flags == 0x05)) && (header->ddspf.fourcc > 0)) // Compressed
|
else if (((header->ddspf.flags == 0x04) || (header->ddspf.flags == 0x05)) && (header->ddspf.fourcc > 0)) // Compressed
|
||||||
{
|
{
|
||||||
int data_size = 0;
|
// NOTE: This forces only 1 mipmap to be loaded which is not really correct but it works
|
||||||
|
int data_size = (header->pitch_or_linear_size < file_size - 0x80) ? header->pitch_or_linear_size : file_size - 0x80;
|
||||||
// Calculate data size, including all mipmaps
|
*mips = 1;
|
||||||
if (header->mipmap_count > 1) data_size = header->pitch_or_linear_size*2;
|
|
||||||
else data_size = header->pitch_or_linear_size;
|
|
||||||
|
|
||||||
image_data = RL_MALLOC(data_size*sizeof(unsigned char));
|
image_data = RL_MALLOC(data_size*sizeof(unsigned char));
|
||||||
|
|
||||||
|
@ -814,5 +812,4 @@ static int get_pixel_data_size(int width, int height, int format)
|
||||||
|
|
||||||
return data_size;
|
return data_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // RL_GPUTEX_IMPLEMENTATION
|
#endif // RL_GPUTEX_IMPLEMENTATION
|
||||||
|
|
305
raylib/external/rprand.h
vendored
Normal file
305
raylib/external/rprand.h
vendored
Normal file
|
@ -0,0 +1,305 @@
|
||||||
|
/**********************************************************************************************
|
||||||
|
*
|
||||||
|
* rprand v1.0 - A simple and easy-to-use pseudo-random numbers generator (PRNG)
|
||||||
|
*
|
||||||
|
* FEATURES:
|
||||||
|
* - Pseudo-random values generation, 32 bits: [0..4294967295]
|
||||||
|
* - Sequence generation avoiding duplicate values
|
||||||
|
* - Using standard and proven prng algorithm (Xoshiro128**)
|
||||||
|
* - State initialized with a separate generator (SplitMix64)
|
||||||
|
*
|
||||||
|
* LIMITATIONS:
|
||||||
|
* - No negative numbers, up to the user to manage them
|
||||||
|
*
|
||||||
|
* POSSIBLE IMPROVEMENTS:
|
||||||
|
* - Support 64 bits generation
|
||||||
|
*
|
||||||
|
* ADDITIONAL NOTES:
|
||||||
|
* This library implements two pseudo-random number generation algorithms:
|
||||||
|
*
|
||||||
|
* - Xoshiro128** : https://prng.di.unimi.it/xoshiro128starstar.c
|
||||||
|
* - SplitMix64 : https://prng.di.unimi.it/splitmix64.c
|
||||||
|
*
|
||||||
|
* SplitMix64 is used to initialize the Xoshiro128** state, from a provided seed
|
||||||
|
*
|
||||||
|
* It's suggested to use SplitMix64 to initialize the state of the generators starting from
|
||||||
|
* a 64-bit seed, as research has shown that initialization must be performed with a generator
|
||||||
|
* radically different in nature from the one initialized to avoid correlation on similar seeds.
|
||||||
|
*
|
||||||
|
* CONFIGURATION:
|
||||||
|
* #define RPRAND_IMPLEMENTATION
|
||||||
|
* Generates the implementation of the library into the included file.
|
||||||
|
* If not defined, the library is in header only mode and can be included in other headers
|
||||||
|
* or source files without problems. But only ONE file should hold the implementation.
|
||||||
|
*
|
||||||
|
* DEPENDENCIES: none
|
||||||
|
*
|
||||||
|
* VERSIONS HISTORY:
|
||||||
|
* 1.0 (01-Jun-2023) First version
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* LICENSE: zlib/libpng
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 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.
|
||||||
|
*
|
||||||
|
**********************************************************************************************/
|
||||||
|
|
||||||
|
#ifndef RPRAND_H
|
||||||
|
#define RPRAND_H
|
||||||
|
|
||||||
|
#define RPRAND_VERSION "1.0"
|
||||||
|
|
||||||
|
// Function specifiers in case library is build/used as a shared library (Windows)
|
||||||
|
// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#if defined(BUILD_LIBTYPE_SHARED)
|
||||||
|
#define RPRAND __declspec(dllexport) // We are building the library as a Win32 shared library (.dll)
|
||||||
|
#elif defined(USE_LIBTYPE_SHARED)
|
||||||
|
#define RPRAND __declspec(dllimport) // We are using the library as a Win32 shared library (.dll)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Function specifiers definition
|
||||||
|
#ifndef RPRANDAPI
|
||||||
|
#define RPRANDAPI // Functions defined as 'extern' by default (implicit specifiers)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Defines and Macros
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Allow custom memory allocators
|
||||||
|
#ifndef RPRAND_CALLOC
|
||||||
|
#define RPRAND_CALLOC(ptr,sz) calloc(ptr,sz)
|
||||||
|
#endif
|
||||||
|
#ifndef RPRAND_FREE
|
||||||
|
#define RPRAND_FREE(ptr) free(ptr)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Simple log system to avoid RPNG_LOG() calls if required
|
||||||
|
// NOTE: Avoiding those calls, also avoids const strings memory usage
|
||||||
|
#define RPRAND_SHOW_LOG_INFO
|
||||||
|
#if defined(RPNG_SHOW_LOG_INFO)
|
||||||
|
#define RPRAND_LOG(...) printf(__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define RPRAND_LOG(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Types and Structures Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
//...
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" { // Prevents name mangling of functions
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Global Variables Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
//...
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module Functions Declaration
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
RPRANDAPI void rprand_set_seed(unsigned long long seed); // Set rprand_state for Xoshiro128**, seed is 64bit
|
||||||
|
RPRANDAPI int rprand_get_value(int min, int max); // Get random value within a range, min and max included
|
||||||
|
|
||||||
|
RPRANDAPI int *rprand_load_sequence(unsigned int count, int min, int max); // Load pseudo-random numbers sequence with no duplicates
|
||||||
|
RPRANDAPI void rprand_unload_sequence(int *sequence); // Unload pseudo-random numbers sequence
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // RPRAND_H
|
||||||
|
|
||||||
|
/***********************************************************************************
|
||||||
|
*
|
||||||
|
* RPRAND IMPLEMENTATION
|
||||||
|
*
|
||||||
|
************************************************************************************/
|
||||||
|
|
||||||
|
#if defined(RPRAND_IMPLEMENTATION)
|
||||||
|
|
||||||
|
#include <stdlib.h> // Required for: calloc(), free(), abs()
|
||||||
|
#include <stdint.h> // Required for data types: uint32_t, uint64_t
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Types and Structures Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// ...
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Global Variables Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
static uint64_t rprand_seed = 0; // SplitMix64 actual seed
|
||||||
|
static uint32_t rprand_state[4] = { 0 }; // Xoshiro128** state, nitialized by SplitMix64
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module internal functions declaration
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
static uint32_t rprand_xoshiro(void); // Xoshiro128** generator (uses global rprand_state)
|
||||||
|
static uint64_t rprand_splitmix64(void); // SplitMix64 generator (uses seed to generate rprand_state)
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module functions definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Set rprand_state for Xoshiro128**
|
||||||
|
// NOTE: We use a custom generation algorithm using SplitMix64
|
||||||
|
void rprand_set_seed(unsigned long long seed)
|
||||||
|
{
|
||||||
|
rprand_seed = (uint64_t)seed; // Set SplitMix64 seed for further use
|
||||||
|
|
||||||
|
// To generate the Xoshiro128** state, we use SplitMix64 generator first
|
||||||
|
// We generate 4 pseudo-random 64bit numbers that we combine using their LSB|MSB
|
||||||
|
rprand_state[0] = (uint32_t)(rprand_splitmix64() & 0xffffffff);
|
||||||
|
rprand_state[1] = (uint32_t)((rprand_splitmix64() & 0xffffffff00000000) >> 32);
|
||||||
|
rprand_state[2] = (uint32_t)(rprand_splitmix64() & 0xffffffff);
|
||||||
|
rprand_state[3] = (uint32_t)((rprand_splitmix64() & 0xffffffff00000000) >> 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get random value within a range, min and max included
|
||||||
|
int rprand_get_value(int min, int max)
|
||||||
|
{
|
||||||
|
int value = rprand_xoshiro()%(abs(max - min) + 1) + min;
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load pseudo-random numbers sequence with no duplicates, min and max included
|
||||||
|
int *rprand_load_sequence(unsigned int count, int min, int max)
|
||||||
|
{
|
||||||
|
int *sequence = NULL;
|
||||||
|
|
||||||
|
if (count > (abs(max - min) + 1))
|
||||||
|
{
|
||||||
|
RPRAND_LOG("WARNING: Sequence count required is greater than range provided\n");
|
||||||
|
//count = (max - min);
|
||||||
|
return sequence;
|
||||||
|
}
|
||||||
|
|
||||||
|
sequence = (int *)RPRAND_CALLOC(count, sizeof(int));
|
||||||
|
|
||||||
|
int value = 0;
|
||||||
|
bool value_is_dup = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < count;)
|
||||||
|
{
|
||||||
|
value = (rprand_xoshiro()%(abs(max - min) + 1)) + min;
|
||||||
|
value_is_dup = false;
|
||||||
|
|
||||||
|
for (int j = 0; j < i; j++)
|
||||||
|
{
|
||||||
|
if (sequence[j] == value)
|
||||||
|
{
|
||||||
|
value_is_dup = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!value_is_dup)
|
||||||
|
{
|
||||||
|
sequence[i] = value;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sequence;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unload pseudo-random numbers sequence
|
||||||
|
void rprand_unload_sequence(int *sequence)
|
||||||
|
{
|
||||||
|
RPRAND_FREE(sequence);
|
||||||
|
sequence = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module internal functions definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
static inline uint32_t rprand_rotate_left(const uint32_t x, int k)
|
||||||
|
{
|
||||||
|
return (x << k) | (x >> (32 - k));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Xoshiro128** generator info:
|
||||||
|
//
|
||||||
|
// Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org)
|
||||||
|
//
|
||||||
|
// To the extent possible under law, the author has dedicated all copyright
|
||||||
|
// and related and neighboring rights to this software to the public domain
|
||||||
|
// worldwide. This software is distributed without any warranty.
|
||||||
|
//
|
||||||
|
// See <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||||
|
//
|
||||||
|
// This is xoshiro128** 1.1, one of our 32-bit all-purpose, rock-solid
|
||||||
|
// generators. It has excellent speed, a state size (128 bits) that is
|
||||||
|
// large enough for mild parallelism, and it passes all tests we are aware
|
||||||
|
// of.
|
||||||
|
//
|
||||||
|
// Note that version 1.0 had mistakenly s[0] instead of s[1] as state
|
||||||
|
// word passed to the scrambler.
|
||||||
|
//
|
||||||
|
// For generating just single-precision (i.e., 32-bit) floating-point
|
||||||
|
// numbers, xoshiro128+ is even faster.
|
||||||
|
//
|
||||||
|
// The state must be seeded so that it is not everywhere zero.
|
||||||
|
//
|
||||||
|
uint32_t rprand_xoshiro(void)
|
||||||
|
{
|
||||||
|
const uint32_t result = rprand_rotate_left(rprand_state[1]*5, 7)*9;
|
||||||
|
const uint32_t t = rprand_state[1] << 9;
|
||||||
|
|
||||||
|
rprand_state[2] ^= rprand_state[0];
|
||||||
|
rprand_state[3] ^= rprand_state[1];
|
||||||
|
rprand_state[1] ^= rprand_state[2];
|
||||||
|
rprand_state[0] ^= rprand_state[3];
|
||||||
|
|
||||||
|
rprand_state[2] ^= t;
|
||||||
|
|
||||||
|
rprand_state[3] = rprand_rotate_left(rprand_state[3], 11);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SplitMix64 generator info:
|
||||||
|
//
|
||||||
|
// Written in 2015 by Sebastiano Vigna (vigna@acm.org)
|
||||||
|
//
|
||||||
|
// To the extent possible under law, the author has dedicated all copyright
|
||||||
|
// and related and neighboring rights to this software to the public domain
|
||||||
|
// worldwide. This software is distributed without any warranty.
|
||||||
|
//
|
||||||
|
// See <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// This is a fixed-increment version of Java 8's SplittableRandom generator
|
||||||
|
// See http://dx.doi.org/10.1145/2714064.2660195 and
|
||||||
|
// http://docs.oracle.com/javase/8/docs/api/java/util/SplittableRandom.html
|
||||||
|
//
|
||||||
|
// It is a very fast generator passing BigCrush, and it can be useful if
|
||||||
|
// for some reason you absolutely want 64 bits of state.
|
||||||
|
uint64_t rprand_splitmix64()
|
||||||
|
{
|
||||||
|
uint64_t z = (rprand_seed += 0x9e3779b97f4a7c15);
|
||||||
|
z = (z ^ (z >> 30))*0xbf58476d1ce4e5b9;
|
||||||
|
z = (z ^ (z >> 27))*0x94d049bb133111eb;
|
||||||
|
return z ^ (z >> 31);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // RPRAND_IMPLEMENTATION
|
180
raylib/external/sdefl.h
vendored
180
raylib/external/sdefl.h
vendored
|
@ -38,10 +38,10 @@ this file implementation in *one* C or C++ file to prevent collisions.
|
||||||
| zlib 1.2.11 -1 | 72 MB/s | 307 MB/s | 42298774 | 42.30 |
|
| zlib 1.2.11 -1 | 72 MB/s | 307 MB/s | 42298774 | 42.30 |
|
||||||
| zlib 1.2.11 -6 | 24 MB/s | 313 MB/s | 36548921 | 36.55 |
|
| zlib 1.2.11 -6 | 24 MB/s | 313 MB/s | 36548921 | 36.55 |
|
||||||
| zlib 1.2.11 -9 | 20 MB/s | 314 MB/s | 36475792 | 36.48 |
|
| zlib 1.2.11 -9 | 20 MB/s | 314 MB/s | 36475792 | 36.48 |
|
||||||
| sdefl 1.0 -0 | 127 MB/s | 371 MB/s | 40004116 | 39.88 |
|
| sdefl 1.0 -0 | 127 MB/s | 355 MB/s | 40004116 | 39.88 |
|
||||||
| sdefl 1.0 -1 | 111 MB/s | 398 MB/s | 38940674 | 38.82 |
|
| sdefl 1.0 -1 | 111 MB/s | 413 MB/s | 38940674 | 38.82 |
|
||||||
| sdefl 1.0 -5 | 45 MB/s | 420 MB/s | 36577183 | 36.46 |
|
| sdefl 1.0 -5 | 45 MB/s | 436 MB/s | 36577183 | 36.46 |
|
||||||
| sdefl 1.0 -7 | 38 MB/s | 423 MB/s | 36523781 | 36.41 |
|
| sdefl 1.0 -7 | 38 MB/s | 432 MB/s | 36523781 | 36.41 |
|
||||||
| libdeflate 1.3 -1 | 147 MB/s | 667 MB/s | 39597378 | 39.60 |
|
| libdeflate 1.3 -1 | 147 MB/s | 667 MB/s | 39597378 | 39.60 |
|
||||||
| libdeflate 1.3 -6 | 69 MB/s | 689 MB/s | 36648318 | 36.65 |
|
| libdeflate 1.3 -6 | 69 MB/s | 689 MB/s | 36648318 | 36.65 |
|
||||||
| libdeflate 1.3 -9 | 13 MB/s | 672 MB/s | 35197141 | 35.20 |
|
| libdeflate 1.3 -9 | 13 MB/s | 672 MB/s | 35197141 | 35.20 |
|
||||||
|
@ -51,8 +51,8 @@ this file implementation in *one* C or C++ file to prevent collisions.
|
||||||
Results on the [Silesia compression corpus](http://sun.aei.polsl.pl/~sdeor/index.php?page=silesia):
|
Results on the [Silesia compression corpus](http://sun.aei.polsl.pl/~sdeor/index.php?page=silesia):
|
||||||
|
|
||||||
| File | Original | `sdefl 0` | `sdefl 5` | `sdefl 7` |
|
| File | Original | `sdefl 0` | `sdefl 5` | `sdefl 7` |
|
||||||
| :------ | ---------: | -----------------: | ---------: | ----------: |
|
| --------| -----------| -------------| ---------- | ------------|
|
||||||
| dickens | 10.192.446 | 4,260,187| 3,845,261| 3,833,657 |
|
| dickens | 10.192.446 | 4,260,187 | 3,845,261 | 3,833,657 |
|
||||||
| mozilla | 51.220.480 | 20,774,706 | 19,607,009 | 19,565,867 |
|
| mozilla | 51.220.480 | 20,774,706 | 19,607,009 | 19,565,867 |
|
||||||
| mr | 9.970.564 | 3,860,531 | 3,673,460 | 3,665,627 |
|
| mr | 9.970.564 | 3,860,531 | 3,673,460 | 3,665,627 |
|
||||||
| nci | 33.553.445 | 4,030,283 | 3,094,526 | 3,006,075 |
|
| nci | 33.553.445 | 4,030,283 | 3,094,526 | 3,006,075 |
|
||||||
|
@ -62,7 +62,7 @@ Results on the [Silesia compression corpus](http://sun.aei.polsl.pl/~sdeor/index
|
||||||
| samba | 21.606.400 | 6,121,797 | 5,462,670 | 5,450,762 |
|
| samba | 21.606.400 | 6,121,797 | 5,462,670 | 5,450,762 |
|
||||||
| sao | 7.251.944 | 5,612,421 | 5,485,380 | 5,481,765 |
|
| sao | 7.251.944 | 5,612,421 | 5,485,380 | 5,481,765 |
|
||||||
| webster | 41.458.703 | 13,972,648 | 12,059,432 | 11,991,421 |
|
| webster | 41.458.703 | 13,972,648 | 12,059,432 | 11,991,421 |
|
||||||
| xml | 5.345.280 | 886,620| 674,009 | 662,141 |
|
| xml | 5.345.280 | 886,620 | 674,009 | 662,141 |
|
||||||
| x-ray | 8.474.240 | 6,304,655 | 6,244,779 | 6,244,779 |
|
| x-ray | 8.474.240 | 6,304,655 | 6,244,779 | 6,244,779 |
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
@ -71,7 +71,7 @@ Results on the [Silesia compression corpus](http://sun.aei.polsl.pl/~sdeor/index
|
||||||
This software is available under 2 licenses -- choose whichever you prefer.
|
This software is available under 2 licenses -- choose whichever you prefer.
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
ALTERNATIVE A - MIT License
|
ALTERNATIVE A - MIT License
|
||||||
Copyright (c) 2020 Micha Mettke
|
Copyright (c) 2020-2023 Micha Mettke
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
this software and associated documentation files (the "Software"), to deal in
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
the Software without restriction, including without limitation the rights to
|
the Software without restriction, including without limitation the rights to
|
||||||
|
@ -125,7 +125,7 @@ extern "C" {
|
||||||
|
|
||||||
#define SDEFL_MIN_MATCH 4
|
#define SDEFL_MIN_MATCH 4
|
||||||
#define SDEFL_BLK_MAX (256*1024)
|
#define SDEFL_BLK_MAX (256*1024)
|
||||||
#define SDEFL_SEQ_SIZ ((SDEFL_BLK_MAX + SDEFL_MIN_MATCH)/SDEFL_MIN_MATCH)
|
#define SDEFL_SEQ_SIZ ((SDEFL_BLK_MAX+2)/3)
|
||||||
|
|
||||||
#define SDEFL_SYM_MAX (288)
|
#define SDEFL_SYM_MAX (288)
|
||||||
#define SDEFL_OFF_MAX (32)
|
#define SDEFL_OFF_MAX (32)
|
||||||
|
@ -185,6 +185,7 @@ extern int zsdeflate(struct sdefl *s, void *o, const void *i, int n, int lvl);
|
||||||
#define SDEFL_MAX_CODE_LEN (15)
|
#define SDEFL_MAX_CODE_LEN (15)
|
||||||
#define SDEFL_SYM_BITS (10u)
|
#define SDEFL_SYM_BITS (10u)
|
||||||
#define SDEFL_SYM_MSK ((1u << SDEFL_SYM_BITS)-1u)
|
#define SDEFL_SYM_MSK ((1u << SDEFL_SYM_BITS)-1u)
|
||||||
|
#define SDEFL_RAW_BLK_SIZE (65535)
|
||||||
#define SDEFL_LIT_LEN_CODES (14)
|
#define SDEFL_LIT_LEN_CODES (14)
|
||||||
#define SDEFL_OFF_CODES (15)
|
#define SDEFL_OFF_CODES (15)
|
||||||
#define SDEFL_PRE_CODES (7)
|
#define SDEFL_PRE_CODES (7)
|
||||||
|
@ -192,6 +193,7 @@ extern int zsdeflate(struct sdefl *s, void *o, const void *i, int n, int lvl);
|
||||||
#define SDEFL_EOB (256)
|
#define SDEFL_EOB (256)
|
||||||
|
|
||||||
#define sdefl_npow2(n) (1 << (sdefl_ilog2((n)-1) + 1))
|
#define sdefl_npow2(n) (1 << (sdefl_ilog2((n)-1) + 1))
|
||||||
|
#define sdefl_div_round_up(n,d) (((n)+((d)-1))/(d))
|
||||||
|
|
||||||
static int
|
static int
|
||||||
sdefl_ilog2(int n) {
|
sdefl_ilog2(int n) {
|
||||||
|
@ -438,12 +440,12 @@ sdefl_precode(struct sdefl_symcnt *cnt, unsigned *freqs, unsigned *items,
|
||||||
} while (run_start != total);
|
} while (run_start != total);
|
||||||
cnt->items = (int)(at - items);
|
cnt->items = (int)(at - items);
|
||||||
}
|
}
|
||||||
struct sdefl_match_codes {
|
struct sdefl_match_codest {
|
||||||
int ls, lc;
|
int ls, lc;
|
||||||
int dc, dx;
|
int dc, dx;
|
||||||
};
|
};
|
||||||
static void
|
static void
|
||||||
sdefl_match_codes(struct sdefl_match_codes *cod, int dist, int len) {
|
sdefl_match_codes(struct sdefl_match_codest *cod, int dist, int len) {
|
||||||
static const short dxmax[] = {0,6,12,24,48,96,192,384,768,1536,3072,6144,12288,24576};
|
static const short dxmax[] = {0,6,12,24,48,96,192,384,768,1536,3072,6144,12288,24576};
|
||||||
static const unsigned char lslot[258+1] = {
|
static const unsigned char lslot[258+1] = {
|
||||||
0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12,
|
0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12,
|
||||||
|
@ -462,11 +464,53 @@ sdefl_match_codes(struct sdefl_match_codes *cod, int dist, int len) {
|
||||||
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
|
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||||
27, 27, 28
|
27, 27, 28
|
||||||
};
|
};
|
||||||
|
assert(len <= 258);
|
||||||
|
assert(dist <= 32768);
|
||||||
cod->ls = lslot[len];
|
cod->ls = lslot[len];
|
||||||
cod->lc = 257 + cod->ls;
|
cod->lc = 257 + cod->ls;
|
||||||
|
assert(cod->lc <= 285);
|
||||||
|
|
||||||
cod->dx = sdefl_ilog2(sdefl_npow2(dist) >> 2);
|
cod->dx = sdefl_ilog2(sdefl_npow2(dist) >> 2);
|
||||||
cod->dc = cod->dx ? ((cod->dx + 1) << 1) + (dist > dxmax[cod->dx]) : dist-1;
|
cod->dc = cod->dx ? ((cod->dx + 1) << 1) + (dist > dxmax[cod->dx]) : dist-1;
|
||||||
}
|
}
|
||||||
|
enum sdefl_blk_type {
|
||||||
|
SDEFL_BLK_UCOMPR,
|
||||||
|
SDEFL_BLK_DYN
|
||||||
|
};
|
||||||
|
static enum sdefl_blk_type
|
||||||
|
sdefl_blk_type(const struct sdefl *s, int blk_len, int pre_item_len,
|
||||||
|
const unsigned *pre_freq, const unsigned char *pre_len) {
|
||||||
|
static const unsigned char x_pre_bits[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
|
||||||
|
static const unsigned char x_len_bits[] = {0,0,0,0,0,0,0,0, 1,1,1,1,2,2,2,2,
|
||||||
|
3,3,3,3,4,4,4,4, 5,5,5,5,0};
|
||||||
|
static const unsigned char x_off_bits[] = {0,0,0,0,1,1,2,2, 3,3,4,4,5,5,6,6,
|
||||||
|
7,7,8,8,9,9,10,10, 11,11,12,12,13,13};
|
||||||
|
|
||||||
|
int dyn_cost = 0;
|
||||||
|
int fix_cost = 0;
|
||||||
|
int sym = 0;
|
||||||
|
|
||||||
|
dyn_cost += 5 + 5 + 4 + (3 * pre_item_len);
|
||||||
|
for (sym = 0; sym < SDEFL_PRE_MAX; sym++)
|
||||||
|
dyn_cost += pre_freq[sym] * (x_pre_bits[sym] + pre_len[sym]);
|
||||||
|
for (sym = 0; sym < 256; sym++)
|
||||||
|
dyn_cost += s->freq.lit[sym] * s->cod.len.lit[sym];
|
||||||
|
dyn_cost += s->cod.len.lit[SDEFL_EOB];
|
||||||
|
for (sym = 257; sym < 286; sym++)
|
||||||
|
dyn_cost += s->freq.lit[sym] * (x_len_bits[sym - 257] + s->cod.len.lit[sym]);
|
||||||
|
for (sym = 0; sym < 30; sym++)
|
||||||
|
dyn_cost += s->freq.off[sym] * (x_off_bits[sym] + s->cod.len.off[sym]);
|
||||||
|
|
||||||
|
fix_cost += 8*(5 * sdefl_div_round_up(blk_len, SDEFL_RAW_BLK_SIZE) + blk_len + 1 + 2);
|
||||||
|
return (dyn_cost < fix_cost) ? SDEFL_BLK_DYN : SDEFL_BLK_UCOMPR;
|
||||||
|
}
|
||||||
|
static void
|
||||||
|
sdefl_put16(unsigned char **dst, unsigned short x) {
|
||||||
|
unsigned char *val = *dst;
|
||||||
|
val[0] = (unsigned char)(x & 0xff);
|
||||||
|
val[1] = (unsigned char)(x >> 8);
|
||||||
|
*dst = val + 2;
|
||||||
|
}
|
||||||
static void
|
static void
|
||||||
sdefl_match(unsigned char **dst, struct sdefl *s, int dist, int len) {
|
sdefl_match(unsigned char **dst, struct sdefl *s, int dist, int len) {
|
||||||
static const char lxn[] = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
|
static const char lxn[] = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
|
||||||
|
@ -475,7 +519,7 @@ sdefl_match(unsigned char **dst, struct sdefl *s, int dist, int len) {
|
||||||
static const short dmin[] = {1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,
|
static const short dmin[] = {1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,
|
||||||
385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577};
|
385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577};
|
||||||
|
|
||||||
struct sdefl_match_codes cod;
|
struct sdefl_match_codest cod;
|
||||||
sdefl_match_codes(&cod, dist, len);
|
sdefl_match_codes(&cod, dist, len);
|
||||||
sdefl_put(dst, s, (int)s->cod.word.lit[cod.lc], s->cod.len.lit[cod.lc]);
|
sdefl_put(dst, s, (int)s->cod.word.lit[cod.lc], s->cod.len.lit[cod.lc]);
|
||||||
sdefl_put(dst, s, len - lmin[cod.ls], lxn[cod.ls]);
|
sdefl_put(dst, s, len - lmin[cod.ls], lxn[cod.ls]);
|
||||||
|
@ -484,7 +528,8 @@ sdefl_match(unsigned char **dst, struct sdefl *s, int dist, int len) {
|
||||||
}
|
}
|
||||||
static void
|
static void
|
||||||
sdefl_flush(unsigned char **dst, struct sdefl *s, int is_last,
|
sdefl_flush(unsigned char **dst, struct sdefl *s, int is_last,
|
||||||
const unsigned char *in) {
|
const unsigned char *in, int blk_begin, int blk_end) {
|
||||||
|
int blk_len = blk_end - blk_begin;
|
||||||
int j, i = 0, item_cnt = 0;
|
int j, i = 0, item_cnt = 0;
|
||||||
struct sdefl_symcnt symcnt = {0};
|
struct sdefl_symcnt symcnt = {0};
|
||||||
unsigned codes[SDEFL_PRE_MAX];
|
unsigned codes[SDEFL_PRE_MAX];
|
||||||
|
@ -494,23 +539,48 @@ sdefl_flush(unsigned char **dst, struct sdefl *s, int is_last,
|
||||||
static const unsigned char perm[SDEFL_PRE_MAX] = {16,17,18,0,8,7,9,6,10,5,11,
|
static const unsigned char perm[SDEFL_PRE_MAX] = {16,17,18,0,8,7,9,6,10,5,11,
|
||||||
4,12,3,13,2,14,1,15};
|
4,12,3,13,2,14,1,15};
|
||||||
|
|
||||||
/* huffman codes */
|
/* calculate huffman codes */
|
||||||
s->freq.lit[SDEFL_EOB]++;
|
s->freq.lit[SDEFL_EOB]++;
|
||||||
sdefl_huff(s->cod.len.lit, s->cod.word.lit, s->freq.lit, SDEFL_SYM_MAX, SDEFL_LIT_LEN_CODES);
|
sdefl_huff(s->cod.len.lit, s->cod.word.lit, s->freq.lit, SDEFL_SYM_MAX, SDEFL_LIT_LEN_CODES);
|
||||||
sdefl_huff(s->cod.len.off, s->cod.word.off, s->freq.off, SDEFL_OFF_MAX, SDEFL_OFF_CODES);
|
sdefl_huff(s->cod.len.off, s->cod.word.off, s->freq.off, SDEFL_OFF_MAX, SDEFL_OFF_CODES);
|
||||||
sdefl_precode(&symcnt, freqs, items, s->cod.len.lit, s->cod.len.off);
|
sdefl_precode(&symcnt, freqs, items, s->cod.len.lit, s->cod.len.off);
|
||||||
sdefl_huff(lens, codes, freqs, SDEFL_PRE_MAX, SDEFL_PRE_CODES);
|
sdefl_huff(lens, codes, freqs, SDEFL_PRE_MAX, SDEFL_PRE_CODES);
|
||||||
for (item_cnt = SDEFL_PRE_MAX; item_cnt > 4; item_cnt--) {
|
for (item_cnt = SDEFL_PRE_MAX; item_cnt > 4; item_cnt--) {
|
||||||
if (lens[perm[item_cnt - 1]]) break;
|
if (lens[perm[item_cnt - 1]]){
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
/* block header */
|
}
|
||||||
sdefl_put(dst, s, is_last ? 0x01 : 0x00, 1); /* block */
|
/* write block */
|
||||||
|
switch (sdefl_blk_type(s, blk_len, item_cnt, freqs, lens)) {
|
||||||
|
case SDEFL_BLK_UCOMPR: {
|
||||||
|
/* uncompressed blocks */
|
||||||
|
int n = sdefl_div_round_up(blk_len, SDEFL_RAW_BLK_SIZE);
|
||||||
|
for (i = 0; i < n; ++i) {
|
||||||
|
int fin = is_last && (i + 1 == n);
|
||||||
|
int amount = blk_len < SDEFL_RAW_BLK_SIZE ? blk_len : SDEFL_RAW_BLK_SIZE;
|
||||||
|
sdefl_put(dst, s, !!fin, 1); /* block */
|
||||||
|
sdefl_put(dst, s, 0x00, 2); /* stored block */
|
||||||
|
if (s->bitcnt) {
|
||||||
|
sdefl_put(dst, s, 0x00, 8 - s->bitcnt);
|
||||||
|
}
|
||||||
|
assert(s->bitcnt == 0);
|
||||||
|
sdefl_put16(dst, (unsigned short)amount);
|
||||||
|
sdefl_put16(dst, ~(unsigned short)amount);
|
||||||
|
memcpy(*dst, in + blk_begin + i * SDEFL_RAW_BLK_SIZE, amount);
|
||||||
|
*dst = *dst + amount;
|
||||||
|
blk_len -= amount;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case SDEFL_BLK_DYN: {
|
||||||
|
/* dynamic huffman block */
|
||||||
|
sdefl_put(dst, s, !!is_last, 1); /* block */
|
||||||
sdefl_put(dst, s, 0x02, 2); /* dynamic huffman */
|
sdefl_put(dst, s, 0x02, 2); /* dynamic huffman */
|
||||||
sdefl_put(dst, s, symcnt.lit - 257, 5);
|
sdefl_put(dst, s, symcnt.lit - 257, 5);
|
||||||
sdefl_put(dst, s, symcnt.off - 1, 5);
|
sdefl_put(dst, s, symcnt.off - 1, 5);
|
||||||
sdefl_put(dst, s, item_cnt - 4, 4);
|
sdefl_put(dst, s, item_cnt - 4, 4);
|
||||||
for (i = 0; i < item_cnt; ++i)
|
for (i = 0; i < item_cnt; ++i) {
|
||||||
sdefl_put(dst, s, lens[perm[i]], 3);
|
sdefl_put(dst, s, lens[perm[i]], 3);
|
||||||
|
}
|
||||||
for (i = 0; i < symcnt.items; ++i) {
|
for (i = 0; i < symcnt.items; ++i) {
|
||||||
unsigned sym = items[i] & 0x1F;
|
unsigned sym = items[i] & 0x1F;
|
||||||
sdefl_put(dst, s, (int)codes[sym], lens[sym]);
|
sdefl_put(dst, s, (int)codes[sym], lens[sym]);
|
||||||
|
@ -521,14 +591,17 @@ sdefl_flush(unsigned char **dst, struct sdefl *s, int is_last,
|
||||||
}
|
}
|
||||||
/* block sequences */
|
/* block sequences */
|
||||||
for (i = 0; i < s->seq_cnt; ++i) {
|
for (i = 0; i < s->seq_cnt; ++i) {
|
||||||
if (s->seq[i].off >= 0)
|
if (s->seq[i].off >= 0) {
|
||||||
for (j = 0; j < s->seq[i].len; ++j) {
|
for (j = 0; j < s->seq[i].len; ++j) {
|
||||||
int c = in[s->seq[i].off + j];
|
int c = in[s->seq[i].off + j];
|
||||||
sdefl_put(dst, s, (int)s->cod.word.lit[c], s->cod.len.lit[c]);
|
sdefl_put(dst, s, (int)s->cod.word.lit[c], s->cod.len.lit[c]);
|
||||||
}
|
}
|
||||||
else sdefl_match(dst, s, -s->seq[i].off, s->seq[i].len);
|
} else {
|
||||||
|
sdefl_match(dst, s, -s->seq[i].off, s->seq[i].len);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sdefl_put(dst, s, (int)(s)->cod.word.lit[SDEFL_EOB], (s)->cod.len.lit[SDEFL_EOB]);
|
sdefl_put(dst, s, (int)(s)->cod.word.lit[SDEFL_EOB], (s)->cod.len.lit[SDEFL_EOB]);
|
||||||
|
} break;}
|
||||||
memset(&s->freq, 0, sizeof(s->freq));
|
memset(&s->freq, 0, sizeof(s->freq));
|
||||||
s->seq_cnt = 0;
|
s->seq_cnt = 0;
|
||||||
}
|
}
|
||||||
|
@ -541,8 +614,12 @@ sdefl_seq(struct sdefl *s, int off, int len) {
|
||||||
}
|
}
|
||||||
static void
|
static void
|
||||||
sdefl_reg_match(struct sdefl *s, int off, int len) {
|
sdefl_reg_match(struct sdefl *s, int off, int len) {
|
||||||
struct sdefl_match_codes cod;
|
struct sdefl_match_codest cod;
|
||||||
sdefl_match_codes(&cod, off, len);
|
sdefl_match_codes(&cod, off, len);
|
||||||
|
|
||||||
|
assert(cod.lc < SDEFL_SYM_MAX);
|
||||||
|
assert(cod.dc < SDEFL_OFF_MAX);
|
||||||
|
|
||||||
s->freq.lit[cod.lc]++;
|
s->freq.lit[cod.lc]++;
|
||||||
s->freq.off[cod.dc]++;
|
s->freq.off[cod.dc]++;
|
||||||
}
|
}
|
||||||
|
@ -551,22 +628,35 @@ struct sdefl_match {
|
||||||
int len;
|
int len;
|
||||||
};
|
};
|
||||||
static void
|
static void
|
||||||
sdefl_fnd(struct sdefl_match *m, const struct sdefl *s,
|
sdefl_fnd(struct sdefl_match *m, const struct sdefl *s, int chain_len,
|
||||||
int chain_len, int max_match, const unsigned char *in, int p) {
|
int max_match, const unsigned char *in, int p, int e) {
|
||||||
int i = s->tbl[sdefl_hash32(&in[p])];
|
int i = s->tbl[sdefl_hash32(in + p)];
|
||||||
int limit = ((p-SDEFL_WIN_SIZ)<SDEFL_NIL)?SDEFL_NIL:(p-SDEFL_WIN_SIZ);
|
int limit = ((p - SDEFL_WIN_SIZ) < SDEFL_NIL) ? SDEFL_NIL : (p-SDEFL_WIN_SIZ);
|
||||||
|
|
||||||
|
assert(p < e);
|
||||||
|
assert(p + max_match <= e);
|
||||||
while (i > limit) {
|
while (i > limit) {
|
||||||
if (in[i+m->len] == in[p+m->len] &&
|
assert(i + m->len < e);
|
||||||
(sdefl_uload32(&in[i]) == sdefl_uload32(&in[p]))){
|
assert(p + m->len < e);
|
||||||
|
assert(i + SDEFL_MIN_MATCH < e);
|
||||||
|
assert(p + SDEFL_MIN_MATCH < e);
|
||||||
|
|
||||||
|
if (in[i + m->len] == in[p + m->len] &&
|
||||||
|
(sdefl_uload32(&in[i]) == sdefl_uload32(&in[p]))) {
|
||||||
int n = SDEFL_MIN_MATCH;
|
int n = SDEFL_MIN_MATCH;
|
||||||
while (n < max_match && in[i+n] == in[p+n]) n++;
|
while (n < max_match && in[i + n] == in[p + n]) {
|
||||||
|
assert(i + n < e);
|
||||||
|
assert(p + n < e);
|
||||||
|
n++;
|
||||||
|
}
|
||||||
if (n > m->len) {
|
if (n > m->len) {
|
||||||
m->len = n, m->off = p - i;
|
m->len = n, m->off = p - i;
|
||||||
if (n == max_match) break;
|
if (n == max_match)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!(--chain_len)) break;
|
if (!(--chain_len)) break;
|
||||||
i = s->prv[i&SDEFL_WIN_MSK];
|
i = s->prv[i & SDEFL_WIN_MSK];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static int
|
static int
|
||||||
|
@ -579,18 +669,20 @@ sdefl_compr(struct sdefl *s, unsigned char *out, const unsigned char *in,
|
||||||
for (n = 0; n < SDEFL_HASH_SIZ; ++n) {
|
for (n = 0; n < SDEFL_HASH_SIZ; ++n) {
|
||||||
s->tbl[n] = SDEFL_NIL;
|
s->tbl[n] = SDEFL_NIL;
|
||||||
}
|
}
|
||||||
do {int blk_end = i + SDEFL_BLK_MAX < in_len ? i + SDEFL_BLK_MAX : in_len;
|
do {int blk_begin = i;
|
||||||
|
int blk_end = ((i + SDEFL_BLK_MAX) < in_len) ? (i + SDEFL_BLK_MAX) : in_len;
|
||||||
while (i < blk_end) {
|
while (i < blk_end) {
|
||||||
struct sdefl_match m = {0};
|
struct sdefl_match m = {0};
|
||||||
int max_match = ((in_len-i)>SDEFL_MAX_MATCH) ? SDEFL_MAX_MATCH:(in_len-i);
|
int left = blk_end - i;
|
||||||
|
int max_match = (left > SDEFL_MAX_MATCH) ? SDEFL_MAX_MATCH : left;
|
||||||
int nice_match = pref[lvl] < max_match ? pref[lvl] : max_match;
|
int nice_match = pref[lvl] < max_match ? pref[lvl] : max_match;
|
||||||
int run = 1, inc = 1, run_inc;
|
int run = 1, inc = 1, run_inc = 0;
|
||||||
if (max_match > SDEFL_MIN_MATCH) {
|
if (max_match > SDEFL_MIN_MATCH) {
|
||||||
sdefl_fnd(&m, s, max_chain, max_match, in, i);
|
sdefl_fnd(&m, s, max_chain, max_match, in, i, in_len);
|
||||||
}
|
}
|
||||||
if (lvl >= 5 && m.len >= SDEFL_MIN_MATCH && m.len < nice_match){
|
if (lvl >= 5 && m.len >= SDEFL_MIN_MATCH && m.len + 1 < nice_match){
|
||||||
struct sdefl_match m2 = {0};
|
struct sdefl_match m2 = {0};
|
||||||
sdefl_fnd(&m2, s, max_chain, m.len+1, in, i+1);
|
sdefl_fnd(&m2, s, max_chain, m.len + 1, in, i + 1, in_len);
|
||||||
m.len = (m2.len > m.len) ? 0 : m.len;
|
m.len = (m2.len > m.len) ? 0 : m.len;
|
||||||
}
|
}
|
||||||
if (m.len >= SDEFL_MIN_MATCH) {
|
if (m.len >= SDEFL_MIN_MATCH) {
|
||||||
|
@ -615,20 +707,23 @@ sdefl_compr(struct sdefl *s, unsigned char *out, const unsigned char *in,
|
||||||
unsigned h = sdefl_hash32(&in[i]);
|
unsigned h = sdefl_hash32(&in[i]);
|
||||||
s->prv[i&SDEFL_WIN_MSK] = s->tbl[h];
|
s->prv[i&SDEFL_WIN_MSK] = s->tbl[h];
|
||||||
s->tbl[h] = i, i += inc;
|
s->tbl[h] = i, i += inc;
|
||||||
|
assert(i <= blk_end);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
i += run_inc;
|
i += run_inc;
|
||||||
|
assert(i <= blk_end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (litlen) {
|
if (litlen) {
|
||||||
sdefl_seq(s, i - litlen, litlen);
|
sdefl_seq(s, i - litlen, litlen);
|
||||||
litlen = 0;
|
litlen = 0;
|
||||||
}
|
}
|
||||||
sdefl_flush(&q, s, blk_end == in_len, in);
|
sdefl_flush(&q, s, blk_end == in_len, in, blk_begin, blk_end);
|
||||||
} while (i < in_len);
|
} while (i < in_len);
|
||||||
|
if (s->bitcnt) {
|
||||||
if (s->bitcnt)
|
|
||||||
sdefl_put(&q, s, 0x00, 8 - s->bitcnt);
|
sdefl_put(&q, s, 0x00, 8 - s->bitcnt);
|
||||||
|
}
|
||||||
|
assert(s->bitcnt == 0);
|
||||||
return (int)(q - out);
|
return (int)(q - out);
|
||||||
}
|
}
|
||||||
extern int
|
extern int
|
||||||
|
@ -688,9 +783,8 @@ zsdeflate(struct sdefl *s, void *out, const void *in, int n, int lvl) {
|
||||||
}
|
}
|
||||||
extern int
|
extern int
|
||||||
sdefl_bound(int len) {
|
sdefl_bound(int len) {
|
||||||
int a = 128 + (len * 110) / 100;
|
int max_blocks = 1 + sdefl_div_round_up(len, SDEFL_RAW_BLK_SIZE);
|
||||||
int b = 128 + len + ((len / (31 * 1024)) + 1) * 5;
|
int bound = 5 * max_blocks + len + 1 + 4 + 8;
|
||||||
return (a > b) ? a : b;
|
return bound;
|
||||||
}
|
}
|
||||||
#endif /* SDEFL_IMPLEMENTATION */
|
#endif /* SDEFL_IMPLEMENTATION */
|
||||||
|
|
||||||
|
|
137
raylib/external/sinfl.h
vendored
137
raylib/external/sinfl.h
vendored
|
@ -10,7 +10,7 @@ as needed to keep the implementation as concise as possible.
|
||||||
- Dual license with either MIT or public domain
|
- Dual license with either MIT or public domain
|
||||||
- Small implementation
|
- Small implementation
|
||||||
- Deflate: 525 LoC
|
- Deflate: 525 LoC
|
||||||
- Inflate: 320 LoC
|
- Inflate: 500 LoC
|
||||||
- Webassembly:
|
- Webassembly:
|
||||||
- Deflate ~3.7 KB (~2.2KB compressed)
|
- Deflate ~3.7 KB (~2.2KB compressed)
|
||||||
- Inflate ~3.6 KB (~2.2KB compressed)
|
- Inflate ~3.6 KB (~2.2KB compressed)
|
||||||
|
@ -39,10 +39,10 @@ this file implementation in *one* C or C++ file to prevent collisions.
|
||||||
| zlib 1.2.11 -1 | 72 MB/s | 307 MB/s | 42298774 | 42.30 |
|
| zlib 1.2.11 -1 | 72 MB/s | 307 MB/s | 42298774 | 42.30 |
|
||||||
| zlib 1.2.11 -6 | 24 MB/s | 313 MB/s | 36548921 | 36.55 |
|
| zlib 1.2.11 -6 | 24 MB/s | 313 MB/s | 36548921 | 36.55 |
|
||||||
| zlib 1.2.11 -9 | 20 MB/s | 314 MB/s | 36475792 | 36.48 |
|
| zlib 1.2.11 -9 | 20 MB/s | 314 MB/s | 36475792 | 36.48 |
|
||||||
| sdefl 1.0 -0 | 127 MB/s | 371 MB/s | 40004116 | 39.88 |
|
| sdefl 1.0 -0 | 127 MB/s | 355 MB/s | 40004116 | 39.88 |
|
||||||
| sdefl 1.0 -1 | 111 MB/s | 398 MB/s | 38940674 | 38.82 |
|
| sdefl 1.0 -1 | 111 MB/s | 413 MB/s | 38940674 | 38.82 |
|
||||||
| sdefl 1.0 -5 | 45 MB/s | 420 MB/s | 36577183 | 36.46 |
|
| sdefl 1.0 -5 | 45 MB/s | 436 MB/s | 36577183 | 36.46 |
|
||||||
| sdefl 1.0 -7 | 38 MB/s | 423 MB/s | 36523781 | 36.41 |
|
| sdefl 1.0 -7 | 38 MB/s | 432 MB/s | 36523781 | 36.41 |
|
||||||
| libdeflate 1.3 -1 | 147 MB/s | 667 MB/s | 39597378 | 39.60 |
|
| libdeflate 1.3 -1 | 147 MB/s | 667 MB/s | 39597378 | 39.60 |
|
||||||
| libdeflate 1.3 -6 | 69 MB/s | 689 MB/s | 36648318 | 36.65 |
|
| libdeflate 1.3 -6 | 69 MB/s | 689 MB/s | 36648318 | 36.65 |
|
||||||
| libdeflate 1.3 -9 | 13 MB/s | 672 MB/s | 35197141 | 35.20 |
|
| libdeflate 1.3 -9 | 13 MB/s | 672 MB/s | 35197141 | 35.20 |
|
||||||
|
@ -52,8 +52,8 @@ this file implementation in *one* C or C++ file to prevent collisions.
|
||||||
Results on the [Silesia compression corpus](http://sun.aei.polsl.pl/~sdeor/index.php?page=silesia):
|
Results on the [Silesia compression corpus](http://sun.aei.polsl.pl/~sdeor/index.php?page=silesia):
|
||||||
|
|
||||||
| File | Original | `sdefl 0` | `sdefl 5` | `sdefl 7` |
|
| File | Original | `sdefl 0` | `sdefl 5` | `sdefl 7` |
|
||||||
| :------ | ---------: | -----------------: | ---------: | ----------: |
|
| --------| -----------| -------------| ---------- | ------------|
|
||||||
| dickens | 10.192.446 | 4,260,187| 3,845,261| 3,833,657 |
|
| dickens | 10.192.446 | 4,260,187 | 3,845,261 | 3,833,657 |
|
||||||
| mozilla | 51.220.480 | 20,774,706 | 19,607,009 | 19,565,867 |
|
| mozilla | 51.220.480 | 20,774,706 | 19,607,009 | 19,565,867 |
|
||||||
| mr | 9.970.564 | 3,860,531 | 3,673,460 | 3,665,627 |
|
| mr | 9.970.564 | 3,860,531 | 3,673,460 | 3,665,627 |
|
||||||
| nci | 33.553.445 | 4,030,283 | 3,094,526 | 3,006,075 |
|
| nci | 33.553.445 | 4,030,283 | 3,094,526 | 3,006,075 |
|
||||||
|
@ -63,7 +63,7 @@ Results on the [Silesia compression corpus](http://sun.aei.polsl.pl/~sdeor/index
|
||||||
| samba | 21.606.400 | 6,121,797 | 5,462,670 | 5,450,762 |
|
| samba | 21.606.400 | 6,121,797 | 5,462,670 | 5,450,762 |
|
||||||
| sao | 7.251.944 | 5,612,421 | 5,485,380 | 5,481,765 |
|
| sao | 7.251.944 | 5,612,421 | 5,485,380 | 5,481,765 |
|
||||||
| webster | 41.458.703 | 13,972,648 | 12,059,432 | 11,991,421 |
|
| webster | 41.458.703 | 13,972,648 | 12,059,432 | 11,991,421 |
|
||||||
| xml | 5.345.280 | 886,620| 674,009 | 662,141 |
|
| xml | 5.345.280 | 886,620 | 674,009 | 662,141 |
|
||||||
| x-ray | 8.474.240 | 6,304,655 | 6,244,779 | 6,244,779 |
|
| x-ray | 8.474.240 | 6,304,655 | 6,244,779 | 6,244,779 |
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
@ -72,7 +72,7 @@ Results on the [Silesia compression corpus](http://sun.aei.polsl.pl/~sdeor/index
|
||||||
This software is available under 2 licenses -- choose whichever you prefer.
|
This software is available under 2 licenses -- choose whichever you prefer.
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
ALTERNATIVE A - MIT License
|
ALTERNATIVE A - MIT License
|
||||||
Copyright (c) 2020 Micha Mettke
|
Copyright (c) 2020-2023 Micha Mettke
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
this software and associated documentation files (the "Software"), to deal in
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
the Software without restriction, including without limitation the rights to
|
the Software without restriction, including without limitation the rights to
|
||||||
|
@ -151,7 +151,7 @@ extern int zsinflate(void *out, int cap, const void *in, int size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef SINFL_NO_SIMD
|
#ifndef SINFL_NO_SIMD
|
||||||
#if __x86_64__ || defined(_WIN32) || defined(_WIN64)
|
#if defined(__x86_64__) || defined(_WIN32) || defined(_WIN64)
|
||||||
#include <emmintrin.h>
|
#include <emmintrin.h>
|
||||||
#define sinfl_char16 __m128i
|
#define sinfl_char16 __m128i
|
||||||
#define sinfl_char16_ld(p) _mm_loadu_si128((const __m128i *)(void*)(p))
|
#define sinfl_char16_ld(p) _mm_loadu_si128((const __m128i *)(void*)(p))
|
||||||
|
@ -183,6 +183,18 @@ sinfl_read64(const void *p) {
|
||||||
memcpy(&n, p, 8);
|
memcpy(&n, p, 8);
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
static void
|
||||||
|
sinfl_copy64(unsigned char **dst, unsigned char **src) {
|
||||||
|
unsigned long long n;
|
||||||
|
memcpy(&n, *src, 8);
|
||||||
|
memcpy(*dst, &n, 8);
|
||||||
|
*dst += 8, *src += 8;
|
||||||
|
}
|
||||||
|
static unsigned char*
|
||||||
|
sinfl_write64(unsigned char *dst, unsigned long long w) {
|
||||||
|
memcpy(dst, &w, 8);
|
||||||
|
return dst + 8;
|
||||||
|
}
|
||||||
#ifndef SINFL_NO_SIMD
|
#ifndef SINFL_NO_SIMD
|
||||||
static unsigned char*
|
static unsigned char*
|
||||||
sinfl_write128(unsigned char *dst, sinfl_char16 w) {
|
sinfl_write128(unsigned char *dst, sinfl_char16 w) {
|
||||||
|
@ -195,25 +207,12 @@ sinfl_copy128(unsigned char **dst, unsigned char **src) {
|
||||||
sinfl_char16_str(*dst, n);
|
sinfl_char16_str(*dst, n);
|
||||||
*dst += 16, *src += 16;
|
*dst += 16, *src += 16;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
static unsigned char*
|
|
||||||
sinfl_write64(unsigned char *dst, unsigned long long w) {
|
|
||||||
memcpy(dst, &w, 8);
|
|
||||||
return dst + 8;
|
|
||||||
}
|
|
||||||
static void
|
|
||||||
sinfl_copy64(unsigned char **dst, unsigned char **src) {
|
|
||||||
unsigned long long n;
|
|
||||||
memcpy(&n, *src, 8);
|
|
||||||
memcpy(*dst, &n, 8);
|
|
||||||
*dst += 8, *src += 8;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
static void
|
static void
|
||||||
sinfl_refill(struct sinfl *s) {
|
sinfl_refill(struct sinfl *s) {
|
||||||
s->bitbuf |= sinfl_read64(s->bitptr) << s->bitcnt;
|
s->bitbuf |= sinfl_read64(s->bitptr) << s->bitcnt;
|
||||||
s->bitptr += (63 - s->bitcnt) >> 3;
|
s->bitptr += (63 - s->bitcnt) >> 3;
|
||||||
s->bitcnt |= 56; /* bitcount is in range [56,63] */
|
s->bitcnt |= 56; /* bitcount in range [56,63] */
|
||||||
}
|
}
|
||||||
static int
|
static int
|
||||||
sinfl_peek(struct sinfl *s, int cnt) {
|
sinfl_peek(struct sinfl *s, int cnt) {
|
||||||
|
@ -222,7 +221,7 @@ sinfl_peek(struct sinfl *s, int cnt) {
|
||||||
return s->bitbuf & ((1ull << cnt) - 1);
|
return s->bitbuf & ((1ull << cnt) - 1);
|
||||||
}
|
}
|
||||||
static void
|
static void
|
||||||
sinfl_consume(struct sinfl *s, int cnt) {
|
sinfl_eat(struct sinfl *s, int cnt) {
|
||||||
assert(cnt <= s->bitcnt);
|
assert(cnt <= s->bitcnt);
|
||||||
s->bitbuf >>= cnt;
|
s->bitbuf >>= cnt;
|
||||||
s->bitcnt -= cnt;
|
s->bitcnt -= cnt;
|
||||||
|
@ -230,7 +229,7 @@ sinfl_consume(struct sinfl *s, int cnt) {
|
||||||
static int
|
static int
|
||||||
sinfl__get(struct sinfl *s, int cnt) {
|
sinfl__get(struct sinfl *s, int cnt) {
|
||||||
int res = sinfl_peek(s, cnt);
|
int res = sinfl_peek(s, cnt);
|
||||||
sinfl_consume(s, cnt);
|
sinfl_eat(s, cnt);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
static int
|
static int
|
||||||
|
@ -285,7 +284,7 @@ sinfl_build_subtbl(struct sinfl_gen *gen, unsigned *tbl, int tbl_bits,
|
||||||
while (1) {
|
while (1) {
|
||||||
unsigned entry;
|
unsigned entry;
|
||||||
int bit, stride, i;
|
int bit, stride, i;
|
||||||
/* start new subtable */
|
/* start new sub-table */
|
||||||
if ((gen->word & ((1 << tbl_bits)-1)) != sub_prefix) {
|
if ((gen->word & ((1 << tbl_bits)-1)) != sub_prefix) {
|
||||||
int used = 0;
|
int used = 0;
|
||||||
sub_prefix = gen->word & ((1 << tbl_bits)-1);
|
sub_prefix = gen->word & ((1 << tbl_bits)-1);
|
||||||
|
@ -299,7 +298,7 @@ sinfl_build_subtbl(struct sinfl_gen *gen, unsigned *tbl, int tbl_bits,
|
||||||
tbl_end = sub_start + (1 << sub_bits);
|
tbl_end = sub_start + (1 << sub_bits);
|
||||||
tbl[sub_prefix] = (sub_start << 16) | 0x10 | (sub_bits & 0xf);
|
tbl[sub_prefix] = (sub_start << 16) | 0x10 | (sub_bits & 0xf);
|
||||||
}
|
}
|
||||||
/* fill subtable */
|
/* fill sub-table */
|
||||||
entry = (*gen->sorted << 16) | ((gen->len - tbl_bits) & 0xf);
|
entry = (*gen->sorted << 16) | ((gen->len - tbl_bits) & 0xf);
|
||||||
gen->sorted++;
|
gen->sorted++;
|
||||||
i = sub_start + (gen->word >> tbl_bits);
|
i = sub_start + (gen->word >> tbl_bits);
|
||||||
|
@ -353,18 +352,17 @@ sinfl_build(unsigned *tbl, unsigned char *lens, int tbl_bits, int maxlen,
|
||||||
}
|
}
|
||||||
static int
|
static int
|
||||||
sinfl_decode(struct sinfl *s, const unsigned *tbl, int bit_len) {
|
sinfl_decode(struct sinfl *s, const unsigned *tbl, int bit_len) {
|
||||||
sinfl_refill(s);
|
int idx = sinfl_peek(s, bit_len);
|
||||||
{int idx = sinfl_peek(s, bit_len);
|
|
||||||
unsigned key = tbl[idx];
|
unsigned key = tbl[idx];
|
||||||
if (key & 0x10) {
|
if (key & 0x10) {
|
||||||
/* sub-table lookup */
|
/* sub-table lookup */
|
||||||
int len = key & 0x0f;
|
int len = key & 0x0f;
|
||||||
sinfl_consume(s, bit_len);
|
sinfl_eat(s, bit_len);
|
||||||
idx = sinfl_peek(s, len);
|
idx = sinfl_peek(s, len);
|
||||||
key = tbl[((key >> 16) & 0xffff) + (unsigned)idx];
|
key = tbl[((key >> 16) & 0xffff) + (unsigned)idx];
|
||||||
}
|
}
|
||||||
sinfl_consume(s, key & 0x0f);
|
sinfl_eat(s, key & 0x0f);
|
||||||
return (key >> 16) & 0x0fff;}
|
return (key >> 16) & 0x0fff;
|
||||||
}
|
}
|
||||||
static int
|
static int
|
||||||
sinfl_decompress(unsigned char *out, int cap, const unsigned char *in, int size) {
|
sinfl_decompress(unsigned char *out, int cap, const unsigned char *in, int size) {
|
||||||
|
@ -402,17 +400,21 @@ sinfl_decompress(unsigned char *out, int cap, const unsigned char *in, int size)
|
||||||
} break;
|
} break;
|
||||||
case stored: {
|
case stored: {
|
||||||
/* uncompressed block */
|
/* uncompressed block */
|
||||||
int len;
|
unsigned len, nlen;
|
||||||
sinfl_refill(&s);
|
|
||||||
sinfl__get(&s,s.bitcnt & 7);
|
sinfl__get(&s,s.bitcnt & 7);
|
||||||
len = sinfl__get(&s,16);
|
len = (unsigned short)sinfl__get(&s,16);
|
||||||
//int nlen = sinfl__get(&s,16); // @raysan5: Unused variable?
|
nlen = (unsigned short)sinfl__get(&s,16);
|
||||||
in -= 2; s.bitcnt = 0;
|
s.bitptr -= s.bitcnt / 8;
|
||||||
|
s.bitbuf = s.bitcnt = 0;
|
||||||
|
|
||||||
if (len > (e-in) || !len)
|
if ((unsigned short)len != (unsigned short)~nlen)
|
||||||
return (int)(out-o);
|
return (int)(out-o);
|
||||||
memcpy(out, in, (size_t)len);
|
if (len > (e - s.bitptr) || !len)
|
||||||
in += len, out += len;
|
return (int)(out-o);
|
||||||
|
|
||||||
|
memcpy(out, s.bitptr, (size_t)len);
|
||||||
|
s.bitptr += len, out += len;
|
||||||
|
if (last) return (int)(out-o);
|
||||||
state = hdr;
|
state = hdr;
|
||||||
} break;
|
} break;
|
||||||
case fixed: {
|
case fixed: {
|
||||||
|
@ -445,7 +447,9 @@ sinfl_decompress(unsigned char *out, int cap, const unsigned char *in, int size)
|
||||||
|
|
||||||
/* decode code lengths */
|
/* decode code lengths */
|
||||||
for (n = 0; n < nlit + ndist;) {
|
for (n = 0; n < nlit + ndist;) {
|
||||||
int sym = sinfl_decode(&s, hlens, 7);
|
int sym = 0;
|
||||||
|
sinfl_refill(&s);
|
||||||
|
sym = sinfl_decode(&s, hlens, 7);
|
||||||
switch (sym) {default: lens[n++] = (unsigned char)sym; break;
|
switch (sym) {default: lens[n++] = (unsigned char)sym; break;
|
||||||
case 16: for (i=3+sinfl_get(&s,2);i;i--,n++) lens[n]=lens[n-1]; break;
|
case 16: for (i=3+sinfl_get(&s,2);i;i--,n++) lens[n]=lens[n-1]; break;
|
||||||
case 17: for (i=3+sinfl_get(&s,3);i;i--,n++) lens[n]=0; break;
|
case 17: for (i=3+sinfl_get(&s,3);i;i--,n++) lens[n]=0; break;
|
||||||
|
@ -458,12 +462,34 @@ sinfl_decompress(unsigned char *out, int cap, const unsigned char *in, int size)
|
||||||
} break;
|
} break;
|
||||||
case blk: {
|
case blk: {
|
||||||
/* decompress block */
|
/* decompress block */
|
||||||
int sym = sinfl_decode(&s, s.lits, 10);
|
while (1) {
|
||||||
|
int sym;
|
||||||
|
sinfl_refill(&s);
|
||||||
|
sym = sinfl_decode(&s, s.lits, 10);
|
||||||
if (sym < 256) {
|
if (sym < 256) {
|
||||||
/* literal */
|
/* literal */
|
||||||
|
if (sinfl_unlikely(out >= oe)) {
|
||||||
|
return (int)(out-o);
|
||||||
|
}
|
||||||
*out++ = (unsigned char)sym;
|
*out++ = (unsigned char)sym;
|
||||||
} else if (sym > 256) {sym -= 257; /* match symbol */
|
sym = sinfl_decode(&s, s.lits, 10);
|
||||||
sinfl_refill(&s);
|
if (sym < 256) {
|
||||||
|
*out++ = (unsigned char)sym;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sinfl_unlikely(sym == 256)) {
|
||||||
|
/* end of block */
|
||||||
|
if (last) return (int)(out-o);
|
||||||
|
state = hdr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* match */
|
||||||
|
if (sym >= 286) {
|
||||||
|
/* length codes 286 and 287 must not appear in compressed data */
|
||||||
|
return (int)(out-o);
|
||||||
|
}
|
||||||
|
sym -= 257;
|
||||||
{int len = sinfl__get(&s, lbits[sym]) + lbase[sym];
|
{int len = sinfl__get(&s, lbits[sym]) + lbase[sym];
|
||||||
int dsym = sinfl_decode(&s, s.dsts, 8);
|
int dsym = sinfl_decode(&s, s.dsts, 8);
|
||||||
int offs = sinfl__get(&s, dbits[dsym]) + dbase[dsym];
|
int offs = sinfl__get(&s, dbits[dsym]) + dbase[dsym];
|
||||||
|
@ -476,11 +502,17 @@ sinfl_decompress(unsigned char *out, int cap, const unsigned char *in, int size)
|
||||||
#ifndef SINFL_NO_SIMD
|
#ifndef SINFL_NO_SIMD
|
||||||
if (sinfl_likely(oe - out >= 16 * 3)) {
|
if (sinfl_likely(oe - out >= 16 * 3)) {
|
||||||
if (offs >= 16) {
|
if (offs >= 16) {
|
||||||
/* copy match */
|
/* simd copy match */
|
||||||
sinfl_copy128(&dst, &src);
|
sinfl_copy128(&dst, &src);
|
||||||
sinfl_copy128(&dst, &src);
|
sinfl_copy128(&dst, &src);
|
||||||
do sinfl_copy128(&dst, &src);
|
do sinfl_copy128(&dst, &src);
|
||||||
while (dst < out);
|
while (dst < out);
|
||||||
|
} else if (offs >= 8) {
|
||||||
|
/* word copy match */
|
||||||
|
sinfl_copy64(&dst, &src);
|
||||||
|
sinfl_copy64(&dst, &src);
|
||||||
|
do sinfl_copy64(&dst, &src);
|
||||||
|
while (dst < out);
|
||||||
} else if (offs == 1) {
|
} else if (offs == 1) {
|
||||||
/* rle match copying */
|
/* rle match copying */
|
||||||
sinfl_char16 w = sinfl_char16_char(src[0]);
|
sinfl_char16 w = sinfl_char16_char(src[0]);
|
||||||
|
@ -489,6 +521,7 @@ sinfl_decompress(unsigned char *out, int cap, const unsigned char *in, int size)
|
||||||
do dst = sinfl_write128(dst, w);
|
do dst = sinfl_write128(dst, w);
|
||||||
while (dst < out);
|
while (dst < out);
|
||||||
} else {
|
} else {
|
||||||
|
/* byte copy match */
|
||||||
*dst++ = *src++;
|
*dst++ = *src++;
|
||||||
*dst++ = *src++;
|
*dst++ = *src++;
|
||||||
do *dst++ = *src++;
|
do *dst++ = *src++;
|
||||||
|
@ -498,7 +531,7 @@ sinfl_decompress(unsigned char *out, int cap, const unsigned char *in, int size)
|
||||||
#else
|
#else
|
||||||
if (sinfl_likely(oe - out >= 3 * 8 - 3)) {
|
if (sinfl_likely(oe - out >= 3 * 8 - 3)) {
|
||||||
if (offs >= 8) {
|
if (offs >= 8) {
|
||||||
/* copy match */
|
/* word copy match */
|
||||||
sinfl_copy64(&dst, &src);
|
sinfl_copy64(&dst, &src);
|
||||||
sinfl_copy64(&dst, &src);
|
sinfl_copy64(&dst, &src);
|
||||||
do sinfl_copy64(&dst, &src);
|
do sinfl_copy64(&dst, &src);
|
||||||
|
@ -513,6 +546,7 @@ sinfl_decompress(unsigned char *out, int cap, const unsigned char *in, int size)
|
||||||
do dst = sinfl_write64(dst, w);
|
do dst = sinfl_write64(dst, w);
|
||||||
while (dst < out);
|
while (dst < out);
|
||||||
} else {
|
} else {
|
||||||
|
/* byte copy match */
|
||||||
*dst++ = *src++;
|
*dst++ = *src++;
|
||||||
*dst++ = *src++;
|
*dst++ = *src++;
|
||||||
do *dst++ = *src++;
|
do *dst++ = *src++;
|
||||||
|
@ -524,13 +558,8 @@ sinfl_decompress(unsigned char *out, int cap, const unsigned char *in, int size)
|
||||||
*dst++ = *src++;
|
*dst++ = *src++;
|
||||||
*dst++ = *src++;
|
*dst++ = *src++;
|
||||||
do *dst++ = *src++;
|
do *dst++ = *src++;
|
||||||
while (dst < out);}
|
while (dst < out);
|
||||||
}
|
}}
|
||||||
} else {
|
|
||||||
/* end of block */
|
|
||||||
if (last) return (int)(out-o);
|
|
||||||
state = hdr;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} break;}
|
} break;}
|
||||||
}
|
}
|
||||||
|
|
2634
raylib/external/stb_image_resize.h
vendored
2634
raylib/external/stb_image_resize.h
vendored
File diff suppressed because it is too large
Load diff
10303
raylib/external/stb_image_resize2.h
vendored
Normal file
10303
raylib/external/stb_image_resize2.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
7
raylib/external/tinyobj_loader_c.h
vendored
7
raylib/external/tinyobj_loader_c.h
vendored
|
@ -746,7 +746,7 @@ static int tinyobj_parse_and_index_mtl_file(tinyobj_material_t **materials_out,
|
||||||
(*materials_out) = NULL;
|
(*materials_out) = NULL;
|
||||||
(*num_materials_out) = 0;
|
(*num_materials_out) = 0;
|
||||||
|
|
||||||
fp = fopen(filename, "r");
|
fp = fopen(filename, "rt");
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
fprintf(stderr, "TINYOBJ: Error reading file '%s': %s (%d)\n", filename, strerror(errno), errno);
|
fprintf(stderr, "TINYOBJ: Error reading file '%s': %s (%d)\n", filename, strerror(errno), errno);
|
||||||
return TINYOBJ_ERROR_FILE_OPERATION;
|
return TINYOBJ_ERROR_FILE_OPERATION;
|
||||||
|
@ -1269,6 +1269,11 @@ int tinyobj_parse_obj(tinyobj_attrib_t *attrib, tinyobj_shape_t **shapes,
|
||||||
if (is_line_ending(buf, i, end_idx)) {
|
if (is_line_ending(buf, i, end_idx)) {
|
||||||
line_infos[line_no].pos = prev_pos;
|
line_infos[line_no].pos = prev_pos;
|
||||||
line_infos[line_no].len = i - prev_pos;
|
line_infos[line_no].len = i - prev_pos;
|
||||||
|
|
||||||
|
// ---- QUICK BUG FIX : https://github.com/raysan5/raylib/issues/3473
|
||||||
|
if ( i > 0 && buf[i-1] == '\r' ) line_infos[line_no].len--;
|
||||||
|
// --------
|
||||||
|
|
||||||
prev_pos = i + 1;
|
prev_pos = i + 1;
|
||||||
line_no++;
|
line_no++;
|
||||||
}
|
}
|
||||||
|
|
2
raylib/external/vox_loader.h
vendored
2
raylib/external/vox_loader.h
vendored
|
@ -555,7 +555,7 @@ int Vox_LoadFromMemory(unsigned char* pvoxData, unsigned int voxDataSize, VoxArr
|
||||||
version = ((unsigned int*)fileDataPtr)[0];
|
version = ((unsigned int*)fileDataPtr)[0];
|
||||||
fileDataPtr += 4;
|
fileDataPtr += 4;
|
||||||
|
|
||||||
if (version != 150)
|
if (version != 150 && version != 200)
|
||||||
{
|
{
|
||||||
return VOX_ERROR_FILE_VERSION_NOT_MATCH; //"MagicaVoxel version doesn't match"
|
return VOX_ERROR_FILE_VERSION_NOT_MATCH; //"MagicaVoxel version doesn't match"
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,8 @@ package rl
|
||||||
|
|
||||||
extern void android_init();
|
extern void android_init();
|
||||||
|
|
||||||
AAssetManager* asset_manager;
|
extern AAssetManager* asset_manager;
|
||||||
const char* internal_storage_path;
|
extern const char* internal_storage_path;
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//go:build !rpi && !drm && !android
|
//go:build !sdl && !drm && !android
|
||||||
// +build !rpi,!drm,!android
|
// +build !sdl,!drm,!android
|
||||||
|
|
||||||
package rl
|
package rl
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//go:build linux && rpi && !drm && !android
|
//go:build sdl && !drm && !android
|
||||||
// +build linux,rpi,!drm,!android
|
// +build sdl,!drm,!android
|
||||||
|
|
||||||
package rl
|
package rl
|
||||||
|
|
||||||
|
@ -27,7 +27,6 @@ func InitWindow(width int32, height int32, title string) {
|
||||||
|
|
||||||
// SetCallbackFunc - Sets callback function
|
// SetCallbackFunc - Sets callback function
|
||||||
func SetCallbackFunc(func()) {
|
func SetCallbackFunc(func()) {
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ShowCursor - Shows cursor
|
// ShowCursor - Shows cursor
|
||||||
|
@ -66,17 +65,27 @@ func DisableCursor() {
|
||||||
|
|
||||||
// IsFileDropped - Check if a file have been dropped into window
|
// IsFileDropped - Check if a file have been dropped into window
|
||||||
func IsFileDropped() bool {
|
func IsFileDropped() bool {
|
||||||
return false
|
ret := C.IsFileDropped()
|
||||||
|
v := bool(ret)
|
||||||
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadDroppedFiles - Load dropped filepaths
|
// LoadDroppedFiles - Load dropped filepaths
|
||||||
func LoadDroppedFiles() (files []string) {
|
func LoadDroppedFiles() []string {
|
||||||
return
|
ret := C.LoadDroppedFiles()
|
||||||
|
defer C.UnloadDroppedFiles(ret)
|
||||||
|
|
||||||
|
tmpslice := (*[1 << 24]*C.char)(unsafe.Pointer(ret.paths))[:ret.count:ret.count]
|
||||||
|
gostrings := make([]string, ret.count)
|
||||||
|
for i, s := range tmpslice {
|
||||||
|
gostrings[i] = C.GoString(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
return gostrings
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnloadDroppedFiles - Unload dropped filepaths
|
// UnloadDroppedFiles - Unload dropped filepaths
|
||||||
func UnloadDroppedFiles() {
|
func UnloadDroppedFiles() {
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenAsset - Open asset
|
// OpenAsset - Open asset
|
|
@ -1,5 +1,5 @@
|
||||||
//go:build linux && drm && !rpi && !android
|
//go:build linux && drm && !sdl && !android
|
||||||
// +build linux,drm,!rpi,!android
|
// +build linux,drm,!sdl,!android
|
||||||
|
|
||||||
package rl
|
package rl
|
||||||
|
|
||||||
|
|
1137
raylib/platforms/rcore_android.c
Normal file
1137
raylib/platforms/rcore_android.c
Normal file
File diff suppressed because it is too large
Load diff
1829
raylib/platforms/rcore_desktop.c
Normal file
1829
raylib/platforms/rcore_desktop.c
Normal file
File diff suppressed because it is too large
Load diff
1358
raylib/platforms/rcore_desktop_sdl.c
Normal file
1358
raylib/platforms/rcore_desktop_sdl.c
Normal file
File diff suppressed because it is too large
Load diff
1942
raylib/platforms/rcore_drm.c
Normal file
1942
raylib/platforms/rcore_drm.c
Normal file
File diff suppressed because it is too large
Load diff
176
raylib/raudio.c
176
raylib/raudio.c
|
@ -14,7 +14,6 @@
|
||||||
* - Play/Stop/Pause/Resume loaded audio
|
* - Play/Stop/Pause/Resume loaded audio
|
||||||
*
|
*
|
||||||
* CONFIGURATION:
|
* CONFIGURATION:
|
||||||
*
|
|
||||||
* #define SUPPORT_MODULE_RAUDIO
|
* #define SUPPORT_MODULE_RAUDIO
|
||||||
* raudio module is included in the build
|
* raudio module is included in the build
|
||||||
*
|
*
|
||||||
|
@ -45,7 +44,7 @@
|
||||||
* David Reid (github: @mackron) (Nov. 2017):
|
* David Reid (github: @mackron) (Nov. 2017):
|
||||||
* - Complete port to miniaudio library
|
* - Complete port to miniaudio library
|
||||||
*
|
*
|
||||||
* Joshua Reisenauer (github: @kd7tck) (2015)
|
* Joshua Reisenauer (github: @kd7tck) (2015):
|
||||||
* - XM audio module support (jar_xm)
|
* - XM audio module support (jar_xm)
|
||||||
* - MOD audio module support (jar_mod)
|
* - MOD audio module support (jar_mod)
|
||||||
* - Mixing channels support
|
* - Mixing channels support
|
||||||
|
@ -231,9 +230,20 @@ typedef struct tagBITMAPINFOHEADER {
|
||||||
#define QOA_MALLOC RL_MALLOC
|
#define QOA_MALLOC RL_MALLOC
|
||||||
#define QOA_FREE RL_FREE
|
#define QOA_FREE RL_FREE
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) // Disable some MSVC warning
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4018)
|
||||||
|
#pragma warning(disable : 4267)
|
||||||
|
#pragma warning(disable : 4244)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define QOA_IMPLEMENTATION
|
#define QOA_IMPLEMENTATION
|
||||||
#include "external/qoa.h" // QOA loading and saving functions
|
#include "external/qoa.h" // QOA loading and saving functions
|
||||||
#include "external/qoaplay.c" // QOA stream playing helper functions
|
#include "external/qoaplay.c" // QOA stream playing helper functions
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(pop) // Disable MSVC warning suppression
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(SUPPORT_FILEFORMAT_FLAC)
|
#if defined(SUPPORT_FILEFORMAT_FLAC)
|
||||||
|
@ -250,16 +260,16 @@ typedef struct tagBITMAPINFOHEADER {
|
||||||
#define JARXM_MALLOC RL_MALLOC
|
#define JARXM_MALLOC RL_MALLOC
|
||||||
#define JARXM_FREE RL_FREE
|
#define JARXM_FREE RL_FREE
|
||||||
|
|
||||||
#if defined(_MSC_VER ) // jar_xm has warnings on windows, so disable them just for this file
|
#if defined(_MSC_VER) // Disable some MSVC warning
|
||||||
#pragma warning( push )
|
#pragma warning(push)
|
||||||
#pragma warning( disable : 4244)
|
#pragma warning(disable : 4244)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define JAR_XM_IMPLEMENTATION
|
#define JAR_XM_IMPLEMENTATION
|
||||||
#include "external/jar_xm.h" // XM loading functions
|
#include "external/jar_xm.h" // XM loading functions
|
||||||
|
|
||||||
#if defined(_MSC_VER )
|
#if defined(_MSC_VER)
|
||||||
#pragma warning( pop )
|
#pragma warning(pop) // Disable MSVC warning suppression
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -406,8 +416,8 @@ static void MixAudioFrames(float *framesOut, const float *framesIn, ma_uint32 fr
|
||||||
static bool IsFileExtension(const char *fileName, const char *ext); // Check file extension
|
static bool IsFileExtension(const char *fileName, const char *ext); // Check file extension
|
||||||
static const char *GetFileExtension(const char *fileName); // Get pointer to extension for a filename string (includes the dot: .png)
|
static const char *GetFileExtension(const char *fileName); // Get pointer to extension for a filename string (includes the dot: .png)
|
||||||
|
|
||||||
static unsigned char *LoadFileData(const char *fileName, unsigned int *bytesRead); // Load file data as byte array (read)
|
static unsigned char *LoadFileData(const char *fileName, int *dataSize); // Load file data as byte array (read)
|
||||||
static bool SaveFileData(const char *fileName, void *data, unsigned int bytesToWrite); // Save data to file from byte array (write)
|
static bool SaveFileData(const char *fileName, void *data, int dataSize); // Save data to file from byte array (write)
|
||||||
static bool SaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated
|
static bool SaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -467,6 +477,16 @@ void InitAudioDevice(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mixing happens on a separate thread which means we need to synchronize. I'm using a mutex here to make things simple, but may
|
||||||
|
// want to look at something a bit smarter later on to keep everything real-time, if that's necessary.
|
||||||
|
if (ma_mutex_init(&AUDIO.System.lock) != MA_SUCCESS)
|
||||||
|
{
|
||||||
|
TRACELOG(LOG_WARNING, "AUDIO: Failed to create mutex for mixing");
|
||||||
|
ma_device_uninit(&AUDIO.System.device);
|
||||||
|
ma_context_uninit(&AUDIO.System.context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Keep the device running the whole time. May want to consider doing something a bit smarter and only have the device running
|
// Keep the device running the whole time. May want to consider doing something a bit smarter and only have the device running
|
||||||
// while there's at least one sound being played.
|
// while there's at least one sound being played.
|
||||||
result = ma_device_start(&AUDIO.System.device);
|
result = ma_device_start(&AUDIO.System.device);
|
||||||
|
@ -478,16 +498,6 @@ void InitAudioDevice(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mixing happens on a separate thread which means we need to synchronize. I'm using a mutex here to make things simple, but may
|
|
||||||
// want to look at something a bit smarter later on to keep everything real-time, if that's necessary.
|
|
||||||
if (ma_mutex_init(&AUDIO.System.lock) != MA_SUCCESS)
|
|
||||||
{
|
|
||||||
TRACELOG(LOG_WARNING, "AUDIO: Failed to create mutex for mixing");
|
|
||||||
ma_device_uninit(&AUDIO.System.device);
|
|
||||||
ma_context_uninit(&AUDIO.System.context);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACELOG(LOG_INFO, "AUDIO: Device initialized successfully");
|
TRACELOG(LOG_INFO, "AUDIO: Device initialized successfully");
|
||||||
TRACELOG(LOG_INFO, " > Backend: miniaudio / %s", ma_get_backend_name(AUDIO.System.context.backend));
|
TRACELOG(LOG_INFO, " > Backend: miniaudio / %s", ma_get_backend_name(AUDIO.System.context.backend));
|
||||||
TRACELOG(LOG_INFO, " > Format: %s -> %s", ma_get_format_name(AUDIO.System.device.playback.format), ma_get_format_name(AUDIO.System.device.playback.internalFormat));
|
TRACELOG(LOG_INFO, " > Format: %s -> %s", ma_get_format_name(AUDIO.System.device.playback.format), ma_get_format_name(AUDIO.System.device.playback.internalFormat));
|
||||||
|
@ -529,6 +539,14 @@ void SetMasterVolume(float volume)
|
||||||
ma_device_set_master_volume(&AUDIO.System.device, volume);
|
ma_device_set_master_volume(&AUDIO.System.device, volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get master volume (listener)
|
||||||
|
float GetMasterVolume(void)
|
||||||
|
{
|
||||||
|
float volume = 0.0f;
|
||||||
|
ma_device_get_master_volume(&AUDIO.System.device, &volume);
|
||||||
|
return volume;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Functions Definition - Audio Buffer management
|
// Module Functions Definition - Audio Buffer management
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
@ -725,11 +743,11 @@ Wave LoadWave(const char *fileName)
|
||||||
Wave wave = { 0 };
|
Wave wave = { 0 };
|
||||||
|
|
||||||
// Loading file to memory
|
// Loading file to memory
|
||||||
unsigned int fileSize = 0;
|
int dataSize = 0;
|
||||||
unsigned char *fileData = LoadFileData(fileName, &fileSize);
|
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
||||||
|
|
||||||
// Loading wave from memory data
|
// Loading wave from memory data
|
||||||
if (fileData != NULL) wave = LoadWaveFromMemory(GetFileExtension(fileName), fileData, fileSize);
|
if (fileData != NULL) wave = LoadWaveFromMemory(GetFileExtension(fileName), fileData, dataSize);
|
||||||
|
|
||||||
RL_FREE(fileData);
|
RL_FREE(fileData);
|
||||||
|
|
||||||
|
@ -744,7 +762,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
|
||||||
|
|
||||||
if (false) { }
|
if (false) { }
|
||||||
#if defined(SUPPORT_FILEFORMAT_WAV)
|
#if defined(SUPPORT_FILEFORMAT_WAV)
|
||||||
else if (strcmp(fileType, ".wav") == 0)
|
else if ((strcmp(fileType, ".wav") == 0) || (strcmp(fileType, ".WAV") == 0))
|
||||||
{
|
{
|
||||||
drwav wav = { 0 };
|
drwav wav = { 0 };
|
||||||
bool success = drwav_init_memory(&wav, fileData, dataSize, NULL);
|
bool success = drwav_init_memory(&wav, fileData, dataSize, NULL);
|
||||||
|
@ -766,7 +784,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_OGG)
|
#if defined(SUPPORT_FILEFORMAT_OGG)
|
||||||
else if (strcmp(fileType, ".ogg") == 0)
|
else if ((strcmp(fileType, ".ogg") == 0) || (strcmp(fileType, ".OGG") == 0))
|
||||||
{
|
{
|
||||||
stb_vorbis *oggData = stb_vorbis_open_memory((unsigned char *)fileData, dataSize, NULL, NULL);
|
stb_vorbis *oggData = stb_vorbis_open_memory((unsigned char *)fileData, dataSize, NULL, NULL);
|
||||||
|
|
||||||
|
@ -788,7 +806,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_MP3)
|
#if defined(SUPPORT_FILEFORMAT_MP3)
|
||||||
else if (strcmp(fileType, ".mp3") == 0)
|
else if ((strcmp(fileType, ".mp3") == 0) || (strcmp(fileType, ".MP3") == 0))
|
||||||
{
|
{
|
||||||
drmp3_config config = { 0 };
|
drmp3_config config = { 0 };
|
||||||
unsigned long long int totalFrameCount = 0;
|
unsigned long long int totalFrameCount = 0;
|
||||||
|
@ -808,7 +826,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_QOA)
|
#if defined(SUPPORT_FILEFORMAT_QOA)
|
||||||
else if (strcmp(fileType, ".qoa") == 0)
|
else if ((strcmp(fileType, ".qoa") == 0) || (strcmp(fileType, ".QOA") == 0))
|
||||||
{
|
{
|
||||||
qoa_desc qoa = { 0 };
|
qoa_desc qoa = { 0 };
|
||||||
|
|
||||||
|
@ -827,7 +845,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_FLAC)
|
#if defined(SUPPORT_FILEFORMAT_FLAC)
|
||||||
else if (strcmp(fileType, ".flac") == 0)
|
else if ((strcmp(fileType, ".flac") == 0) || (strcmp(fileType, ".FLAC") == 0))
|
||||||
{
|
{
|
||||||
unsigned long long int totalFrameCount = 0;
|
unsigned long long int totalFrameCount = 0;
|
||||||
|
|
||||||
|
@ -912,6 +930,35 @@ Sound LoadSoundFromWave(Wave wave)
|
||||||
return sound;
|
return sound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clone sound from existing sound data, clone does not own wave data
|
||||||
|
// NOTE: Wave data must be unallocated manually and will be shared across all clones
|
||||||
|
Sound LoadSoundAlias(Sound source)
|
||||||
|
{
|
||||||
|
Sound sound = { 0 };
|
||||||
|
|
||||||
|
if (source.stream.buffer->data != NULL)
|
||||||
|
{
|
||||||
|
AudioBuffer* audioBuffer = LoadAudioBuffer(AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, 0, AUDIO_BUFFER_USAGE_STATIC);
|
||||||
|
if (audioBuffer == NULL)
|
||||||
|
{
|
||||||
|
TRACELOG(LOG_WARNING, "SOUND: Failed to create buffer");
|
||||||
|
return sound; // early return to avoid dereferencing the audioBuffer null pointer
|
||||||
|
}
|
||||||
|
audioBuffer->sizeInFrames = source.stream.buffer->sizeInFrames;
|
||||||
|
audioBuffer->volume = source.stream.buffer->volume;
|
||||||
|
audioBuffer->data = source.stream.buffer->data;
|
||||||
|
|
||||||
|
sound.frameCount = source.frameCount;
|
||||||
|
sound.stream.sampleRate = AUDIO.System.device.sampleRate;
|
||||||
|
sound.stream.sampleSize = 32;
|
||||||
|
sound.stream.channels = AUDIO_DEVICE_CHANNELS;
|
||||||
|
sound.stream.buffer = audioBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sound;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Checks if a sound is ready
|
// Checks if a sound is ready
|
||||||
bool IsSoundReady(Sound sound)
|
bool IsSoundReady(Sound sound)
|
||||||
{
|
{
|
||||||
|
@ -936,15 +983,26 @@ void UnloadSound(Sound sound)
|
||||||
//TRACELOG(LOG_INFO, "SOUND: Unloaded sound data from RAM");
|
//TRACELOG(LOG_INFO, "SOUND: Unloaded sound data from RAM");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UnloadSoundAlias(Sound alias)
|
||||||
|
{
|
||||||
|
// untrack and unload just the sound buffer, not the sample data, it is shared with the source for the alias
|
||||||
|
if (alias.stream.buffer != NULL)
|
||||||
|
{
|
||||||
|
ma_data_converter_uninit(&alias.stream.buffer->converter, NULL);
|
||||||
|
UntrackAudioBuffer(alias.stream.buffer);
|
||||||
|
RL_FREE(alias.stream.buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update sound buffer with new data
|
// Update sound buffer with new data
|
||||||
void UpdateSound(Sound sound, const void *data, int sampleCount)
|
void UpdateSound(Sound sound, const void *data, int frameCount)
|
||||||
{
|
{
|
||||||
if (sound.stream.buffer != NULL)
|
if (sound.stream.buffer != NULL)
|
||||||
{
|
{
|
||||||
StopAudioBuffer(sound.stream.buffer);
|
StopAudioBuffer(sound.stream.buffer);
|
||||||
|
|
||||||
// TODO: May want to lock/unlock this since this data buffer is read at mixing time
|
// TODO: May want to lock/unlock this since this data buffer is read at mixing time
|
||||||
memcpy(sound.stream.buffer->data, data, sampleCount*ma_get_bytes_per_frame(sound.stream.buffer->converter.formatIn, sound.stream.buffer->converter.channelsIn));
|
memcpy(sound.stream.buffer->data, data, frameCount*ma_get_bytes_per_frame(sound.stream.buffer->converter.formatIn, sound.stream.buffer->converter.channelsIn));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1033,29 +1091,30 @@ bool ExportWaveAsCode(Wave wave, const char *fileName)
|
||||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||||
byteCount += sprintf(txtData + byteCount, "//////////////////////////////////////////////////////////////////////////////////\n\n");
|
byteCount += sprintf(txtData + byteCount, "//////////////////////////////////////////////////////////////////////////////////\n\n");
|
||||||
|
|
||||||
char fileNameLower[256] = { 0 };
|
// Get file name from path and convert variable name to uppercase
|
||||||
char fileNameUpper[256] = { 0 };
|
char varFileName[256] = { 0 };
|
||||||
for (int i = 0; fileName[i] != '.'; i++) { fileNameLower[i] = fileName[i]; } // Get filename without extension
|
strcpy(varFileName, GetFileNameWithoutExt(fileName));
|
||||||
for (int i = 0; fileNameLower[i] != '\0'; i++) if (fileNameLower[i] >= 'a' && fileNameLower[i] <= 'z') { fileNameUpper[i] = fileNameLower[i] - 32; }
|
for (int i = 0; varFileName[i] != '\0'; i++) if (varFileName[i] >= 'a' && varFileName[i] <= 'z') { varFileName[i] = varFileName[i] - 32; }
|
||||||
|
|
||||||
|
//Add wave information
|
||||||
byteCount += sprintf(txtData + byteCount, "// Wave data information\n");
|
byteCount += sprintf(txtData + byteCount, "// Wave data information\n");
|
||||||
byteCount += sprintf(txtData + byteCount, "#define %s_FRAME_COUNT %u\n", fileNameUpper, wave.frameCount);
|
byteCount += sprintf(txtData + byteCount, "#define %s_FRAME_COUNT %u\n", varFileName, wave.frameCount);
|
||||||
byteCount += sprintf(txtData + byteCount, "#define %s_SAMPLE_RATE %u\n", fileNameUpper, wave.sampleRate);
|
byteCount += sprintf(txtData + byteCount, "#define %s_SAMPLE_RATE %u\n", varFileName, wave.sampleRate);
|
||||||
byteCount += sprintf(txtData + byteCount, "#define %s_SAMPLE_SIZE %u\n", fileNameUpper, wave.sampleSize);
|
byteCount += sprintf(txtData + byteCount, "#define %s_SAMPLE_SIZE %u\n", varFileName, wave.sampleSize);
|
||||||
byteCount += sprintf(txtData + byteCount, "#define %s_CHANNELS %u\n\n", fileNameUpper, wave.channels);
|
byteCount += sprintf(txtData + byteCount, "#define %s_CHANNELS %u\n\n", varFileName, wave.channels);
|
||||||
|
|
||||||
// Write wave data as an array of values
|
// Write wave data as an array of values
|
||||||
// Wave data is exported as byte array for 8/16bit and float array for 32bit float data
|
// Wave data is exported as byte array for 8/16bit and float array for 32bit float data
|
||||||
// NOTE: Frame data exported is channel-interlaced: frame01[sampleChannel1, sampleChannel2, ...], frame02[], frame03[]
|
// NOTE: Frame data exported is channel-interlaced: frame01[sampleChannel1, sampleChannel2, ...], frame02[], frame03[]
|
||||||
if (wave.sampleSize == 32)
|
if (wave.sampleSize == 32)
|
||||||
{
|
{
|
||||||
byteCount += sprintf(txtData + byteCount, "static float %sData[%i] = {\n", fileNameLower, waveDataSize/4);
|
byteCount += sprintf(txtData + byteCount, "static float %s_DATA[%i] = {\n", varFileName, waveDataSize/4);
|
||||||
for (int i = 1; i < waveDataSize/4; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "%.4ff,\n " : "%.4ff, "), ((float *)wave.data)[i - 1]);
|
for (int i = 1; i < waveDataSize/4; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "%.4ff,\n " : "%.4ff, "), ((float *)wave.data)[i - 1]);
|
||||||
byteCount += sprintf(txtData + byteCount, "%.4ff };\n", ((float *)wave.data)[waveDataSize/4 - 1]);
|
byteCount += sprintf(txtData + byteCount, "%.4ff };\n", ((float *)wave.data)[waveDataSize/4 - 1]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
byteCount += sprintf(txtData + byteCount, "static unsigned char %sData[%i] = { ", fileNameLower, waveDataSize);
|
byteCount += sprintf(txtData + byteCount, "static unsigned char %s_DATA[%i] = { ", varFileName, waveDataSize);
|
||||||
for (int i = 1; i < waveDataSize; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%x,\n " : "0x%x, "), ((unsigned char *)wave.data)[i - 1]);
|
for (int i = 1; i < waveDataSize; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%x,\n " : "0x%x, "), ((unsigned char *)wave.data)[i - 1]);
|
||||||
byteCount += sprintf(txtData + byteCount, "0x%x };\n", ((unsigned char *)wave.data)[waveDataSize - 1]);
|
byteCount += sprintf(txtData + byteCount, "0x%x };\n", ((unsigned char *)wave.data)[waveDataSize - 1]);
|
||||||
}
|
}
|
||||||
|
@ -1383,7 +1442,7 @@ Music LoadMusicStream(const char *fileName)
|
||||||
else if (music.ctxType == MUSIC_AUDIO_MP3) { drmp3_uninit((drmp3 *)music.ctxData); RL_FREE(music.ctxData); }
|
else if (music.ctxType == MUSIC_AUDIO_MP3) { drmp3_uninit((drmp3 *)music.ctxData); RL_FREE(music.ctxData); }
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_QOA)
|
#if defined(SUPPORT_FILEFORMAT_QOA)
|
||||||
else if (music.ctxType == MUSIC_AUDIO_QOA) { /*TODO: Release QOA context data*/ RL_FREE(music.ctxData); }
|
else if (music.ctxType == MUSIC_AUDIO_QOA) qoaplay_close((qoaplay_desc *)music.ctxData);
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_FLAC)
|
#if defined(SUPPORT_FILEFORMAT_FLAC)
|
||||||
else if (music.ctxType == MUSIC_AUDIO_FLAC) drflac_free((drflac *)music.ctxData, NULL);
|
else if (music.ctxType == MUSIC_AUDIO_FLAC) drflac_free((drflac *)music.ctxData, NULL);
|
||||||
|
@ -1420,7 +1479,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
|
||||||
|
|
||||||
if (false) { }
|
if (false) { }
|
||||||
#if defined(SUPPORT_FILEFORMAT_WAV)
|
#if defined(SUPPORT_FILEFORMAT_WAV)
|
||||||
else if (strcmp(fileType, ".wav") == 0)
|
else if ((strcmp(fileType, ".wav") == 0) || (strcmp(fileType, ".WAV") == 0))
|
||||||
{
|
{
|
||||||
drwav *ctxWav = RL_CALLOC(1, sizeof(drwav));
|
drwav *ctxWav = RL_CALLOC(1, sizeof(drwav));
|
||||||
|
|
||||||
|
@ -1442,7 +1501,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_OGG)
|
#if defined(SUPPORT_FILEFORMAT_OGG)
|
||||||
else if (strcmp(fileType, ".ogg") == 0)
|
else if ((strcmp(fileType, ".ogg") == 0) || (strcmp(fileType, ".OGG") == 0))
|
||||||
{
|
{
|
||||||
// Open ogg audio stream
|
// Open ogg audio stream
|
||||||
music.ctxType = MUSIC_AUDIO_OGG;
|
music.ctxType = MUSIC_AUDIO_OGG;
|
||||||
|
@ -1464,7 +1523,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_MP3)
|
#if defined(SUPPORT_FILEFORMAT_MP3)
|
||||||
else if (strcmp(fileType, ".mp3") == 0)
|
else if ((strcmp(fileType, ".mp3") == 0) || (strcmp(fileType, ".MP3") == 0))
|
||||||
{
|
{
|
||||||
drmp3 *ctxMp3 = RL_CALLOC(1, sizeof(drmp3));
|
drmp3 *ctxMp3 = RL_CALLOC(1, sizeof(drmp3));
|
||||||
int success = drmp3_init_memory(ctxMp3, (const void*)data, dataSize, NULL);
|
int success = drmp3_init_memory(ctxMp3, (const void*)data, dataSize, NULL);
|
||||||
|
@ -1482,7 +1541,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_QOA)
|
#if defined(SUPPORT_FILEFORMAT_QOA)
|
||||||
else if (strcmp(fileType, ".qoa") == 0)
|
else if ((strcmp(fileType, ".qoa") == 0) || (strcmp(fileType, ".QOA") == 0))
|
||||||
{
|
{
|
||||||
qoaplay_desc *ctxQoa = qoaplay_open_memory(data, dataSize);
|
qoaplay_desc *ctxQoa = qoaplay_open_memory(data, dataSize);
|
||||||
music.ctxType = MUSIC_AUDIO_QOA;
|
music.ctxType = MUSIC_AUDIO_QOA;
|
||||||
|
@ -1500,7 +1559,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_FLAC)
|
#if defined(SUPPORT_FILEFORMAT_FLAC)
|
||||||
else if (strcmp(fileType, ".flac") == 0)
|
else if ((strcmp(fileType, ".flac") == 0) || (strcmp(fileType, ".FLAC") == 0))
|
||||||
{
|
{
|
||||||
music.ctxType = MUSIC_AUDIO_FLAC;
|
music.ctxType = MUSIC_AUDIO_FLAC;
|
||||||
music.ctxData = drflac_open_memory((const void*)data, dataSize, NULL);
|
music.ctxData = drflac_open_memory((const void*)data, dataSize, NULL);
|
||||||
|
@ -1517,7 +1576,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_XM)
|
#if defined(SUPPORT_FILEFORMAT_XM)
|
||||||
else if (strcmp(fileType, ".xm") == 0)
|
else if ((strcmp(fileType, ".xm") == 0) || (strcmp(fileType, ".XM") == 0))
|
||||||
{
|
{
|
||||||
jar_xm_context_t *ctxXm = NULL;
|
jar_xm_context_t *ctxXm = NULL;
|
||||||
int result = jar_xm_create_context_safe(&ctxXm, (const char *)data, dataSize, AUDIO.System.device.sampleRate);
|
int result = jar_xm_create_context_safe(&ctxXm, (const char *)data, dataSize, AUDIO.System.device.sampleRate);
|
||||||
|
@ -1542,7 +1601,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_MOD)
|
#if defined(SUPPORT_FILEFORMAT_MOD)
|
||||||
else if (strcmp(fileType, ".mod") == 0)
|
else if ((strcmp(fileType, ".mod") == 0) || (strcmp(fileType, ".MOD") == 0))
|
||||||
{
|
{
|
||||||
jar_mod_context_t *ctxMod = (jar_mod_context_t *)RL_MALLOC(sizeof(jar_mod_context_t));
|
jar_mod_context_t *ctxMod = (jar_mod_context_t *)RL_MALLOC(sizeof(jar_mod_context_t));
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
@ -1741,7 +1800,14 @@ void SeekMusicStream(Music music, float position)
|
||||||
case MUSIC_AUDIO_MP3: drmp3_seek_to_pcm_frame((drmp3 *)music.ctxData, positionInFrames); break;
|
case MUSIC_AUDIO_MP3: drmp3_seek_to_pcm_frame((drmp3 *)music.ctxData, positionInFrames); break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_QOA)
|
#if defined(SUPPORT_FILEFORMAT_QOA)
|
||||||
case MUSIC_AUDIO_QOA: qoaplay_seek_frame((qoaplay_desc *)music.ctxData, positionInFrames); break;
|
case MUSIC_AUDIO_QOA:
|
||||||
|
{
|
||||||
|
int qoaFrame = positionInFrames/QOA_FRAME_LEN;
|
||||||
|
qoaplay_seek_frame((qoaplay_desc *)music.ctxData, qoaFrame); // Seeks to QOA frame, not PCM frame
|
||||||
|
|
||||||
|
// We need to compute QOA frame number and update positionInFrames
|
||||||
|
positionInFrames = ((qoaplay_desc *)music.ctxData)->sample_position;
|
||||||
|
} break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_FLAC)
|
#if defined(SUPPORT_FILEFORMAT_FLAC)
|
||||||
case MUSIC_AUDIO_FLAC: drflac_seek_to_pcm_frame((drflac *)music.ctxData, positionInFrames); break;
|
case MUSIC_AUDIO_FLAC: drflac_seek_to_pcm_frame((drflac *)music.ctxData, positionInFrames); break;
|
||||||
|
@ -1861,7 +1927,7 @@ void UpdateMusicStream(Music music)
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
int frameCountRead = drflac_read_pcm_frames_s16((drflac *)music.ctxData, frameCountStillNeeded, (short *)((char *)AUDIO.System.pcmBuffer + frameCountReadTotal*frameSize));
|
int frameCountRead = (int)drflac_read_pcm_frames_s16((drflac *)music.ctxData, frameCountStillNeeded, (short *)((char *)AUDIO.System.pcmBuffer + frameCountReadTotal*frameSize));
|
||||||
frameCountReadTotal += frameCountRead;
|
frameCountReadTotal += frameCountRead;
|
||||||
frameCountStillNeeded -= frameCountRead;
|
frameCountStillNeeded -= frameCountRead;
|
||||||
if (frameCountStillNeeded == 0) break;
|
if (frameCountStillNeeded == 0) break;
|
||||||
|
@ -2574,10 +2640,10 @@ static const char *GetFileExtension(const char *fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load data from file into a buffer
|
// Load data from file into a buffer
|
||||||
static unsigned char *LoadFileData(const char *fileName, unsigned int *bytesRead)
|
static unsigned char *LoadFileData(const char *fileName, int *dataSize)
|
||||||
{
|
{
|
||||||
unsigned char *data = NULL;
|
unsigned char *data = NULL;
|
||||||
*bytesRead = 0;
|
*dataSize = 0;
|
||||||
|
|
||||||
if (fileName != NULL)
|
if (fileName != NULL)
|
||||||
{
|
{
|
||||||
|
@ -2597,7 +2663,7 @@ static unsigned char *LoadFileData(const char *fileName, unsigned int *bytesRead
|
||||||
|
|
||||||
// NOTE: fread() returns number of read elements instead of bytes, so we read [1 byte, size elements]
|
// NOTE: fread() returns number of read elements instead of bytes, so we read [1 byte, size elements]
|
||||||
unsigned int count = (unsigned int)fread(data, sizeof(unsigned char), size, file);
|
unsigned int count = (unsigned int)fread(data, sizeof(unsigned char), size, file);
|
||||||
*bytesRead = count;
|
*dataSize = count;
|
||||||
|
|
||||||
if (count != size) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially loaded", fileName);
|
if (count != size) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially loaded", fileName);
|
||||||
else TRACELOG(LOG_INFO, "FILEIO: [%s] File loaded successfully", fileName);
|
else TRACELOG(LOG_INFO, "FILEIO: [%s] File loaded successfully", fileName);
|
||||||
|
@ -2614,7 +2680,7 @@ static unsigned char *LoadFileData(const char *fileName, unsigned int *bytesRead
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save data to file from buffer
|
// Save data to file from buffer
|
||||||
static bool SaveFileData(const char *fileName, void *data, unsigned int bytesToWrite)
|
static bool SaveFileData(const char *fileName, void *data, int dataSize)
|
||||||
{
|
{
|
||||||
if (fileName != NULL)
|
if (fileName != NULL)
|
||||||
{
|
{
|
||||||
|
@ -2622,10 +2688,10 @@ static bool SaveFileData(const char *fileName, void *data, unsigned int bytesToW
|
||||||
|
|
||||||
if (file != NULL)
|
if (file != NULL)
|
||||||
{
|
{
|
||||||
unsigned int count = (unsigned int)fwrite(data, sizeof(unsigned char), bytesToWrite, file);
|
unsigned int count = (unsigned int)fwrite(data, sizeof(unsigned char), dataSize, file);
|
||||||
|
|
||||||
if (count == 0) TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to write file", fileName);
|
if (count == 0) TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to write file", fileName);
|
||||||
else if (count != bytesToWrite) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially written", fileName);
|
else if (count != dataSize) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially written", fileName);
|
||||||
else TRACELOG(LOG_INFO, "FILEIO: [%s] File saved successfully", fileName);
|
else TRACELOG(LOG_INFO, "FILEIO: [%s] File saved successfully", fileName);
|
||||||
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
|
141
raylib/raylib.h
141
raylib/raylib.h
|
@ -1,6 +1,6 @@
|
||||||
/**********************************************************************************************
|
/**********************************************************************************************
|
||||||
*
|
*
|
||||||
* raylib v4.5 - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com)
|
* raylib v4.6-dev - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com)
|
||||||
*
|
*
|
||||||
* FEATURES:
|
* FEATURES:
|
||||||
* - NO external dependencies, all required libraries included with raylib
|
* - NO external dependencies, all required libraries included with raylib
|
||||||
|
@ -81,10 +81,10 @@
|
||||||
|
|
||||||
#include <stdarg.h> // Required for: va_list - Only used by TraceLogCallback
|
#include <stdarg.h> // Required for: va_list - Only used by TraceLogCallback
|
||||||
|
|
||||||
#define RAYLIB_VERSION_MAJOR 4
|
#define RAYLIB_VERSION_MAJOR 5
|
||||||
#define RAYLIB_VERSION_MINOR 5
|
#define RAYLIB_VERSION_MINOR 0
|
||||||
#define RAYLIB_VERSION_PATCH 0
|
#define RAYLIB_VERSION_PATCH 0
|
||||||
#define RAYLIB_VERSION "4.5"
|
#define RAYLIB_VERSION "5.0"
|
||||||
|
|
||||||
// Function specifiers in case library is build/used as a shared library (Windows)
|
// Function specifiers in case library is build/used as a shared library (Windows)
|
||||||
// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
|
// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
|
||||||
|
@ -133,12 +133,20 @@
|
||||||
|
|
||||||
// NOTE: MSVC C++ compiler does not support compound literals (C99 feature)
|
// NOTE: MSVC C++ compiler does not support compound literals (C99 feature)
|
||||||
// Plain structures in C++ (without constructors) can be initialized with { }
|
// Plain structures in C++ (without constructors) can be initialized with { }
|
||||||
|
// This is called aggregate initialization (C++11 feature)
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
#define CLITERAL(type) type
|
#define CLITERAL(type) type
|
||||||
#else
|
#else
|
||||||
#define CLITERAL(type) (type)
|
#define CLITERAL(type) (type)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Some compilers (mostly macos clang) default to C++98,
|
||||||
|
// where aggregate initialization can't be used
|
||||||
|
// So, give a more clear error stating how to fix this
|
||||||
|
#if !defined(_MSC_VER) && (defined(__cplusplus) && __cplusplus < 201103L)
|
||||||
|
#error "C++11 or later is required. Add -std=c++11"
|
||||||
|
#endif
|
||||||
|
|
||||||
// NOTE: We set some defines with some data types declared by raylib
|
// NOTE: We set some defines with some data types declared by raylib
|
||||||
// Other modules (raymath, rlgl) also require some of those types, so,
|
// Other modules (raymath, rlgl) also require some of those types, so,
|
||||||
// to be able to use those other modules as standalone (not depending on raylib)
|
// to be able to use those other modules as standalone (not depending on raylib)
|
||||||
|
@ -402,6 +410,7 @@ typedef struct ModelAnimation {
|
||||||
int frameCount; // Number of animation frames
|
int frameCount; // Number of animation frames
|
||||||
BoneInfo *bones; // Bones information (skeleton)
|
BoneInfo *bones; // Bones information (skeleton)
|
||||||
Transform **framePoses; // Poses array by frame
|
Transform **framePoses; // Poses array by frame
|
||||||
|
char name[32]; // Animation name
|
||||||
} ModelAnimation;
|
} ModelAnimation;
|
||||||
|
|
||||||
// Ray, ray for raycasting
|
// Ray, ray for raycasting
|
||||||
|
@ -497,6 +506,20 @@ typedef struct FilePathList {
|
||||||
char **paths; // Filepaths entries
|
char **paths; // Filepaths entries
|
||||||
} FilePathList;
|
} FilePathList;
|
||||||
|
|
||||||
|
// Automation event
|
||||||
|
typedef struct AutomationEvent {
|
||||||
|
unsigned int frame; // Event frame
|
||||||
|
unsigned int type; // Event type (AutomationEventType)
|
||||||
|
int params[4]; // Event parameters (if required)
|
||||||
|
} AutomationEvent;
|
||||||
|
|
||||||
|
// Automation event list
|
||||||
|
typedef struct AutomationEventList {
|
||||||
|
unsigned int capacity; // Events max entries (MAX_AUTOMATION_EVENTS)
|
||||||
|
unsigned int count; // Events entries count
|
||||||
|
AutomationEvent *events; // Events entries
|
||||||
|
} AutomationEventList;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Enumerators Definition
|
// Enumerators Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
@ -517,6 +540,7 @@ typedef enum {
|
||||||
FLAG_WINDOW_TRANSPARENT = 0x00000010, // Set to allow transparent framebuffer
|
FLAG_WINDOW_TRANSPARENT = 0x00000010, // Set to allow transparent framebuffer
|
||||||
FLAG_WINDOW_HIGHDPI = 0x00002000, // Set to support HighDPI
|
FLAG_WINDOW_HIGHDPI = 0x00002000, // Set to support HighDPI
|
||||||
FLAG_WINDOW_MOUSE_PASSTHROUGH = 0x00004000, // Set to support mouse passthrough, only supported when FLAG_WINDOW_UNDECORATED
|
FLAG_WINDOW_MOUSE_PASSTHROUGH = 0x00004000, // Set to support mouse passthrough, only supported when FLAG_WINDOW_UNDECORATED
|
||||||
|
FLAG_BORDERLESS_WINDOWED_MODE = 0x00008000, // Set to run program in borderless windowed mode
|
||||||
FLAG_MSAA_4X_HINT = 0x00000020, // Set to try enabling MSAA 4X
|
FLAG_MSAA_4X_HINT = 0x00000020, // Set to try enabling MSAA 4X
|
||||||
FLAG_INTERLACED_HINT = 0x00010000 // Set to try enabling interlaced video format (for V3D)
|
FLAG_INTERLACED_HINT = 0x00010000 // Set to try enabling interlaced video format (for V3D)
|
||||||
} ConfigFlags;
|
} ConfigFlags;
|
||||||
|
@ -802,6 +826,9 @@ typedef enum {
|
||||||
PIXELFORMAT_UNCOMPRESSED_R32, // 32 bpp (1 channel - float)
|
PIXELFORMAT_UNCOMPRESSED_R32, // 32 bpp (1 channel - float)
|
||||||
PIXELFORMAT_UNCOMPRESSED_R32G32B32, // 32*3 bpp (3 channels - float)
|
PIXELFORMAT_UNCOMPRESSED_R32G32B32, // 32*3 bpp (3 channels - float)
|
||||||
PIXELFORMAT_UNCOMPRESSED_R32G32B32A32, // 32*4 bpp (4 channels - float)
|
PIXELFORMAT_UNCOMPRESSED_R32G32B32A32, // 32*4 bpp (4 channels - float)
|
||||||
|
PIXELFORMAT_UNCOMPRESSED_R16, // 16 bpp (1 channel - half float)
|
||||||
|
PIXELFORMAT_UNCOMPRESSED_R16G16B16, // 16*3 bpp (3 channels - half float)
|
||||||
|
PIXELFORMAT_UNCOMPRESSED_R16G16B16A16, // 16*4 bpp (4 channels - half float)
|
||||||
PIXELFORMAT_COMPRESSED_DXT1_RGB, // 4 bpp (no alpha)
|
PIXELFORMAT_COMPRESSED_DXT1_RGB, // 4 bpp (no alpha)
|
||||||
PIXELFORMAT_COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha)
|
PIXELFORMAT_COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha)
|
||||||
PIXELFORMAT_COMPRESSED_DXT3_RGBA, // 8 bpp
|
PIXELFORMAT_COMPRESSED_DXT3_RGBA, // 8 bpp
|
||||||
|
@ -905,8 +932,8 @@ typedef enum {
|
||||||
// Callbacks to hook some internal functions
|
// Callbacks to hook some internal functions
|
||||||
// WARNING: These callbacks are intended for advance users
|
// WARNING: These callbacks are intended for advance users
|
||||||
typedef void (*TraceLogCallback)(int logLevel, const char *text, va_list args); // Logging: Redirect trace log messages
|
typedef void (*TraceLogCallback)(int logLevel, const char *text, va_list args); // Logging: Redirect trace log messages
|
||||||
typedef unsigned char *(*LoadFileDataCallback)(const char *fileName, unsigned int *bytesRead); // FileIO: Load binary data
|
typedef unsigned char *(*LoadFileDataCallback)(const char *fileName, int *dataSize); // FileIO: Load binary data
|
||||||
typedef bool (*SaveFileDataCallback)(const char *fileName, void *data, unsigned int bytesToWrite); // FileIO: Save binary data
|
typedef bool (*SaveFileDataCallback)(const char *fileName, void *data, int dataSize); // FileIO: Save binary data
|
||||||
typedef char *(*LoadFileTextCallback)(const char *fileName); // FileIO: Load text data
|
typedef char *(*LoadFileTextCallback)(const char *fileName); // FileIO: Load text data
|
||||||
typedef bool (*SaveFileTextCallback)(const char *fileName, char *text); // FileIO: Save text data
|
typedef bool (*SaveFileTextCallback)(const char *fileName, char *text); // FileIO: Save text data
|
||||||
|
|
||||||
|
@ -925,8 +952,8 @@ extern "C" { // Prevents name mangling of functions
|
||||||
|
|
||||||
// Window-related functions
|
// Window-related functions
|
||||||
RLAPI void InitWindow(int width, int height, const char *title); // Initialize window and OpenGL context
|
RLAPI void InitWindow(int width, int height, const char *title); // Initialize window and OpenGL context
|
||||||
RLAPI bool WindowShouldClose(void); // Check if KEY_ESCAPE pressed or Close icon pressed
|
|
||||||
RLAPI void CloseWindow(void); // Close window and unload OpenGL context
|
RLAPI void CloseWindow(void); // Close window and unload OpenGL context
|
||||||
|
RLAPI bool WindowShouldClose(void); // Check if application should close (KEY_ESCAPE pressed or windows close icon clicked)
|
||||||
RLAPI bool IsWindowReady(void); // Check if window has been initialized successfully
|
RLAPI bool IsWindowReady(void); // Check if window has been initialized successfully
|
||||||
RLAPI bool IsWindowFullscreen(void); // Check if window is currently fullscreen
|
RLAPI bool IsWindowFullscreen(void); // Check if window is currently fullscreen
|
||||||
RLAPI bool IsWindowHidden(void); // Check if window is currently hidden (only PLATFORM_DESKTOP)
|
RLAPI bool IsWindowHidden(void); // Check if window is currently hidden (only PLATFORM_DESKTOP)
|
||||||
|
@ -938,17 +965,20 @@ RLAPI bool IsWindowState(unsigned int flag); // Check if on
|
||||||
RLAPI void SetWindowState(unsigned int flags); // Set window configuration state using flags (only PLATFORM_DESKTOP)
|
RLAPI void SetWindowState(unsigned int flags); // Set window configuration state using flags (only PLATFORM_DESKTOP)
|
||||||
RLAPI void ClearWindowState(unsigned int flags); // Clear window configuration state flags
|
RLAPI void ClearWindowState(unsigned int flags); // Clear window configuration state flags
|
||||||
RLAPI void ToggleFullscreen(void); // Toggle window state: fullscreen/windowed (only PLATFORM_DESKTOP)
|
RLAPI void ToggleFullscreen(void); // Toggle window state: fullscreen/windowed (only PLATFORM_DESKTOP)
|
||||||
|
RLAPI void ToggleBorderlessWindowed(void); // Toggle window state: borderless windowed (only PLATFORM_DESKTOP)
|
||||||
RLAPI void MaximizeWindow(void); // Set window state: maximized, if resizable (only PLATFORM_DESKTOP)
|
RLAPI void MaximizeWindow(void); // Set window state: maximized, if resizable (only PLATFORM_DESKTOP)
|
||||||
RLAPI void MinimizeWindow(void); // Set window state: minimized, if resizable (only PLATFORM_DESKTOP)
|
RLAPI void MinimizeWindow(void); // Set window state: minimized, if resizable (only PLATFORM_DESKTOP)
|
||||||
RLAPI void RestoreWindow(void); // Set window state: not minimized/maximized (only PLATFORM_DESKTOP)
|
RLAPI void RestoreWindow(void); // Set window state: not minimized/maximized (only PLATFORM_DESKTOP)
|
||||||
RLAPI void SetWindowIcon(Image image); // Set icon for window (single image, RGBA 32bit, only PLATFORM_DESKTOP)
|
RLAPI void SetWindowIcon(Image image); // Set icon for window (single image, RGBA 32bit, only PLATFORM_DESKTOP)
|
||||||
RLAPI void SetWindowIcons(Image *images, int count); // Set icon for window (multiple images, RGBA 32bit, only PLATFORM_DESKTOP)
|
RLAPI void SetWindowIcons(Image *images, int count); // Set icon for window (multiple images, RGBA 32bit, only PLATFORM_DESKTOP)
|
||||||
RLAPI void SetWindowTitle(const char *title); // Set title for window (only PLATFORM_DESKTOP)
|
RLAPI void SetWindowTitle(const char *title); // Set title for window (only PLATFORM_DESKTOP and PLATFORM_WEB)
|
||||||
RLAPI void SetWindowPosition(int x, int y); // Set window position on screen (only PLATFORM_DESKTOP)
|
RLAPI void SetWindowPosition(int x, int y); // Set window position on screen (only PLATFORM_DESKTOP)
|
||||||
RLAPI void SetWindowMonitor(int monitor); // Set monitor for the current window (fullscreen mode)
|
RLAPI void SetWindowMonitor(int monitor); // Set monitor for the current window
|
||||||
RLAPI void SetWindowMinSize(int width, int height); // Set window minimum dimensions (for FLAG_WINDOW_RESIZABLE)
|
RLAPI void SetWindowMinSize(int width, int height); // Set window minimum dimensions (for FLAG_WINDOW_RESIZABLE)
|
||||||
|
RLAPI void SetWindowMaxSize(int width, int height); // Set window maximum dimensions (for FLAG_WINDOW_RESIZABLE)
|
||||||
RLAPI void SetWindowSize(int width, int height); // Set window dimensions
|
RLAPI void SetWindowSize(int width, int height); // Set window dimensions
|
||||||
RLAPI void SetWindowOpacity(float opacity); // Set window opacity [0.0f..1.0f] (only PLATFORM_DESKTOP)
|
RLAPI void SetWindowOpacity(float opacity); // Set window opacity [0.0f..1.0f] (only PLATFORM_DESKTOP)
|
||||||
|
RLAPI void SetWindowFocused(void); // Set window focused (only PLATFORM_DESKTOP)
|
||||||
RLAPI void *GetWindowHandle(void); // Get native window handle
|
RLAPI void *GetWindowHandle(void); // Get native window handle
|
||||||
RLAPI int GetScreenWidth(void); // Get current screen width
|
RLAPI int GetScreenWidth(void); // Get current screen width
|
||||||
RLAPI int GetScreenHeight(void); // Get current screen height
|
RLAPI int GetScreenHeight(void); // Get current screen height
|
||||||
|
@ -964,20 +994,12 @@ RLAPI int GetMonitorPhysicalHeight(int monitor); // Get specifi
|
||||||
RLAPI int GetMonitorRefreshRate(int monitor); // Get specified monitor refresh rate
|
RLAPI int GetMonitorRefreshRate(int monitor); // Get specified monitor refresh rate
|
||||||
RLAPI Vector2 GetWindowPosition(void); // Get window position XY on monitor
|
RLAPI Vector2 GetWindowPosition(void); // Get window position XY on monitor
|
||||||
RLAPI Vector2 GetWindowScaleDPI(void); // Get window scale DPI factor
|
RLAPI Vector2 GetWindowScaleDPI(void); // Get window scale DPI factor
|
||||||
RLAPI const char *GetMonitorName(int monitor); // Get the human-readable, UTF-8 encoded name of the primary monitor
|
RLAPI const char *GetMonitorName(int monitor); // Get the human-readable, UTF-8 encoded name of the specified monitor
|
||||||
RLAPI void SetClipboardText(const char *text); // Set clipboard text content
|
RLAPI void SetClipboardText(const char *text); // Set clipboard text content
|
||||||
RLAPI const char *GetClipboardText(void); // Get clipboard text content
|
RLAPI const char *GetClipboardText(void); // Get clipboard text content
|
||||||
RLAPI void EnableEventWaiting(void); // Enable waiting for events on EndDrawing(), no automatic event polling
|
RLAPI void EnableEventWaiting(void); // Enable waiting for events on EndDrawing(), no automatic event polling
|
||||||
RLAPI void DisableEventWaiting(void); // Disable waiting for events on EndDrawing(), automatic events polling
|
RLAPI void DisableEventWaiting(void); // Disable waiting for events on EndDrawing(), automatic events polling
|
||||||
|
|
||||||
// Custom frame control functions
|
|
||||||
// NOTE: Those functions are intended for advance users that want full control over the frame processing
|
|
||||||
// By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timing + PollInputEvents()
|
|
||||||
// To avoid that behaviour and control frame processes manually, enable in config.h: SUPPORT_CUSTOM_FRAME_CONTROL
|
|
||||||
RLAPI void SwapScreenBuffer(void); // Swap back buffer with front buffer (screen drawing)
|
|
||||||
RLAPI void PollInputEvents(void); // Register all input events
|
|
||||||
RLAPI void WaitTime(double seconds); // Wait for some time (halt program execution)
|
|
||||||
|
|
||||||
// Cursor-related functions
|
// Cursor-related functions
|
||||||
RLAPI void ShowCursor(void); // Shows cursor
|
RLAPI void ShowCursor(void); // Shows cursor
|
||||||
RLAPI void HideCursor(void); // Hides cursor
|
RLAPI void HideCursor(void); // Hides cursor
|
||||||
|
@ -1033,24 +1055,37 @@ RLAPI Vector2 GetWorldToScreen2D(Vector2 position, Camera2D camera); // Get the
|
||||||
|
|
||||||
// Timing-related functions
|
// Timing-related functions
|
||||||
RLAPI void SetTargetFPS(int fps); // Set target FPS (maximum)
|
RLAPI void SetTargetFPS(int fps); // Set target FPS (maximum)
|
||||||
RLAPI int GetFPS(void); // Get current FPS
|
|
||||||
RLAPI float GetFrameTime(void); // Get time in seconds for last frame drawn (delta time)
|
RLAPI float GetFrameTime(void); // Get time in seconds for last frame drawn (delta time)
|
||||||
RLAPI double GetTime(void); // Get elapsed time in seconds since InitWindow()
|
RLAPI double GetTime(void); // Get elapsed time in seconds since InitWindow()
|
||||||
|
RLAPI int GetFPS(void); // Get current FPS
|
||||||
|
|
||||||
|
// Custom frame control functions
|
||||||
|
// NOTE: Those functions are intended for advance users that want full control over the frame processing
|
||||||
|
// By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timing + PollInputEvents()
|
||||||
|
// To avoid that behaviour and control frame processes manually, enable in config.h: SUPPORT_CUSTOM_FRAME_CONTROL
|
||||||
|
RLAPI void SwapScreenBuffer(void); // Swap back buffer with front buffer (screen drawing)
|
||||||
|
RLAPI void PollInputEvents(void); // Register all input events
|
||||||
|
RLAPI void WaitTime(double seconds); // Wait for some time (halt program execution)
|
||||||
|
|
||||||
|
// Random values generation functions
|
||||||
|
RLAPI void SetRandomSeed(unsigned int seed); // Set the seed for the random number generator
|
||||||
|
RLAPI int GetRandomValue(int min, int max); // Get a random value between min and max (both included)
|
||||||
|
RLAPI int *LoadRandomSequence(unsigned int count, int min, int max); // Load random values sequence, no values repeated
|
||||||
|
RLAPI void UnloadRandomSequence(int *sequence); // Unload random values sequence
|
||||||
|
|
||||||
// Misc. functions
|
// Misc. functions
|
||||||
RLAPI int GetRandomValue(int min, int max); // Get a random value between min and max (both included)
|
|
||||||
RLAPI void SetRandomSeed(unsigned int seed); // Set the seed for the random number generator
|
|
||||||
RLAPI void TakeScreenshot(const char *fileName); // Takes a screenshot of current screen (filename extension defines format)
|
RLAPI void TakeScreenshot(const char *fileName); // Takes a screenshot of current screen (filename extension defines format)
|
||||||
RLAPI void SetConfigFlags(unsigned int flags); // Setup init configuration flags (view FLAGS)
|
RLAPI void SetConfigFlags(unsigned int flags); // Setup init configuration flags (view FLAGS)
|
||||||
|
RLAPI void OpenURL(const char *url); // Open URL with default system browser (if available)
|
||||||
|
|
||||||
|
// NOTE: Following functions implemented in module [utils]
|
||||||
|
//------------------------------------------------------------------
|
||||||
RLAPI void TraceLog(int logLevel, const char *text, ...); // Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...)
|
RLAPI void TraceLog(int logLevel, const char *text, ...); // Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...)
|
||||||
RLAPI void SetTraceLogLevel(int logLevel); // Set the current threshold (minimum) log level
|
RLAPI void SetTraceLogLevel(int logLevel); // Set the current threshold (minimum) log level
|
||||||
RLAPI void *MemAlloc(unsigned int size); // Internal memory allocator
|
RLAPI void *MemAlloc(unsigned int size); // Internal memory allocator
|
||||||
RLAPI void *MemRealloc(void *ptr, unsigned int size); // Internal memory reallocator
|
RLAPI void *MemRealloc(void *ptr, unsigned int size); // Internal memory reallocator
|
||||||
RLAPI void MemFree(void *ptr); // Internal memory free
|
RLAPI void MemFree(void *ptr); // Internal memory free
|
||||||
|
|
||||||
RLAPI void OpenURL(const char *url); // Open URL with default system browser (if available)
|
|
||||||
|
|
||||||
// Set custom callbacks
|
// Set custom callbacks
|
||||||
// WARNING: Callbacks setup is intended for advance users
|
// WARNING: Callbacks setup is intended for advance users
|
||||||
RLAPI void SetTraceLogCallback(TraceLogCallback callback); // Set custom trace log
|
RLAPI void SetTraceLogCallback(TraceLogCallback callback); // Set custom trace log
|
||||||
|
@ -1060,13 +1095,16 @@ RLAPI void SetLoadFileTextCallback(LoadFileTextCallback callback); // Set custom
|
||||||
RLAPI void SetSaveFileTextCallback(SaveFileTextCallback callback); // Set custom file text data saver
|
RLAPI void SetSaveFileTextCallback(SaveFileTextCallback callback); // Set custom file text data saver
|
||||||
|
|
||||||
// Files management functions
|
// Files management functions
|
||||||
RLAPI unsigned char *LoadFileData(const char *fileName, unsigned int *bytesRead); // Load file data as byte array (read)
|
RLAPI unsigned char *LoadFileData(const char *fileName, int *dataSize); // Load file data as byte array (read)
|
||||||
RLAPI void UnloadFileData(unsigned char *data); // Unload file data allocated by LoadFileData()
|
RLAPI void UnloadFileData(unsigned char *data); // Unload file data allocated by LoadFileData()
|
||||||
RLAPI bool SaveFileData(const char *fileName, void *data, unsigned int bytesToWrite); // Save data to file from byte array (write), returns true on success
|
RLAPI bool SaveFileData(const char *fileName, void *data, int dataSize); // Save data to file from byte array (write), returns true on success
|
||||||
RLAPI bool ExportDataAsCode(const unsigned char *data, unsigned int size, const char *fileName); // Export data to code (.h), returns true on success
|
RLAPI bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileName); // Export data to code (.h), returns true on success
|
||||||
RLAPI char *LoadFileText(const char *fileName); // Load text data from file (read), returns a '\0' terminated string
|
RLAPI char *LoadFileText(const char *fileName); // Load text data from file (read), returns a '\0' terminated string
|
||||||
RLAPI void UnloadFileText(char *text); // Unload file text data allocated by LoadFileText()
|
RLAPI void UnloadFileText(char *text); // Unload file text data allocated by LoadFileText()
|
||||||
RLAPI bool SaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated, returns true on success
|
RLAPI bool SaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated, returns true on success
|
||||||
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
|
// File system functions
|
||||||
RLAPI bool FileExists(const char *fileName); // Check if file exists
|
RLAPI bool FileExists(const char *fileName); // Check if file exists
|
||||||
RLAPI bool DirectoryExists(const char *dirPath); // Check if a directory path exists
|
RLAPI bool DirectoryExists(const char *dirPath); // Check if a directory path exists
|
||||||
RLAPI bool IsFileExtension(const char *fileName, const char *ext); // Check file extension (including point: .png, .wav)
|
RLAPI bool IsFileExtension(const char *fileName, const char *ext); // Check file extension (including point: .png, .wav)
|
||||||
|
@ -1077,7 +1115,7 @@ RLAPI const char *GetFileNameWithoutExt(const char *filePath); // Get filenam
|
||||||
RLAPI const char *GetDirectoryPath(const char *filePath); // Get full path for a given fileName with path (uses static string)
|
RLAPI const char *GetDirectoryPath(const char *filePath); // Get full path for a given fileName with path (uses static string)
|
||||||
RLAPI const char *GetPrevDirectoryPath(const char *dirPath); // Get previous directory path for a given path (uses static string)
|
RLAPI const char *GetPrevDirectoryPath(const char *dirPath); // Get previous directory path for a given path (uses static string)
|
||||||
RLAPI const char *GetWorkingDirectory(void); // Get current working directory (uses static string)
|
RLAPI const char *GetWorkingDirectory(void); // Get current working directory (uses static string)
|
||||||
RLAPI const char *GetApplicationDirectory(void); // Get the directory if the running application (uses static string)
|
RLAPI const char *GetApplicationDirectory(void); // Get the directory of the running application (uses static string)
|
||||||
RLAPI bool ChangeDirectory(const char *dir); // Change working directory, return true on success
|
RLAPI bool ChangeDirectory(const char *dir); // Change working directory, return true on success
|
||||||
RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory
|
RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory
|
||||||
RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths
|
RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths
|
||||||
|
@ -1094,18 +1132,29 @@ RLAPI unsigned char *DecompressData(const unsigned char *compData, int compDataS
|
||||||
RLAPI char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize); // Encode data to Base64 string, memory must be MemFree()
|
RLAPI char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize); // Encode data to Base64 string, memory must be MemFree()
|
||||||
RLAPI unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize); // Decode Base64 string data, memory must be MemFree()
|
RLAPI unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize); // Decode Base64 string data, memory must be MemFree()
|
||||||
|
|
||||||
|
// Automation events functionality
|
||||||
|
RLAPI AutomationEventList LoadAutomationEventList(const char *fileName); // Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS
|
||||||
|
RLAPI void UnloadAutomationEventList(AutomationEventList *list); // Unload automation events list from file
|
||||||
|
RLAPI bool ExportAutomationEventList(AutomationEventList list, const char *fileName); // Export automation events list as text file
|
||||||
|
RLAPI void SetAutomationEventList(AutomationEventList *list); // Set automation event list to record to
|
||||||
|
RLAPI void SetAutomationEventBaseFrame(int frame); // Set automation event internal base frame to start recording
|
||||||
|
RLAPI void StartAutomationEventRecording(void); // Start recording automation events (AutomationEventList must be set)
|
||||||
|
RLAPI void StopAutomationEventRecording(void); // Stop recording automation events
|
||||||
|
RLAPI void PlayAutomationEvent(AutomationEvent event); // Play a recorded automation event
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Input Handling Functions (Module: core)
|
// Input Handling Functions (Module: core)
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Input-related functions: keyboard
|
// Input-related functions: keyboard
|
||||||
RLAPI bool IsKeyPressed(int key); // Check if a key has been pressed once
|
RLAPI bool IsKeyPressed(int key); // Check if a key has been pressed once
|
||||||
|
RLAPI bool IsKeyPressedRepeat(int key); // Check if a key has been pressed again (Only PLATFORM_DESKTOP)
|
||||||
RLAPI bool IsKeyDown(int key); // Check if a key is being pressed
|
RLAPI bool IsKeyDown(int key); // Check if a key is being pressed
|
||||||
RLAPI bool IsKeyReleased(int key); // Check if a key has been released once
|
RLAPI bool IsKeyReleased(int key); // Check if a key has been released once
|
||||||
RLAPI bool IsKeyUp(int key); // Check if a key is NOT being pressed
|
RLAPI bool IsKeyUp(int key); // Check if a key is NOT being pressed
|
||||||
RLAPI void SetExitKey(int key); // Set a custom key to exit program (default is ESC)
|
|
||||||
RLAPI int GetKeyPressed(void); // Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty
|
RLAPI int GetKeyPressed(void); // Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty
|
||||||
RLAPI int GetCharPressed(void); // Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty
|
RLAPI int GetCharPressed(void); // Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty
|
||||||
|
RLAPI void SetExitKey(int key); // Set a custom key to exit program (default is ESC)
|
||||||
|
|
||||||
// Input-related functions: gamepads
|
// Input-related functions: gamepads
|
||||||
RLAPI bool IsGamepadAvailable(int gamepad); // Check if a gamepad is available
|
RLAPI bool IsGamepadAvailable(int gamepad); // Check if a gamepad is available
|
||||||
|
@ -1146,7 +1195,7 @@ RLAPI int GetTouchPointCount(void); // Get number of t
|
||||||
// Gestures and Touch Handling Functions (Module: rgestures)
|
// Gestures and Touch Handling Functions (Module: rgestures)
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
RLAPI void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
|
RLAPI void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
|
||||||
RLAPI bool IsGestureDetected(int gesture); // Check if a gesture have been detected
|
RLAPI bool IsGestureDetected(unsigned int gesture); // Check if a gesture have been detected
|
||||||
RLAPI int GetGestureDetected(void); // Get latest detected gesture
|
RLAPI int GetGestureDetected(void); // Get latest detected gesture
|
||||||
RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds
|
RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds
|
||||||
RLAPI Vector2 GetGestureDragVector(void); // Get gesture drag vector
|
RLAPI Vector2 GetGestureDragVector(void); // Get gesture drag vector
|
||||||
|
@ -1177,6 +1226,8 @@ RLAPI void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color
|
||||||
RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line using cubic-bezier curves in-out
|
RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line using cubic-bezier curves in-out
|
||||||
RLAPI void DrawLineBezierQuad(Vector2 startPos, Vector2 endPos, Vector2 controlPos, float thick, Color color); // Draw line using quadratic bezier curves with a control point
|
RLAPI void DrawLineBezierQuad(Vector2 startPos, Vector2 endPos, Vector2 controlPos, float thick, Color color); // Draw line using quadratic bezier curves with a control point
|
||||||
RLAPI void DrawLineBezierCubic(Vector2 startPos, Vector2 endPos, Vector2 startControlPos, Vector2 endControlPos, float thick, Color color); // Draw line using cubic bezier curves with 2 control points
|
RLAPI void DrawLineBezierCubic(Vector2 startPos, Vector2 endPos, Vector2 startControlPos, Vector2 endControlPos, float thick, Color color); // Draw line using cubic bezier curves with 2 control points
|
||||||
|
RLAPI void DrawLineBSpline(Vector2 *points, int pointCount, float thick, Color color); // Draw a B-Spline line, minimum 4 points
|
||||||
|
RLAPI void DrawLineCatmullRom(Vector2 *points, int pointCount, float thick, Color color); // Draw a Catmull Rom spline line, minimum 4 points
|
||||||
RLAPI void DrawLineStrip(Vector2 *points, int pointCount, Color color); // Draw lines sequence
|
RLAPI void DrawLineStrip(Vector2 *points, int pointCount, Color color); // Draw lines sequence
|
||||||
RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle
|
RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle
|
||||||
RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle
|
RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle
|
||||||
|
@ -1184,6 +1235,7 @@ RLAPI void DrawCircleSectorLines(Vector2 center, float radius, float startAngle,
|
||||||
RLAPI void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2); // Draw a gradient-filled circle
|
RLAPI void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2); // Draw a gradient-filled circle
|
||||||
RLAPI void DrawCircleV(Vector2 center, float radius, Color color); // Draw a color-filled circle (Vector version)
|
RLAPI void DrawCircleV(Vector2 center, float radius, Color color); // Draw a color-filled circle (Vector version)
|
||||||
RLAPI void DrawCircleLines(int centerX, int centerY, float radius, Color color); // Draw circle outline
|
RLAPI void DrawCircleLines(int centerX, int centerY, float radius, Color color); // Draw circle outline
|
||||||
|
RLAPI void DrawCircleLinesV(Vector2 center, float radius, Color color); // Draw circle outline (Vector version)
|
||||||
RLAPI void DrawEllipse(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse
|
RLAPI void DrawEllipse(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse
|
||||||
RLAPI void DrawEllipseLines(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse outline
|
RLAPI void DrawEllipseLines(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse outline
|
||||||
RLAPI void DrawRing(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color); // Draw ring
|
RLAPI void DrawRing(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color); // Draw ring
|
||||||
|
@ -1227,6 +1279,7 @@ RLAPI Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2);
|
||||||
// NOTE: These functions do not require GPU access
|
// NOTE: These functions do not require GPU access
|
||||||
RLAPI Image LoadImage(const char *fileName); // Load image from file into CPU memory (RAM)
|
RLAPI Image LoadImage(const char *fileName); // Load image from file into CPU memory (RAM)
|
||||||
RLAPI Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize); // Load image from RAW file data
|
RLAPI Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize); // Load image from RAW file data
|
||||||
|
RLAPI Image LoadImageSvg(const char *fileNameOrString, int width, int height); // Load image from SVG file data or string with specified size
|
||||||
RLAPI Image LoadImageAnim(const char *fileName, int *frames); // Load image sequence from file (frames appended to image.data)
|
RLAPI Image LoadImageAnim(const char *fileName, int *frames); // Load image sequence from file (frames appended to image.data)
|
||||||
RLAPI Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load image from memory buffer, fileType refers to extension: i.e. '.png'
|
RLAPI Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load image from memory buffer, fileType refers to extension: i.e. '.png'
|
||||||
RLAPI Image LoadImageFromTexture(Texture2D texture); // Load image from GPU texture data
|
RLAPI Image LoadImageFromTexture(Texture2D texture); // Load image from GPU texture data
|
||||||
|
@ -1234,13 +1287,14 @@ RLAPI Image LoadImageFromScreen(void);
|
||||||
RLAPI bool IsImageReady(Image image); // Check if an image is ready
|
RLAPI bool IsImageReady(Image image); // Check if an image is ready
|
||||||
RLAPI void UnloadImage(Image image); // Unload image from CPU memory (RAM)
|
RLAPI void UnloadImage(Image image); // Unload image from CPU memory (RAM)
|
||||||
RLAPI bool ExportImage(Image image, const char *fileName); // Export image data to file, returns true on success
|
RLAPI bool ExportImage(Image image, const char *fileName); // Export image data to file, returns true on success
|
||||||
|
RLAPI unsigned char *ExportImageToMemory(Image image, const char *fileType, int *fileSize); // Export image to memory buffer
|
||||||
RLAPI bool ExportImageAsCode(Image image, const char *fileName); // Export image as code file defining an array of bytes, returns true on success
|
RLAPI bool ExportImageAsCode(Image image, const char *fileName); // Export image as code file defining an array of bytes, returns true on success
|
||||||
|
|
||||||
// Image generation functions
|
// Image generation functions
|
||||||
RLAPI Image GenImageColor(int width, int height, Color color); // Generate image: plain color
|
RLAPI Image GenImageColor(int width, int height, Color color); // Generate image: plain color
|
||||||
RLAPI Image GenImageGradientV(int width, int height, Color top, Color bottom); // Generate image: vertical gradient
|
RLAPI Image GenImageGradientLinear(int width, int height, int direction, Color start, Color end); // Generate image: linear gradient, direction in degrees [0..360], 0=Vertical gradient
|
||||||
RLAPI Image GenImageGradientH(int width, int height, Color left, Color right); // Generate image: horizontal gradient
|
|
||||||
RLAPI Image GenImageGradientRadial(int width, int height, float density, Color inner, Color outer); // Generate image: radial gradient
|
RLAPI Image GenImageGradientRadial(int width, int height, float density, Color inner, Color outer); // Generate image: radial gradient
|
||||||
|
RLAPI Image GenImageGradientSquare(int width, int height, float density, Color inner, Color outer); // Generate image: square gradient
|
||||||
RLAPI Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2); // Generate image: checked
|
RLAPI Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2); // Generate image: checked
|
||||||
RLAPI Image GenImageWhiteNoise(int width, int height, float factor); // Generate image: white noise
|
RLAPI Image GenImageWhiteNoise(int width, int height, float factor); // Generate image: white noise
|
||||||
RLAPI Image GenImagePerlinNoise(int width, int height, int offsetX, int offsetY, float scale); // Generate image: perlin noise
|
RLAPI Image GenImagePerlinNoise(int width, int height, int offsetX, int offsetY, float scale); // Generate image: perlin noise
|
||||||
|
@ -1267,6 +1321,7 @@ RLAPI void ImageMipmaps(Image *image);
|
||||||
RLAPI void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp); // Dither image data to 16bpp or lower (Floyd-Steinberg dithering)
|
RLAPI void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp); // Dither image data to 16bpp or lower (Floyd-Steinberg dithering)
|
||||||
RLAPI void ImageFlipVertical(Image *image); // Flip image vertically
|
RLAPI void ImageFlipVertical(Image *image); // Flip image vertically
|
||||||
RLAPI void ImageFlipHorizontal(Image *image); // Flip image horizontally
|
RLAPI void ImageFlipHorizontal(Image *image); // Flip image horizontally
|
||||||
|
RLAPI void ImageRotate(Image *image, int degrees); // Rotate image by input angle in degrees (-359 to 359)
|
||||||
RLAPI void ImageRotateCW(Image *image); // Rotate image clockwise 90deg
|
RLAPI void ImageRotateCW(Image *image); // Rotate image clockwise 90deg
|
||||||
RLAPI void ImageRotateCCW(Image *image); // Rotate image counter-clockwise 90deg
|
RLAPI void ImageRotateCCW(Image *image); // Rotate image counter-clockwise 90deg
|
||||||
RLAPI void ImageColorTint(Image *image, Color color); // Modify image color: tint
|
RLAPI void ImageColorTint(Image *image, Color color); // Modify image color: tint
|
||||||
|
@ -1351,13 +1406,13 @@ RLAPI int GetPixelDataSize(int width, int height, int format); // G
|
||||||
// Font loading/unloading functions
|
// Font loading/unloading functions
|
||||||
RLAPI Font GetFontDefault(void); // Get the default Font
|
RLAPI Font GetFontDefault(void); // Get the default Font
|
||||||
RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM)
|
RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM)
|
||||||
RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int glyphCount); // Load font from file with extended parameters, use NULL for fontChars and 0 for glyphCount to load the default character set
|
RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set
|
||||||
RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style)
|
RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style)
|
||||||
RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int glyphCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf'
|
RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf'
|
||||||
RLAPI bool IsFontReady(Font font); // Check if a font is ready
|
RLAPI bool IsFontReady(Font font); // Check if a font is ready
|
||||||
RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int glyphCount, int type); // Load font data for further use
|
RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount, int type); // Load font data for further use
|
||||||
RLAPI Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **recs, int glyphCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info
|
RLAPI Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyphCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info
|
||||||
RLAPI void UnloadFontData(GlyphInfo *chars, int glyphCount); // Unload font chars info data (RAM)
|
RLAPI void UnloadFontData(GlyphInfo *glyphs, int glyphCount); // Unload font chars info data (RAM)
|
||||||
RLAPI void UnloadFont(Font font); // Unload font from GPU memory (VRAM)
|
RLAPI void UnloadFont(Font font); // Unload font from GPU memory (VRAM)
|
||||||
RLAPI bool ExportFontAsCode(Font font, const char *fileName); // Export font as code file, returns true on success
|
RLAPI bool ExportFontAsCode(Font font, const char *fileName); // Export font as code file, returns true on success
|
||||||
|
|
||||||
|
@ -1367,9 +1422,10 @@ RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color co
|
||||||
RLAPI void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters
|
RLAPI void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters
|
||||||
RLAPI void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint); // Draw text using Font and pro parameters (rotation)
|
RLAPI void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint); // Draw text using Font and pro parameters (rotation)
|
||||||
RLAPI void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSize, Color tint); // Draw one character (codepoint)
|
RLAPI void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSize, Color tint); // Draw one character (codepoint)
|
||||||
RLAPI void DrawTextCodepoints(Font font, const int *codepoints, int count, Vector2 position, float fontSize, float spacing, Color tint); // Draw multiple character (codepoint)
|
RLAPI void DrawTextCodepoints(Font font, const int *codepoints, int codepointCount, Vector2 position, float fontSize, float spacing, Color tint); // Draw multiple character (codepoint)
|
||||||
|
|
||||||
// Text font info functions
|
// Text font info functions
|
||||||
|
RLAPI void SetTextLineSpacing(int spacing); // Set vertical line spacing when drawing with line-breaks
|
||||||
RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font
|
RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font
|
||||||
RLAPI Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // Measure string size for Font
|
RLAPI Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // Measure string size for Font
|
||||||
RLAPI int GetGlyphIndex(Font font, int codepoint); // Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found
|
RLAPI int GetGlyphIndex(Font font, int codepoint); // Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found
|
||||||
|
@ -1485,10 +1541,10 @@ RLAPI void SetMaterialTexture(Material *material, int mapType, Texture2D texture
|
||||||
RLAPI void SetModelMeshMaterial(Model *model, int meshId, int materialId); // Set material for a mesh
|
RLAPI void SetModelMeshMaterial(Model *model, int meshId, int materialId); // Set material for a mesh
|
||||||
|
|
||||||
// Model animations loading/unloading functions
|
// Model animations loading/unloading functions
|
||||||
RLAPI ModelAnimation *LoadModelAnimations(const char *fileName, unsigned int *animCount); // Load model animations from file
|
RLAPI ModelAnimation *LoadModelAnimations(const char *fileName, int *animCount); // Load model animations from file
|
||||||
RLAPI void UpdateModelAnimation(Model model, ModelAnimation anim, int frame); // Update model animation pose
|
RLAPI void UpdateModelAnimation(Model model, ModelAnimation anim, int frame); // Update model animation pose
|
||||||
RLAPI void UnloadModelAnimation(ModelAnimation anim); // Unload animation data
|
RLAPI void UnloadModelAnimation(ModelAnimation anim); // Unload animation data
|
||||||
RLAPI void UnloadModelAnimations(ModelAnimation *animations, unsigned int count); // Unload animation array data
|
RLAPI void UnloadModelAnimations(ModelAnimation *animations, int animCount); // Unload animation array data
|
||||||
RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match
|
RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match
|
||||||
|
|
||||||
// Collision detection functions
|
// Collision detection functions
|
||||||
|
@ -1511,6 +1567,7 @@ RLAPI void InitAudioDevice(void); // Initial
|
||||||
RLAPI void CloseAudioDevice(void); // Close the audio device and context
|
RLAPI void CloseAudioDevice(void); // Close the audio device and context
|
||||||
RLAPI bool IsAudioDeviceReady(void); // Check if audio device has been initialized successfully
|
RLAPI bool IsAudioDeviceReady(void); // Check if audio device has been initialized successfully
|
||||||
RLAPI void SetMasterVolume(float volume); // Set master volume (listener)
|
RLAPI void SetMasterVolume(float volume); // Set master volume (listener)
|
||||||
|
RLAPI float GetMasterVolume(void); // Get master volume (listener)
|
||||||
|
|
||||||
// Wave/Sound loading/unloading functions
|
// Wave/Sound loading/unloading functions
|
||||||
RLAPI Wave LoadWave(const char *fileName); // Load wave data from file
|
RLAPI Wave LoadWave(const char *fileName); // Load wave data from file
|
||||||
|
@ -1518,10 +1575,12 @@ RLAPI Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileDat
|
||||||
RLAPI bool IsWaveReady(Wave wave); // Checks if wave data is ready
|
RLAPI bool IsWaveReady(Wave wave); // Checks if wave data is ready
|
||||||
RLAPI Sound LoadSound(const char *fileName); // Load sound from file
|
RLAPI Sound LoadSound(const char *fileName); // Load sound from file
|
||||||
RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound from wave data
|
RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound from wave data
|
||||||
|
RLAPI Sound LoadSoundAlias(Sound source); // Create a new sound that shares the same sample data as the source sound, does not own the sound data
|
||||||
RLAPI bool IsSoundReady(Sound sound); // Checks if a sound is ready
|
RLAPI bool IsSoundReady(Sound sound); // Checks if a sound is ready
|
||||||
RLAPI void UpdateSound(Sound sound, const void *data, int sampleCount); // Update sound buffer with new data
|
RLAPI void UpdateSound(Sound sound, const void *data, int sampleCount); // Update sound buffer with new data
|
||||||
RLAPI void UnloadWave(Wave wave); // Unload wave data
|
RLAPI void UnloadWave(Wave wave); // Unload wave data
|
||||||
RLAPI void UnloadSound(Sound sound); // Unload sound
|
RLAPI void UnloadSound(Sound sound); // Unload sound
|
||||||
|
RLAPI void UnloadSoundAlias(Sound alias); // Unload a sound alias (does not deallocate sample data)
|
||||||
RLAPI bool ExportWave(Wave wave, const char *fileName); // Export wave data to file, returns true on success
|
RLAPI bool ExportWave(Wave wave, const char *fileName); // Export wave data to file, returns true on success
|
||||||
RLAPI bool ExportWaveAsCode(Wave wave, const char *fileName); // Export wave sample data to code (.h), returns true on success
|
RLAPI bool ExportWaveAsCode(Wave wave, const char *fileName); // Export wave sample data to code (.h), returns true on success
|
||||||
|
|
||||||
|
@ -1575,10 +1634,10 @@ RLAPI void SetAudioStreamPan(AudioStream stream, float pan); // Set pan
|
||||||
RLAPI void SetAudioStreamBufferSizeDefault(int size); // Default size for new audio streams
|
RLAPI void SetAudioStreamBufferSizeDefault(int size); // Default size for new audio streams
|
||||||
RLAPI void SetAudioStreamCallback(AudioStream stream, AudioCallback callback); // Audio thread callback to request new data
|
RLAPI void SetAudioStreamCallback(AudioStream stream, AudioCallback callback); // Audio thread callback to request new data
|
||||||
|
|
||||||
RLAPI void AttachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Attach audio stream processor to stream
|
RLAPI void AttachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Attach audio stream processor to stream, receives the samples as <float>s
|
||||||
RLAPI void DetachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Detach audio stream processor from stream
|
RLAPI void DetachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Detach audio stream processor from stream
|
||||||
|
|
||||||
RLAPI void AttachAudioMixedProcessor(AudioCallback processor); // Attach audio stream processor to the entire audio pipeline
|
RLAPI void AttachAudioMixedProcessor(AudioCallback processor); // Attach audio stream processor to the entire audio pipeline, receives the samples as <float>s
|
||||||
RLAPI void DetachAudioMixedProcessor(AudioCallback processor); // Detach audio stream processor from the entire audio pipeline
|
RLAPI void DetachAudioMixedProcessor(AudioCallback processor); // Detach audio stream processor from the entire audio pipeline
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
|
|
178
raylib/raymath.h
178
raylib/raymath.h
|
@ -2,8 +2,22 @@
|
||||||
*
|
*
|
||||||
* raymath v1.5 - Math functions to work with Vector2, Vector3, Matrix and Quaternions
|
* raymath v1.5 - Math functions to work with Vector2, Vector3, Matrix and Quaternions
|
||||||
*
|
*
|
||||||
* CONFIGURATION:
|
* CONVENTIONS:
|
||||||
|
* - Matrix structure is defined as row-major (memory layout) but parameters naming AND all
|
||||||
|
* math operations performed by the library consider the structure as it was column-major
|
||||||
|
* It is like transposed versions of the matrices are used for all the maths
|
||||||
|
* It benefits some functions making them cache-friendly and also avoids matrix
|
||||||
|
* transpositions sometimes required by OpenGL
|
||||||
|
* Example: In memory order, row0 is [m0 m4 m8 m12] but in semantic math row0 is [m0 m1 m2 m3]
|
||||||
|
* - Functions are always self-contained, no function use another raymath function inside,
|
||||||
|
* required code is directly re-implemented inside
|
||||||
|
* - Functions input parameters are always received by value (2 unavoidable exceptions)
|
||||||
|
* - Functions use always a "result" variable for return
|
||||||
|
* - Functions are always defined inline
|
||||||
|
* - Angles are always in radians (DEG2RAD/RAD2DEG macros provided for convenience)
|
||||||
|
* - No compound literals used to make sure libray is compatible with C++
|
||||||
*
|
*
|
||||||
|
* CONFIGURATION:
|
||||||
* #define RAYMATH_IMPLEMENTATION
|
* #define RAYMATH_IMPLEMENTATION
|
||||||
* Generates the implementation of the library into the included file.
|
* Generates the implementation of the library into the included file.
|
||||||
* If not defined, the library is in header only mode and can be included in other headers
|
* If not defined, the library is in header only mode and can be included in other headers
|
||||||
|
@ -13,15 +27,6 @@
|
||||||
* Define static inline functions code, so #include header suffices for use.
|
* Define static inline functions code, so #include header suffices for use.
|
||||||
* This may use up lots of memory.
|
* This may use up lots of memory.
|
||||||
*
|
*
|
||||||
* CONVENTIONS:
|
|
||||||
*
|
|
||||||
* - Functions are always self-contained, no function use another raymath function inside,
|
|
||||||
* required code is directly re-implemented inside
|
|
||||||
* - Functions input parameters are always received by value (2 unavoidable exceptions)
|
|
||||||
* - Functions use always a "result" variable for return
|
|
||||||
* - Functions are always defined inline
|
|
||||||
* - Angles are always in radians (DEG2RAD/RAD2DEG macros provided for convenience)
|
|
||||||
*
|
|
||||||
*
|
*
|
||||||
* LICENSE: zlib/libpng
|
* LICENSE: zlib/libpng
|
||||||
*
|
*
|
||||||
|
@ -209,6 +214,10 @@ RMAPI float Wrap(float value, float min, float max)
|
||||||
// Check whether two given floats are almost equal
|
// Check whether two given floats are almost equal
|
||||||
RMAPI int FloatEquals(float x, float y)
|
RMAPI int FloatEquals(float x, float y)
|
||||||
{
|
{
|
||||||
|
#if !defined(EPSILON)
|
||||||
|
#define EPSILON 0.000001f
|
||||||
|
#endif
|
||||||
|
|
||||||
int result = (fabsf(x - y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(x), fabsf(y))));
|
int result = (fabsf(x - y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(x), fabsf(y))));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -310,7 +319,12 @@ RMAPI float Vector2DistanceSqr(Vector2 v1, Vector2 v2)
|
||||||
// NOTE: Angle is calculated from origin point (0, 0)
|
// NOTE: Angle is calculated from origin point (0, 0)
|
||||||
RMAPI float Vector2Angle(Vector2 v1, Vector2 v2)
|
RMAPI float Vector2Angle(Vector2 v1, Vector2 v2)
|
||||||
{
|
{
|
||||||
float result = atan2f(v2.y - v1.y, v2.x - v1.x);
|
float result = 0.0f;
|
||||||
|
|
||||||
|
float dot = v1.x*v2.x + v1.y*v2.y;
|
||||||
|
float det = v1.x*v2.y - v1.y*v2.x;
|
||||||
|
|
||||||
|
result = atan2f(det, dot);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -322,17 +336,8 @@ RMAPI float Vector2LineAngle(Vector2 start, Vector2 end)
|
||||||
{
|
{
|
||||||
float result = 0.0f;
|
float result = 0.0f;
|
||||||
|
|
||||||
float dot = start.x*end.x + start.y*end.y; // Dot product
|
// TODO(10/9/2023): Currently angles move clockwise, determine if this is wanted behavior
|
||||||
|
result = -atan2f(end.y - start.y, end.x - start.x);
|
||||||
float dotClamp = (dot < -1.0f)? -1.0f : dot; // Clamp
|
|
||||||
if (dotClamp > 1.0f) dotClamp = 1.0f;
|
|
||||||
|
|
||||||
result = acosf(dotClamp);
|
|
||||||
|
|
||||||
// Alternative implementation, more costly
|
|
||||||
//float v1Length = sqrtf((start.x*start.x) + (start.y*start.y));
|
|
||||||
//float v2Length = sqrtf((end.x*end.x) + (end.y*end.y));
|
|
||||||
//float result = -acosf((start.x*end.x + start.y*end.y)/(v1Length*v2Length));
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -507,6 +512,10 @@ RMAPI Vector2 Vector2ClampValue(Vector2 v, float min, float max)
|
||||||
// Check whether two given vectors are almost equal
|
// Check whether two given vectors are almost equal
|
||||||
RMAPI int Vector2Equals(Vector2 p, Vector2 q)
|
RMAPI int Vector2Equals(Vector2 p, Vector2 q)
|
||||||
{
|
{
|
||||||
|
#if !defined(EPSILON)
|
||||||
|
#define EPSILON 0.000001f
|
||||||
|
#endif
|
||||||
|
|
||||||
int result = ((fabsf(p.x - q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) &&
|
int result = ((fabsf(p.x - q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) &&
|
||||||
((fabsf(p.y - q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y)))));
|
((fabsf(p.y - q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y)))));
|
||||||
|
|
||||||
|
@ -703,12 +712,48 @@ RMAPI Vector3 Vector3Normalize(Vector3 v)
|
||||||
Vector3 result = v;
|
Vector3 result = v;
|
||||||
|
|
||||||
float length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z);
|
float length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z);
|
||||||
if (length == 0.0f) length = 1.0f;
|
if (length != 0.0f)
|
||||||
|
{
|
||||||
float ilength = 1.0f/length;
|
float ilength = 1.0f/length;
|
||||||
|
|
||||||
result.x *= ilength;
|
result.x *= ilength;
|
||||||
result.y *= ilength;
|
result.y *= ilength;
|
||||||
result.z *= ilength;
|
result.z *= ilength;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Calculate the projection of the vector v1 on to v2
|
||||||
|
RMAPI Vector3 Vector3Project(Vector3 v1, Vector3 v2)
|
||||||
|
{
|
||||||
|
Vector3 result = { 0 };
|
||||||
|
|
||||||
|
float v1dv2 = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z);
|
||||||
|
float v2dv2 = (v2.x*v2.x + v2.y*v2.y + v2.z*v2.z);
|
||||||
|
|
||||||
|
float mag = v1dv2/v2dv2;
|
||||||
|
|
||||||
|
result.x = v2.x*mag;
|
||||||
|
result.y = v2.y*mag;
|
||||||
|
result.z = v2.z*mag;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Calculate the rejection of the vector v1 on to v2
|
||||||
|
RMAPI Vector3 Vector3Reject(Vector3 v1, Vector3 v2)
|
||||||
|
{
|
||||||
|
Vector3 result = { 0 };
|
||||||
|
|
||||||
|
float v1dv2 = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z);
|
||||||
|
float v2dv2 = (v2.x*v2.x + v2.y*v2.y + v2.z*v2.z);
|
||||||
|
|
||||||
|
float mag = v1dv2/v2dv2;
|
||||||
|
|
||||||
|
result.x = v1.x - (v2.x*mag);
|
||||||
|
result.y = v1.y - (v2.y*mag);
|
||||||
|
result.z = v1.z - (v2.z*mag);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -785,7 +830,7 @@ RMAPI Vector3 Vector3RotateByAxisAngle(Vector3 v, Vector3 axis, float angle)
|
||||||
Vector3 result = v;
|
Vector3 result = v;
|
||||||
|
|
||||||
// Vector3Normalize(axis);
|
// Vector3Normalize(axis);
|
||||||
float length = sqrtf(axis.x * axis.x + axis.y * axis.y + axis.z * axis.z);
|
float length = sqrtf(axis.x*axis.x + axis.y*axis.y + axis.z*axis.z);
|
||||||
if (length == 0.0f) length = 1.0f;
|
if (length == 0.0f) length = 1.0f;
|
||||||
float ilength = 1.0f / length;
|
float ilength = 1.0f / length;
|
||||||
axis.x *= ilength;
|
axis.x *= ilength;
|
||||||
|
@ -794,19 +839,19 @@ RMAPI Vector3 Vector3RotateByAxisAngle(Vector3 v, Vector3 axis, float angle)
|
||||||
|
|
||||||
angle /= 2.0f;
|
angle /= 2.0f;
|
||||||
float a = sinf(angle);
|
float a = sinf(angle);
|
||||||
float b = axis.x * a;
|
float b = axis.x*a;
|
||||||
float c = axis.y * a;
|
float c = axis.y*a;
|
||||||
float d = axis.z * a;
|
float d = axis.z*a;
|
||||||
a = cosf(angle);
|
a = cosf(angle);
|
||||||
Vector3 w = { b, c, d };
|
Vector3 w = { b, c, d };
|
||||||
|
|
||||||
// Vector3CrossProduct(w, v)
|
// Vector3CrossProduct(w, v)
|
||||||
Vector3 wv = { w.y * v.z - w.z * v.y, w.z * v.x - w.x * v.z, w.x * v.y - w.y * v.x };
|
Vector3 wv = { w.y*v.z - w.z*v.y, w.z*v.x - w.x*v.z, w.x*v.y - w.y*v.x };
|
||||||
|
|
||||||
// Vector3CrossProduct(w, wv)
|
// Vector3CrossProduct(w, wv)
|
||||||
Vector3 wwv = { w.y * wv.z - w.z * wv.y, w.z * wv.x - w.x * wv.z, w.x * wv.y - w.y * wv.x };
|
Vector3 wwv = { w.y*wv.z - w.z*wv.y, w.z*wv.x - w.x*wv.z, w.x*wv.y - w.y*wv.x };
|
||||||
|
|
||||||
// Vector3Scale(wv, 2 * a)
|
// Vector3Scale(wv, 2*a)
|
||||||
a *= 2;
|
a *= 2;
|
||||||
wv.x *= a;
|
wv.x *= a;
|
||||||
wv.y *= a;
|
wv.y *= a;
|
||||||
|
@ -1055,6 +1100,10 @@ RMAPI Vector3 Vector3ClampValue(Vector3 v, float min, float max)
|
||||||
// Check whether two given vectors are almost equal
|
// Check whether two given vectors are almost equal
|
||||||
RMAPI int Vector3Equals(Vector3 p, Vector3 q)
|
RMAPI int Vector3Equals(Vector3 p, Vector3 q)
|
||||||
{
|
{
|
||||||
|
#if !defined(EPSILON)
|
||||||
|
#define EPSILON 0.000001f
|
||||||
|
#endif
|
||||||
|
|
||||||
int result = ((fabsf(p.x - q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) &&
|
int result = ((fabsf(p.x - q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) &&
|
||||||
((fabsf(p.y - q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))) &&
|
((fabsf(p.y - q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))) &&
|
||||||
((fabsf(p.z - q.z)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z)))));
|
((fabsf(p.z - q.z)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z)))));
|
||||||
|
@ -1062,12 +1111,11 @@ RMAPI int Vector3Equals(Vector3 p, Vector3 q)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the direction of a refracted ray where v specifies the
|
// Compute the direction of a refracted ray
|
||||||
// normalized direction of the incoming ray, n specifies the
|
// v: normalized direction of the incoming ray
|
||||||
// normalized normal vector of the interface of two optical media,
|
// n: normalized normal vector of the interface of two optical media
|
||||||
// and r specifies the ratio of the refractive index of the medium
|
// r: ratio of the refractive index of the medium from where the ray comes
|
||||||
// from where the ray comes to the refractive index of the medium
|
// to the refractive index of the medium on the other side of the surface
|
||||||
// on the other side of the surface
|
|
||||||
RMAPI Vector3 Vector3Refract(Vector3 v, Vector3 n, float r)
|
RMAPI Vector3 Vector3Refract(Vector3 v, Vector3 n, float r)
|
||||||
{
|
{
|
||||||
Vector3 result = { 0 };
|
Vector3 result = { 0 };
|
||||||
|
@ -1509,11 +1557,11 @@ RMAPI Matrix MatrixFrustum(double left, double right, double bottom, double top,
|
||||||
|
|
||||||
// Get perspective projection matrix
|
// Get perspective projection matrix
|
||||||
// NOTE: Fovy angle must be provided in radians
|
// NOTE: Fovy angle must be provided in radians
|
||||||
RMAPI Matrix MatrixPerspective(double fovy, double aspect, double near, double far)
|
RMAPI Matrix MatrixPerspective(double fovY, double aspect, double nearPlane, double farPlane)
|
||||||
{
|
{
|
||||||
Matrix result = { 0 };
|
Matrix result = { 0 };
|
||||||
|
|
||||||
double top = near*tan(fovy*0.5);
|
double top = nearPlane*tan(fovY*0.5);
|
||||||
double bottom = -top;
|
double bottom = -top;
|
||||||
double right = top*aspect;
|
double right = top*aspect;
|
||||||
double left = -right;
|
double left = -right;
|
||||||
|
@ -1521,27 +1569,27 @@ RMAPI Matrix MatrixPerspective(double fovy, double aspect, double near, double f
|
||||||
// MatrixFrustum(-right, right, -top, top, near, far);
|
// MatrixFrustum(-right, right, -top, top, near, far);
|
||||||
float rl = (float)(right - left);
|
float rl = (float)(right - left);
|
||||||
float tb = (float)(top - bottom);
|
float tb = (float)(top - bottom);
|
||||||
float fn = (float)(far - near);
|
float fn = (float)(farPlane - nearPlane);
|
||||||
|
|
||||||
result.m0 = ((float)near*2.0f)/rl;
|
result.m0 = ((float)nearPlane*2.0f)/rl;
|
||||||
result.m5 = ((float)near*2.0f)/tb;
|
result.m5 = ((float)nearPlane*2.0f)/tb;
|
||||||
result.m8 = ((float)right + (float)left)/rl;
|
result.m8 = ((float)right + (float)left)/rl;
|
||||||
result.m9 = ((float)top + (float)bottom)/tb;
|
result.m9 = ((float)top + (float)bottom)/tb;
|
||||||
result.m10 = -((float)far + (float)near)/fn;
|
result.m10 = -((float)farPlane + (float)nearPlane)/fn;
|
||||||
result.m11 = -1.0f;
|
result.m11 = -1.0f;
|
||||||
result.m14 = -((float)far*(float)near*2.0f)/fn;
|
result.m14 = -((float)farPlane*(float)nearPlane*2.0f)/fn;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get orthographic projection matrix
|
// Get orthographic projection matrix
|
||||||
RMAPI Matrix MatrixOrtho(double left, double right, double bottom, double top, double near, double far)
|
RMAPI Matrix MatrixOrtho(double left, double right, double bottom, double top, double nearPlane, double farPlane)
|
||||||
{
|
{
|
||||||
Matrix result = { 0 };
|
Matrix result = { 0 };
|
||||||
|
|
||||||
float rl = (float)(right - left);
|
float rl = (float)(right - left);
|
||||||
float tb = (float)(top - bottom);
|
float tb = (float)(top - bottom);
|
||||||
float fn = (float)(far - near);
|
float fn = (float)(farPlane - nearPlane);
|
||||||
|
|
||||||
result.m0 = 2.0f/rl;
|
result.m0 = 2.0f/rl;
|
||||||
result.m1 = 0.0f;
|
result.m1 = 0.0f;
|
||||||
|
@ -1557,7 +1605,7 @@ RMAPI Matrix MatrixOrtho(double left, double right, double bottom, double top, d
|
||||||
result.m11 = 0.0f;
|
result.m11 = 0.0f;
|
||||||
result.m12 = -((float)left + (float)right)/rl;
|
result.m12 = -((float)left + (float)right)/rl;
|
||||||
result.m13 = -((float)top + (float)bottom)/tb;
|
result.m13 = -((float)top + (float)bottom)/tb;
|
||||||
result.m14 = -((float)far + (float)near)/fn;
|
result.m14 = -((float)farPlane + (float)nearPlane)/fn;
|
||||||
result.m15 = 1.0f;
|
result.m15 = 1.0f;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -1812,6 +1860,10 @@ RMAPI Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount)
|
||||||
{
|
{
|
||||||
Quaternion result = { 0 };
|
Quaternion result = { 0 };
|
||||||
|
|
||||||
|
#if !defined(EPSILON)
|
||||||
|
#define EPSILON 0.000001f
|
||||||
|
#endif
|
||||||
|
|
||||||
float cosHalfTheta = q1.x*q2.x + q1.y*q2.y + q1.z*q2.z + q1.w*q2.w;
|
float cosHalfTheta = q1.x*q2.x + q1.y*q2.y + q1.z*q2.z + q1.w*q2.w;
|
||||||
|
|
||||||
if (cosHalfTheta < 0)
|
if (cosHalfTheta < 0)
|
||||||
|
@ -1827,7 +1879,7 @@ RMAPI Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount)
|
||||||
float halfTheta = acosf(cosHalfTheta);
|
float halfTheta = acosf(cosHalfTheta);
|
||||||
float sinHalfTheta = sqrtf(1.0f - cosHalfTheta*cosHalfTheta);
|
float sinHalfTheta = sqrtf(1.0f - cosHalfTheta*cosHalfTheta);
|
||||||
|
|
||||||
if (fabsf(sinHalfTheta) < 0.001f)
|
if (fabsf(sinHalfTheta) < EPSILON)
|
||||||
{
|
{
|
||||||
result.x = (q1.x*0.5f + q2.x*0.5f);
|
result.x = (q1.x*0.5f + q2.x*0.5f);
|
||||||
result.y = (q1.y*0.5f + q2.y*0.5f);
|
result.y = (q1.y*0.5f + q2.y*0.5f);
|
||||||
|
@ -1907,34 +1959,34 @@ RMAPI Quaternion QuaternionFromMatrix(Matrix mat)
|
||||||
biggestIndex = 3;
|
biggestIndex = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
float biggestVal = sqrtf(fourBiggestSquaredMinus1 + 1.0f) * 0.5f;
|
float biggestVal = sqrtf(fourBiggestSquaredMinus1 + 1.0f)*0.5f;
|
||||||
float mult = 0.25f / biggestVal;
|
float mult = 0.25f / biggestVal;
|
||||||
|
|
||||||
switch (biggestIndex)
|
switch (biggestIndex)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
result.w = biggestVal;
|
result.w = biggestVal;
|
||||||
result.x = (mat.m6 - mat.m9) * mult;
|
result.x = (mat.m6 - mat.m9)*mult;
|
||||||
result.y = (mat.m8 - mat.m2) * mult;
|
result.y = (mat.m8 - mat.m2)*mult;
|
||||||
result.z = (mat.m1 - mat.m4) * mult;
|
result.z = (mat.m1 - mat.m4)*mult;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
result.x = biggestVal;
|
result.x = biggestVal;
|
||||||
result.w = (mat.m6 - mat.m9) * mult;
|
result.w = (mat.m6 - mat.m9)*mult;
|
||||||
result.y = (mat.m1 + mat.m4) * mult;
|
result.y = (mat.m1 + mat.m4)*mult;
|
||||||
result.z = (mat.m8 + mat.m2) * mult;
|
result.z = (mat.m8 + mat.m2)*mult;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
result.y = biggestVal;
|
result.y = biggestVal;
|
||||||
result.w = (mat.m8 - mat.m2) * mult;
|
result.w = (mat.m8 - mat.m2)*mult;
|
||||||
result.x = (mat.m1 + mat.m4) * mult;
|
result.x = (mat.m1 + mat.m4)*mult;
|
||||||
result.z = (mat.m6 + mat.m9) * mult;
|
result.z = (mat.m6 + mat.m9)*mult;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
result.z = biggestVal;
|
result.z = biggestVal;
|
||||||
result.w = (mat.m1 - mat.m4) * mult;
|
result.w = (mat.m1 - mat.m4)*mult;
|
||||||
result.x = (mat.m8 + mat.m2) * mult;
|
result.x = (mat.m8 + mat.m2)*mult;
|
||||||
result.y = (mat.m6 + mat.m9) * mult;
|
result.y = (mat.m6 + mat.m9)*mult;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2040,7 +2092,7 @@ RMAPI void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle
|
||||||
float resAngle = 2.0f*acosf(q.w);
|
float resAngle = 2.0f*acosf(q.w);
|
||||||
float den = sqrtf(1.0f - q.w*q.w);
|
float den = sqrtf(1.0f - q.w*q.w);
|
||||||
|
|
||||||
if (den > 0.0001f)
|
if (den > EPSILON)
|
||||||
{
|
{
|
||||||
resAxis.x = q.x/den;
|
resAxis.x = q.x/den;
|
||||||
resAxis.y = q.y/den;
|
resAxis.y = q.y/den;
|
||||||
|
@ -2119,6 +2171,10 @@ RMAPI Quaternion QuaternionTransform(Quaternion q, Matrix mat)
|
||||||
// Check whether two given quaternions are almost equal
|
// Check whether two given quaternions are almost equal
|
||||||
RMAPI int QuaternionEquals(Quaternion p, Quaternion q)
|
RMAPI int QuaternionEquals(Quaternion p, Quaternion q)
|
||||||
{
|
{
|
||||||
|
#if !defined(EPSILON)
|
||||||
|
#define EPSILON 0.000001f
|
||||||
|
#endif
|
||||||
|
|
||||||
int result = (((fabsf(p.x - q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) &&
|
int result = (((fabsf(p.x - q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) &&
|
||||||
((fabsf(p.y - q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))) &&
|
((fabsf(p.y - q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))) &&
|
||||||
((fabsf(p.z - q.z)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z))))) &&
|
((fabsf(p.z - q.z)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z))))) &&
|
||||||
|
|
|
@ -3,13 +3,12 @@
|
||||||
* rcamera - Basic camera system with support for multiple camera modes
|
* rcamera - Basic camera system with support for multiple camera modes
|
||||||
*
|
*
|
||||||
* CONFIGURATION:
|
* CONFIGURATION:
|
||||||
*
|
* #define RCAMERA_IMPLEMENTATION
|
||||||
* #define CAMERA_IMPLEMENTATION
|
|
||||||
* Generates the implementation of the library into the included file.
|
* Generates the implementation of the library into the included file.
|
||||||
* If not defined, the library is in header only mode and can be included in other headers
|
* If not defined, the library is in header only mode and can be included in other headers
|
||||||
* or source files without problems. But only ONE file should hold the implementation.
|
* or source files without problems. But only ONE file should hold the implementation.
|
||||||
*
|
*
|
||||||
* #define CAMERA_STANDALONE
|
* #define RCAMERA_STANDALONE
|
||||||
* If defined, the library can be used as standalone as a camera system but some
|
* If defined, the library can be used as standalone as a camera system but some
|
||||||
* functions must be redefined to manage inputs accordingly.
|
* functions must be redefined to manage inputs accordingly.
|
||||||
*
|
*
|
||||||
|
@ -47,11 +46,25 @@
|
||||||
// Defines and Macros
|
// Defines and Macros
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Function specifiers definition
|
// Function specifiers definition
|
||||||
|
|
||||||
|
// Function specifiers in case library is build/used as a shared library (Windows)
|
||||||
|
// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#if defined(BUILD_LIBTYPE_SHARED)
|
||||||
|
#if defined(__TINYC__)
|
||||||
|
#define __declspec(x) __attribute__((x))
|
||||||
|
#endif
|
||||||
|
#define RLAPI __declspec(dllexport) // We are building the library as a Win32 shared library (.dll)
|
||||||
|
#elif defined(USE_LIBTYPE_SHARED)
|
||||||
|
#define RLAPI __declspec(dllimport) // We are using the library as a Win32 shared library (.dll)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef RLAPI
|
#ifndef RLAPI
|
||||||
#define RLAPI // Functions defined as 'extern' by default (implicit specifiers)
|
#define RLAPI // Functions defined as 'extern' by default (implicit specifiers)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CAMERA_STANDALONE)
|
#if defined(RCAMERA_STANDALONE)
|
||||||
#define CAMERA_CULL_DISTANCE_NEAR 0.01
|
#define CAMERA_CULL_DISTANCE_NEAR 0.01
|
||||||
#define CAMERA_CULL_DISTANCE_FAR 1000.0
|
#define CAMERA_CULL_DISTANCE_FAR 1000.0
|
||||||
#else
|
#else
|
||||||
|
@ -61,9 +74,9 @@
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Types and Structures Definition
|
// Types and Structures Definition
|
||||||
// NOTE: Below types are required for CAMERA_STANDALONE usage
|
// NOTE: Below types are required for standalone usage
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
#if defined(CAMERA_STANDALONE)
|
#if defined(RCAMERA_STANDALONE)
|
||||||
// Vector2, 2 components
|
// Vector2, 2 components
|
||||||
typedef struct Vector2 {
|
typedef struct Vector2 {
|
||||||
float x; // Vector x component
|
float x; // Vector x component
|
||||||
|
@ -77,6 +90,14 @@
|
||||||
float z; // Vector z component
|
float z; // Vector z component
|
||||||
} Vector3;
|
} Vector3;
|
||||||
|
|
||||||
|
// Matrix, 4x4 components, column major, OpenGL style, right-handed
|
||||||
|
typedef struct Matrix {
|
||||||
|
float m0, m4, m8, m12; // Matrix first row (4 components)
|
||||||
|
float m1, m5, m9, m13; // Matrix second row (4 components)
|
||||||
|
float m2, m6, m10, m14; // Matrix third row (4 components)
|
||||||
|
float m3, m7, m11, m15; // Matrix fourth row (4 components)
|
||||||
|
} Matrix;
|
||||||
|
|
||||||
// Camera type, defines a camera position/orientation in 3d space
|
// Camera type, defines a camera position/orientation in 3d space
|
||||||
typedef struct Camera3D {
|
typedef struct Camera3D {
|
||||||
Vector3 position; // Camera position
|
Vector3 position; // Camera position
|
||||||
|
@ -139,7 +160,7 @@ RLAPI Matrix GetCameraProjectionMatrix(Camera* camera, float aspect);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // CAMERA_H
|
#endif // RCAMERA_H
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************************
|
/***********************************************************************************
|
||||||
|
@ -148,7 +169,7 @@ RLAPI Matrix GetCameraProjectionMatrix(Camera* camera, float aspect);
|
||||||
*
|
*
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
#if defined(CAMERA_IMPLEMENTATION)
|
#if defined(RCAMERA_IMPLEMENTATION)
|
||||||
|
|
||||||
#include "raymath.h" // Required for vector maths:
|
#include "raymath.h" // Required for vector maths:
|
||||||
// Vector3Add()
|
// Vector3Add()
|
||||||
|
@ -177,6 +198,7 @@ RLAPI Matrix GetCameraProjectionMatrix(Camera* camera, float aspect);
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
#define CAMERA_MOVE_SPEED 0.09f
|
#define CAMERA_MOVE_SPEED 0.09f
|
||||||
#define CAMERA_ROTATION_SPEED 0.03f
|
#define CAMERA_ROTATION_SPEED 0.03f
|
||||||
|
#define CAMERA_PAN_SPEED 0.2f
|
||||||
|
|
||||||
// Camera mouse movement sensitivity
|
// Camera mouse movement sensitivity
|
||||||
#define CAMERA_MOUSE_MOVE_SENSITIVITY 0.003f // TODO: it should be independant of framerate
|
#define CAMERA_MOUSE_MOVE_SENSITIVITY 0.003f // TODO: it should be independant of framerate
|
||||||
|
@ -294,7 +316,7 @@ void CameraMoveToTarget(Camera *camera, float delta)
|
||||||
distance += delta;
|
distance += delta;
|
||||||
|
|
||||||
// Distance must be greater than 0
|
// Distance must be greater than 0
|
||||||
if (distance < 0) distance = 0.001f;
|
if (distance <= 0) distance = 0.001f;
|
||||||
|
|
||||||
// Set new distance by moving the position along the forward vector
|
// Set new distance by moving the position along the forward vector
|
||||||
Vector3 forward = GetCameraForward(camera);
|
Vector3 forward = GetCameraForward(camera);
|
||||||
|
@ -418,7 +440,7 @@ Matrix GetCameraProjectionMatrix(Camera *camera, float aspect)
|
||||||
return MatrixIdentity();
|
return MatrixIdentity();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CAMERA_STANDALONE
|
#if !defined(RCAMERA_STANDALONE)
|
||||||
// Update camera position for selected mode
|
// Update camera position for selected mode
|
||||||
// Camera mode: CAMERA_FREE, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON, CAMERA_ORBITAL or CUSTOM
|
// Camera mode: CAMERA_FREE, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON, CAMERA_ORBITAL or CUSTOM
|
||||||
void UpdateCamera(Camera *camera, int mode)
|
void UpdateCamera(Camera *camera, int mode)
|
||||||
|
@ -428,7 +450,7 @@ void UpdateCamera(Camera *camera, int mode)
|
||||||
bool moveInWorldPlane = ((mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON));
|
bool moveInWorldPlane = ((mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON));
|
||||||
bool rotateAroundTarget = ((mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL));
|
bool rotateAroundTarget = ((mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL));
|
||||||
bool lockView = ((mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL));
|
bool lockView = ((mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL));
|
||||||
bool rotateUp = (mode == CAMERA_FREE);
|
bool rotateUp = false;
|
||||||
|
|
||||||
if (mode == CAMERA_ORBITAL)
|
if (mode == CAMERA_ORBITAL)
|
||||||
{
|
{
|
||||||
|
@ -448,19 +470,51 @@ void UpdateCamera(Camera *camera, int mode)
|
||||||
if (IsKeyDown(KEY_Q)) CameraRoll(camera, -CAMERA_ROTATION_SPEED);
|
if (IsKeyDown(KEY_Q)) CameraRoll(camera, -CAMERA_ROTATION_SPEED);
|
||||||
if (IsKeyDown(KEY_E)) CameraRoll(camera, CAMERA_ROTATION_SPEED);
|
if (IsKeyDown(KEY_E)) CameraRoll(camera, CAMERA_ROTATION_SPEED);
|
||||||
|
|
||||||
|
// Camera movement
|
||||||
|
if (!IsGamepadAvailable(0))
|
||||||
|
{
|
||||||
|
// Camera pan (for CAMERA_FREE)
|
||||||
|
if ((mode == CAMERA_FREE) && (IsMouseButtonDown(MOUSE_BUTTON_MIDDLE)))
|
||||||
|
{
|
||||||
|
const Vector2 mouseDelta = GetMouseDelta();
|
||||||
|
if (mouseDelta.x > 0.0f) CameraMoveRight(camera, CAMERA_PAN_SPEED, moveInWorldPlane);
|
||||||
|
if (mouseDelta.x < 0.0f) CameraMoveRight(camera, -CAMERA_PAN_SPEED, moveInWorldPlane);
|
||||||
|
if (mouseDelta.y > 0.0f) CameraMoveUp(camera, -CAMERA_PAN_SPEED);
|
||||||
|
if (mouseDelta.y < 0.0f) CameraMoveUp(camera, CAMERA_PAN_SPEED);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Mouse support
|
||||||
CameraYaw(camera, -mousePositionDelta.x*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget);
|
CameraYaw(camera, -mousePositionDelta.x*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget);
|
||||||
CameraPitch(camera, -mousePositionDelta.y*CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp);
|
CameraPitch(camera, -mousePositionDelta.y*CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp);
|
||||||
|
}
|
||||||
|
|
||||||
// Camera movement
|
// Keyboard support
|
||||||
if (IsKeyDown(KEY_W)) CameraMoveForward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
|
if (IsKeyDown(KEY_W)) CameraMoveForward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
|
||||||
if (IsKeyDown(KEY_A)) CameraMoveRight(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
|
if (IsKeyDown(KEY_A)) CameraMoveRight(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
|
||||||
if (IsKeyDown(KEY_S)) CameraMoveForward(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
|
if (IsKeyDown(KEY_S)) CameraMoveForward(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
|
||||||
if (IsKeyDown(KEY_D)) CameraMoveRight(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
|
if (IsKeyDown(KEY_D)) CameraMoveRight(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
|
||||||
//if (IsKeyDown(KEY_SPACE)) CameraMoveUp(camera, CAMERA_MOVE_SPEED);
|
}
|
||||||
//if (IsKeyDown(KEY_LEFT_CONTROL)) CameraMoveUp(camera, -CAMERA_MOVE_SPEED);
|
else
|
||||||
|
{
|
||||||
|
// Gamepad controller support
|
||||||
|
CameraYaw(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_X) * 2)*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget);
|
||||||
|
CameraPitch(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_Y) * 2)*CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp);
|
||||||
|
|
||||||
|
if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) <= -0.25f) CameraMoveForward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
|
||||||
|
if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) <= -0.25f) CameraMoveRight(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
|
||||||
|
if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) >= 0.25f) CameraMoveForward(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
|
||||||
|
if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) >= 0.25f) CameraMoveRight(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL))
|
if (mode == CAMERA_FREE)
|
||||||
|
{
|
||||||
|
if (IsKeyDown(KEY_SPACE)) CameraMoveUp(camera, CAMERA_MOVE_SPEED);
|
||||||
|
if (IsKeyDown(KEY_LEFT_CONTROL)) CameraMoveUp(camera, -CAMERA_MOVE_SPEED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL) || (mode == CAMERA_FREE))
|
||||||
{
|
{
|
||||||
// Zoom target distance
|
// Zoom target distance
|
||||||
CameraMoveToTarget(camera, -GetMouseWheelMove());
|
CameraMoveToTarget(camera, -GetMouseWheelMove());
|
||||||
|
@ -468,7 +522,7 @@ void UpdateCamera(Camera *camera, int mode)
|
||||||
if (IsKeyPressed(KEY_KP_ADD)) CameraMoveToTarget(camera, -2.0f);
|
if (IsKeyPressed(KEY_KP_ADD)) CameraMoveToTarget(camera, -2.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // !CAMERA_STANDALONE
|
#endif // !RCAMERA_STANDALONE
|
||||||
|
|
||||||
// Update camera movement, movement/rotation values should be provided by user
|
// Update camera movement, movement/rotation values should be provided by user
|
||||||
void UpdateCameraPro(Camera *camera, Vector3 movement, Vector3 rotation, float zoom)
|
void UpdateCameraPro(Camera *camera, Vector3 movement, Vector3 rotation, float zoom)
|
||||||
|
@ -501,4 +555,4 @@ void UpdateCameraPro(Camera *camera, Vector3 movement, Vector3 rotation, float z
|
||||||
CameraMoveToTarget(camera, zoom);
|
CameraMoveToTarget(camera, zoom);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // CAMERA_IMPLEMENTATION
|
#endif // RCAMERA_IMPLEMENTATION
|
||||||
|
|
5847
raylib/rcore.c
5847
raylib/rcore.c
File diff suppressed because it is too large
Load diff
|
@ -14,7 +14,7 @@ func SetGesturesEnabled(gestureFlags uint32) {
|
||||||
|
|
||||||
// IsGestureDetected - Check if a gesture have been detected
|
// IsGestureDetected - Check if a gesture have been detected
|
||||||
func IsGestureDetected(gesture Gestures) bool {
|
func IsGestureDetected(gesture Gestures) bool {
|
||||||
cgesture := (C.int)(gesture)
|
cgesture := (C.uint)(gesture)
|
||||||
ret := C.IsGestureDetected(cgesture)
|
ret := C.IsGestureDetected(cgesture)
|
||||||
v := bool(ret)
|
v := bool(ret)
|
||||||
return v
|
return v
|
||||||
|
|
|
@ -2,16 +2,13 @@
|
||||||
*
|
*
|
||||||
* rgestures - Gestures system, gestures processing based on input events (touch/mouse)
|
* rgestures - Gestures system, gestures processing based on input events (touch/mouse)
|
||||||
*
|
*
|
||||||
* NOTE: Memory footprint of this library is aproximately 128 bytes (global variables)
|
|
||||||
*
|
|
||||||
* CONFIGURATION:
|
* CONFIGURATION:
|
||||||
*
|
* #define RGESTURES_IMPLEMENTATION
|
||||||
* #define GESTURES_IMPLEMENTATION
|
|
||||||
* Generates the implementation of the library into the included file.
|
* Generates the implementation of the library into the included file.
|
||||||
* If not defined, the library is in header only mode and can be included in other headers
|
* If not defined, the library is in header only mode and can be included in other headers
|
||||||
* or source files without problems. But only ONE file should hold the implementation.
|
* or source files without problems. But only ONE file should hold the implementation.
|
||||||
*
|
*
|
||||||
* #define GESTURES_STANDALONE
|
* #define RGESTURES_STANDALONE
|
||||||
* If defined, the library can be used as standalone to process gesture events with
|
* If defined, the library can be used as standalone to process gesture events with
|
||||||
* no external dependencies.
|
* no external dependencies.
|
||||||
*
|
*
|
||||||
|
@ -59,7 +56,7 @@
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Types and Structures Definition
|
// Types and Structures Definition
|
||||||
// NOTE: Below types are required for GESTURES_STANDALONE usage
|
// NOTE: Below types are required for standalone usage
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Boolean type
|
// Boolean type
|
||||||
#if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
|
#if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
|
||||||
|
@ -76,7 +73,7 @@ typedef struct Vector2 {
|
||||||
} Vector2;
|
} Vector2;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(GESTURES_STANDALONE)
|
#if defined(RGESTURES_STANDALONE)
|
||||||
// Gestures type
|
// Gestures type
|
||||||
// NOTE: It could be used as flags to enable only some gestures
|
// NOTE: It could be used as flags to enable only some gestures
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -125,12 +122,12 @@ extern "C" { // Prevents name mangling of functions
|
||||||
void ProcessGestureEvent(GestureEvent event); // Process gesture event and translate it into gestures
|
void ProcessGestureEvent(GestureEvent event); // Process gesture event and translate it into gestures
|
||||||
void UpdateGestures(void); // Update gestures detected (must be called every frame)
|
void UpdateGestures(void); // Update gestures detected (must be called every frame)
|
||||||
|
|
||||||
#if defined(GESTURES_STANDALONE)
|
#if defined(RGESTURES_STANDALONE)
|
||||||
void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
|
void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
|
||||||
bool IsGestureDetected(int gesture); // Check if a gesture have been detected
|
bool IsGestureDetected(int gesture); // Check if a gesture have been detected
|
||||||
int GetGestureDetected(void); // Get latest detected gesture
|
int GetGestureDetected(void); // Get latest detected gesture
|
||||||
|
|
||||||
float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds
|
float GetGestureHoldDuration(void); // Get gesture hold time in seconds
|
||||||
Vector2 GetGestureDragVector(void); // Get gesture drag vector
|
Vector2 GetGestureDragVector(void); // Get gesture drag vector
|
||||||
float GetGestureDragAngle(void); // Get gesture drag angle
|
float GetGestureDragAngle(void); // Get gesture drag angle
|
||||||
Vector2 GetGesturePinchVector(void); // Get gesture pinch delta
|
Vector2 GetGesturePinchVector(void); // Get gesture pinch delta
|
||||||
|
@ -141,17 +138,17 @@ float GetGesturePinchAngle(void); // Get gesture pinch ang
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // GESTURES_H
|
#endif // RGESTURES_H
|
||||||
|
|
||||||
/***********************************************************************************
|
/***********************************************************************************
|
||||||
*
|
*
|
||||||
* GESTURES IMPLEMENTATION
|
* RGESTURES IMPLEMENTATION
|
||||||
*
|
*
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
#if defined(GESTURES_IMPLEMENTATION)
|
#if defined(RGESTURES_IMPLEMENTATION)
|
||||||
|
|
||||||
#if defined(GESTURES_STANDALONE)
|
#if defined(RGESTURES_STANDALONE)
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
extern "C" { // Prevents name mangling of functions
|
extern "C" { // Prevents name mangling of functions
|
||||||
|
@ -181,11 +178,12 @@ float GetGesturePinchAngle(void); // Get gesture pinch ang
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Defines and Macros
|
// Defines and Macros
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
#define FORCE_TO_SWIPE 0.0005f // Swipe force, measured in normalized screen units/time
|
#define FORCE_TO_SWIPE 0.2f // Swipe force, measured in normalized screen units/time
|
||||||
#define MINIMUM_DRAG 0.015f // Drag minimum force, measured in normalized screen units (0.0f to 1.0f)
|
#define MINIMUM_DRAG 0.015f // Drag minimum force, measured in normalized screen units (0.0f to 1.0f)
|
||||||
|
#define DRAG_TIMEOUT 0.3f // Drag minimum time for web, measured in seconds
|
||||||
#define MINIMUM_PINCH 0.005f // Pinch minimum force, measured in normalized screen units (0.0f to 1.0f)
|
#define MINIMUM_PINCH 0.005f // Pinch minimum force, measured in normalized screen units (0.0f to 1.0f)
|
||||||
#define TAP_TIMEOUT 300 // Tap minimum time, measured in milliseconds
|
#define TAP_TIMEOUT 0.3f // Tap minimum time, measured in seconds
|
||||||
#define PINCH_TIMEOUT 300 // Pinch minimum time, measured in milliseconds
|
#define PINCH_TIMEOUT 0.3f // Pinch minimum time, measured in seconds
|
||||||
#define DOUBLETAP_RANGE 0.03f // DoubleTap range, measured in normalized screen units (0.0f to 1.0f)
|
#define DOUBLETAP_RANGE 0.03f // DoubleTap range, measured in normalized screen units (0.0f to 1.0f)
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
@ -206,11 +204,13 @@ typedef struct {
|
||||||
Vector2 downDragPosition; // Touch drag position
|
Vector2 downDragPosition; // Touch drag position
|
||||||
Vector2 moveDownPositionA; // First touch down position on move
|
Vector2 moveDownPositionA; // First touch down position on move
|
||||||
Vector2 moveDownPositionB; // Second touch down position on move
|
Vector2 moveDownPositionB; // Second touch down position on move
|
||||||
|
Vector2 previousPositionA; // Previous position A to compare for pinch gestures
|
||||||
|
Vector2 previousPositionB; // Previous position B to compare for pinch gestures
|
||||||
int tapCounter; // TAP counter (one tap implies TOUCH_ACTION_DOWN and TOUCH_ACTION_UP actions)
|
int tapCounter; // TAP counter (one tap implies TOUCH_ACTION_DOWN and TOUCH_ACTION_UP actions)
|
||||||
} Touch;
|
} Touch;
|
||||||
struct {
|
struct {
|
||||||
bool resetRequired; // HOLD reset to get first touch point again
|
bool resetRequired; // HOLD reset to get first touch point again
|
||||||
double timeDuration; // HOLD duration in milliseconds
|
double timeDuration; // HOLD duration in seconds
|
||||||
} Hold;
|
} Hold;
|
||||||
struct {
|
struct {
|
||||||
Vector2 vector; // DRAG vector (between initial and current position)
|
Vector2 vector; // DRAG vector (between initial and current position)
|
||||||
|
@ -219,8 +219,7 @@ typedef struct {
|
||||||
float intensity; // DRAG intensity, how far why did the DRAG (pixels per frame)
|
float intensity; // DRAG intensity, how far why did the DRAG (pixels per frame)
|
||||||
} Drag;
|
} Drag;
|
||||||
struct {
|
struct {
|
||||||
bool start; // SWIPE used to define when start measuring GESTURES.Swipe.timeDuration
|
double startTime; // SWIPE start time to calculate drag intensity
|
||||||
double timeDuration; // SWIPE time to calculate drag intensity
|
|
||||||
} Swipe;
|
} Swipe;
|
||||||
struct {
|
struct {
|
||||||
Vector2 vector; // PINCH vector (between first and second touch points)
|
Vector2 vector; // PINCH vector (between first and second touch points)
|
||||||
|
@ -256,7 +255,7 @@ void SetGesturesEnabled(unsigned int flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if a gesture have been detected
|
// Check if a gesture have been detected
|
||||||
bool IsGestureDetected(int gesture)
|
bool IsGestureDetected(unsigned int gesture)
|
||||||
{
|
{
|
||||||
if ((GESTURES.enabledFlags & GESTURES.current) == gesture) return true;
|
if ((GESTURES.enabledFlags & GESTURES.current) == gesture) return true;
|
||||||
else return false;
|
else return false;
|
||||||
|
@ -292,30 +291,29 @@ void ProcessGestureEvent(GestureEvent event)
|
||||||
GESTURES.Touch.upPosition = GESTURES.Touch.downPositionA;
|
GESTURES.Touch.upPosition = GESTURES.Touch.downPositionA;
|
||||||
GESTURES.Touch.eventTime = rgGetCurrentTime();
|
GESTURES.Touch.eventTime = rgGetCurrentTime();
|
||||||
|
|
||||||
GESTURES.Touch.firstId = event.pointId[0];
|
GESTURES.Swipe.startTime = rgGetCurrentTime();
|
||||||
|
|
||||||
GESTURES.Drag.vector = (Vector2){ 0.0f, 0.0f };
|
GESTURES.Drag.vector = (Vector2){ 0.0f, 0.0f };
|
||||||
}
|
}
|
||||||
else if (event.touchAction == TOUCH_ACTION_UP)
|
else if (event.touchAction == TOUCH_ACTION_UP)
|
||||||
{
|
{
|
||||||
if (GESTURES.current == GESTURE_DRAG) GESTURES.Touch.upPosition = event.position[0];
|
// A swipe can happen while the current gesture is drag, but (specially for web) also hold, so set upPosition for both cases
|
||||||
|
if (GESTURES.current == GESTURE_DRAG || GESTURES.current == GESTURE_HOLD) GESTURES.Touch.upPosition = event.position[0];
|
||||||
|
|
||||||
// NOTE: GESTURES.Drag.intensity dependent on the resolution of the screen
|
// NOTE: GESTURES.Drag.intensity dependent on the resolution of the screen
|
||||||
GESTURES.Drag.distance = rgVector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.upPosition);
|
GESTURES.Drag.distance = rgVector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.upPosition);
|
||||||
GESTURES.Drag.intensity = GESTURES.Drag.distance/(float)((rgGetCurrentTime() - GESTURES.Swipe.timeDuration));
|
GESTURES.Drag.intensity = GESTURES.Drag.distance/(float)((rgGetCurrentTime() - GESTURES.Swipe.startTime));
|
||||||
|
|
||||||
GESTURES.Swipe.start = false;
|
|
||||||
|
|
||||||
// Detect GESTURE_SWIPE
|
// Detect GESTURE_SWIPE
|
||||||
if ((GESTURES.Drag.intensity > FORCE_TO_SWIPE) && (GESTURES.Touch.firstId == event.pointId[0]))
|
if ((GESTURES.Drag.intensity > FORCE_TO_SWIPE) && (GESTURES.current != GESTURE_DRAG))
|
||||||
{
|
{
|
||||||
// NOTE: Angle should be inverted in Y
|
// NOTE: Angle should be inverted in Y
|
||||||
GESTURES.Drag.angle = 360.0f - rgVector2Angle(GESTURES.Touch.downPositionA, GESTURES.Touch.upPosition);
|
GESTURES.Drag.angle = 360.0f - rgVector2Angle(GESTURES.Touch.downPositionA, GESTURES.Touch.upPosition);
|
||||||
|
|
||||||
if ((GESTURES.Drag.angle < 30) || (GESTURES.Drag.angle > 330)) GESTURES.current = GESTURE_SWIPE_RIGHT; // Right
|
if ((GESTURES.Drag.angle < 30) || (GESTURES.Drag.angle > 330)) GESTURES.current = GESTURE_SWIPE_RIGHT; // Right
|
||||||
else if ((GESTURES.Drag.angle > 30) && (GESTURES.Drag.angle < 120)) GESTURES.current = GESTURE_SWIPE_UP; // Up
|
else if ((GESTURES.Drag.angle >= 30) && (GESTURES.Drag.angle <= 150)) GESTURES.current = GESTURE_SWIPE_UP; // Up
|
||||||
else if ((GESTURES.Drag.angle > 120) && (GESTURES.Drag.angle < 210)) GESTURES.current = GESTURE_SWIPE_LEFT; // Left
|
else if ((GESTURES.Drag.angle > 150) && (GESTURES.Drag.angle < 210)) GESTURES.current = GESTURE_SWIPE_LEFT; // Left
|
||||||
else if ((GESTURES.Drag.angle > 210) && (GESTURES.Drag.angle < 300)) GESTURES.current = GESTURE_SWIPE_DOWN; // Down
|
else if ((GESTURES.Drag.angle >= 210) && (GESTURES.Drag.angle <= 330)) GESTURES.current = GESTURE_SWIPE_DOWN; // Down
|
||||||
else GESTURES.current = GESTURE_NONE;
|
else GESTURES.current = GESTURE_NONE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -332,14 +330,6 @@ void ProcessGestureEvent(GestureEvent event)
|
||||||
}
|
}
|
||||||
else if (event.touchAction == TOUCH_ACTION_MOVE)
|
else if (event.touchAction == TOUCH_ACTION_MOVE)
|
||||||
{
|
{
|
||||||
if (GESTURES.current == GESTURE_DRAG) GESTURES.Touch.eventTime = rgGetCurrentTime();
|
|
||||||
|
|
||||||
if (!GESTURES.Swipe.start)
|
|
||||||
{
|
|
||||||
GESTURES.Swipe.timeDuration = rgGetCurrentTime();
|
|
||||||
GESTURES.Swipe.start = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
GESTURES.Touch.moveDownPositionA = event.position[0];
|
GESTURES.Touch.moveDownPositionA = event.position[0];
|
||||||
|
|
||||||
if (GESTURES.current == GESTURE_HOLD)
|
if (GESTURES.current == GESTURE_HOLD)
|
||||||
|
@ -349,7 +339,7 @@ void ProcessGestureEvent(GestureEvent event)
|
||||||
GESTURES.Hold.resetRequired = false;
|
GESTURES.Hold.resetRequired = false;
|
||||||
|
|
||||||
// Detect GESTURE_DRAG
|
// Detect GESTURE_DRAG
|
||||||
if (rgVector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.moveDownPositionA) >= MINIMUM_DRAG)
|
if ((rgGetCurrentTime() - GESTURES.Touch.eventTime) > DRAG_TIMEOUT)
|
||||||
{
|
{
|
||||||
GESTURES.Touch.eventTime = rgGetCurrentTime();
|
GESTURES.Touch.eventTime = rgGetCurrentTime();
|
||||||
GESTURES.current = GESTURE_DRAG;
|
GESTURES.current = GESTURE_DRAG;
|
||||||
|
@ -367,6 +357,9 @@ void ProcessGestureEvent(GestureEvent event)
|
||||||
GESTURES.Touch.downPositionA = event.position[0];
|
GESTURES.Touch.downPositionA = event.position[0];
|
||||||
GESTURES.Touch.downPositionB = event.position[1];
|
GESTURES.Touch.downPositionB = event.position[1];
|
||||||
|
|
||||||
|
GESTURES.Touch.previousPositionA = GESTURES.Touch.downPositionA;
|
||||||
|
GESTURES.Touch.previousPositionB = GESTURES.Touch.downPositionB;
|
||||||
|
|
||||||
//GESTURES.Pinch.distance = rgVector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.downPositionB);
|
//GESTURES.Pinch.distance = rgVector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.downPositionB);
|
||||||
|
|
||||||
GESTURES.Pinch.vector.x = GESTURES.Touch.downPositionB.x - GESTURES.Touch.downPositionA.x;
|
GESTURES.Pinch.vector.x = GESTURES.Touch.downPositionB.x - GESTURES.Touch.downPositionA.x;
|
||||||
|
@ -379,18 +372,15 @@ void ProcessGestureEvent(GestureEvent event)
|
||||||
{
|
{
|
||||||
GESTURES.Pinch.distance = rgVector2Distance(GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB);
|
GESTURES.Pinch.distance = rgVector2Distance(GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB);
|
||||||
|
|
||||||
GESTURES.Touch.downPositionA = GESTURES.Touch.moveDownPositionA;
|
|
||||||
GESTURES.Touch.downPositionB = GESTURES.Touch.moveDownPositionB;
|
|
||||||
|
|
||||||
GESTURES.Touch.moveDownPositionA = event.position[0];
|
GESTURES.Touch.moveDownPositionA = event.position[0];
|
||||||
GESTURES.Touch.moveDownPositionB = event.position[1];
|
GESTURES.Touch.moveDownPositionB = event.position[1];
|
||||||
|
|
||||||
GESTURES.Pinch.vector.x = GESTURES.Touch.moveDownPositionB.x - GESTURES.Touch.moveDownPositionA.x;
|
GESTURES.Pinch.vector.x = GESTURES.Touch.moveDownPositionB.x - GESTURES.Touch.moveDownPositionA.x;
|
||||||
GESTURES.Pinch.vector.y = GESTURES.Touch.moveDownPositionB.y - GESTURES.Touch.moveDownPositionA.y;
|
GESTURES.Pinch.vector.y = GESTURES.Touch.moveDownPositionB.y - GESTURES.Touch.moveDownPositionA.y;
|
||||||
|
|
||||||
if ((rgVector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.moveDownPositionA) >= MINIMUM_PINCH) || (rgVector2Distance(GESTURES.Touch.downPositionB, GESTURES.Touch.moveDownPositionB) >= MINIMUM_PINCH))
|
if ((rgVector2Distance(GESTURES.Touch.previousPositionA, GESTURES.Touch.moveDownPositionA) >= MINIMUM_PINCH) || (rgVector2Distance(GESTURES.Touch.previousPositionB, GESTURES.Touch.moveDownPositionB) >= MINIMUM_PINCH))
|
||||||
{
|
{
|
||||||
if ((rgVector2Distance(GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB) - GESTURES.Pinch.distance) < 0) GESTURES.current = GESTURE_PINCH_IN;
|
if ( rgVector2Distance(GESTURES.Touch.previousPositionA, GESTURES.Touch.previousPositionB) > rgVector2Distance(GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB) ) GESTURES.current = GESTURE_PINCH_IN;
|
||||||
else GESTURES.current = GESTURE_PINCH_OUT;
|
else GESTURES.current = GESTURE_PINCH_OUT;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -430,13 +420,6 @@ void UpdateGestures(void)
|
||||||
GESTURES.Hold.timeDuration = rgGetCurrentTime();
|
GESTURES.Hold.timeDuration = rgGetCurrentTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((rgGetCurrentTime() - GESTURES.Touch.eventTime) > TAP_TIMEOUT) && (GESTURES.current == GESTURE_DRAG) && (GESTURES.Touch.pointCount < 2))
|
|
||||||
{
|
|
||||||
GESTURES.current = GESTURE_HOLD;
|
|
||||||
GESTURES.Hold.timeDuration = rgGetCurrentTime();
|
|
||||||
GESTURES.Hold.resetRequired = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Detect GESTURE_NONE
|
// Detect GESTURE_NONE
|
||||||
if ((GESTURES.current == GESTURE_SWIPE_RIGHT) || (GESTURES.current == GESTURE_SWIPE_UP) || (GESTURES.current == GESTURE_SWIPE_LEFT) || (GESTURES.current == GESTURE_SWIPE_DOWN))
|
if ((GESTURES.current == GESTURE_SWIPE_RIGHT) || (GESTURES.current == GESTURE_SWIPE_UP) || (GESTURES.current == GESTURE_SWIPE_LEFT) || (GESTURES.current == GESTURE_SWIPE_DOWN))
|
||||||
{
|
{
|
||||||
|
@ -523,12 +506,12 @@ static float rgVector2Distance(Vector2 v1, Vector2 v2)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Time measure returned are milliseconds
|
// Time measure returned are seconds
|
||||||
static double rgGetCurrentTime(void)
|
static double rgGetCurrentTime(void)
|
||||||
{
|
{
|
||||||
double time = 0;
|
double time = 0;
|
||||||
|
|
||||||
#if !defined(GESTURES_STANDALONE)
|
#if !defined(RGESTURES_STANDALONE)
|
||||||
time = GetTime();
|
time = GetTime();
|
||||||
#else
|
#else
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
@ -537,7 +520,7 @@ static double rgGetCurrentTime(void)
|
||||||
QueryPerformanceFrequency(&clockFrequency); // BE CAREFUL: Costly operation!
|
QueryPerformanceFrequency(&clockFrequency); // BE CAREFUL: Costly operation!
|
||||||
QueryPerformanceCounter(¤tTime);
|
QueryPerformanceCounter(¤tTime);
|
||||||
|
|
||||||
time = (double)currentTime/clockFrequency*1000.0f; // Time in miliseconds
|
time = (double)currentTime/clockFrequency; // Time in seconds
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
|
@ -546,7 +529,7 @@ static double rgGetCurrentTime(void)
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
unsigned long long int nowTime = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec; // Time in nanoseconds
|
unsigned long long int nowTime = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec; // Time in nanoseconds
|
||||||
|
|
||||||
time = ((double)nowTime/1000000.0); // Time in miliseconds
|
time = ((double)nowTime*1e-9); // Time in seconds
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
|
@ -562,11 +545,11 @@ static double rgGetCurrentTime(void)
|
||||||
mach_port_deallocate(mach_task_self(), cclock);
|
mach_port_deallocate(mach_task_self(), cclock);
|
||||||
unsigned long long int nowTime = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec; // Time in nanoseconds
|
unsigned long long int nowTime = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec; // Time in nanoseconds
|
||||||
|
|
||||||
time = ((double)nowTime/1000000.0); // Time in miliseconds
|
time = ((double)nowTime*1e-9); // Time in seconds
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // GESTURES_IMPLEMENTATION
|
#endif // RGESTURES_IMPLEMENTATION
|
||||||
|
|
240
raylib/rlgl.h
240
raylib/rlgl.h
|
@ -2,30 +2,31 @@
|
||||||
*
|
*
|
||||||
* rlgl v4.5 - A multi-OpenGL abstraction layer with an immediate-mode style API
|
* rlgl v4.5 - A multi-OpenGL abstraction layer with an immediate-mode style API
|
||||||
*
|
*
|
||||||
|
* DESCRIPTION:
|
||||||
* An abstraction layer for multiple OpenGL versions (1.1, 2.1, 3.3 Core, 4.3 Core, ES 2.0)
|
* An abstraction layer for multiple OpenGL versions (1.1, 2.1, 3.3 Core, 4.3 Core, ES 2.0)
|
||||||
* that provides a pseudo-OpenGL 1.1 immediate-mode style API (rlVertex, rlTranslate, rlRotate...)
|
* that provides a pseudo-OpenGL 1.1 immediate-mode style API (rlVertex, rlTranslate, rlRotate...)
|
||||||
*
|
*
|
||||||
|
* ADDITIONAL NOTES:
|
||||||
* When choosing an OpenGL backend different than OpenGL 1.1, some internal buffer are
|
* When choosing an OpenGL backend different than OpenGL 1.1, some internal buffer are
|
||||||
* initialized on rlglInit() to accumulate vertex data.
|
* initialized on rlglInit() to accumulate vertex data.
|
||||||
*
|
*
|
||||||
* When an internal state change is required all the stored vertex data is renderer in batch,
|
* When an internal state change is required all the stored vertex data is renderer in batch,
|
||||||
* additionally, rlDrawRenderBatchActive() could be called to force flushing of the batch.
|
* additionally, rlDrawRenderBatchActive() could be called to force flushing of the batch.
|
||||||
*
|
*
|
||||||
* Some additional resources are also loaded for convenience, here the complete list:
|
* Some resources are also loaded for convenience, here the complete list:
|
||||||
* - Default batch (RLGL.defaultBatch): RenderBatch system to accumulate vertex data
|
* - Default batch (RLGL.defaultBatch): RenderBatch system to accumulate vertex data
|
||||||
* - Default texture (RLGL.defaultTextureId): 1x1 white pixel R8G8B8A8
|
* - Default texture (RLGL.defaultTextureId): 1x1 white pixel R8G8B8A8
|
||||||
* - Default shader (RLGL.State.defaultShaderId, RLGL.State.defaultShaderLocs)
|
* - Default shader (RLGL.State.defaultShaderId, RLGL.State.defaultShaderLocs)
|
||||||
*
|
*
|
||||||
* Internal buffer (and additional resources) must be manually unloaded calling rlglClose().
|
* Internal buffer (and resources) must be manually unloaded calling rlglClose().
|
||||||
*
|
|
||||||
*
|
*
|
||||||
* CONFIGURATION:
|
* CONFIGURATION:
|
||||||
*
|
|
||||||
* #define GRAPHICS_API_OPENGL_11
|
* #define GRAPHICS_API_OPENGL_11
|
||||||
* #define GRAPHICS_API_OPENGL_21
|
* #define GRAPHICS_API_OPENGL_21
|
||||||
* #define GRAPHICS_API_OPENGL_33
|
* #define GRAPHICS_API_OPENGL_33
|
||||||
* #define GRAPHICS_API_OPENGL_43
|
* #define GRAPHICS_API_OPENGL_43
|
||||||
* #define GRAPHICS_API_OPENGL_ES2
|
* #define GRAPHICS_API_OPENGL_ES2
|
||||||
|
* #define GRAPHICS_API_OPENGL_ES3
|
||||||
* Use selected OpenGL graphics backend, should be supported by platform
|
* Use selected OpenGL graphics backend, should be supported by platform
|
||||||
* Those preprocessor defines are only used on rlgl module, if OpenGL version is
|
* Those preprocessor defines are only used on rlgl module, if OpenGL version is
|
||||||
* required by any other module, use rlGetVersion() to check it
|
* required by any other module, use rlGetVersion() to check it
|
||||||
|
@ -77,7 +78,6 @@
|
||||||
* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2)
|
* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2)
|
||||||
*
|
*
|
||||||
* DEPENDENCIES:
|
* DEPENDENCIES:
|
||||||
*
|
|
||||||
* - OpenGL libraries (depending on platform and OpenGL version selected)
|
* - OpenGL libraries (depending on platform and OpenGL version selected)
|
||||||
* - GLAD OpenGL extensions loading library (only for OpenGL 3.3 Core, 4.3 Core)
|
* - GLAD OpenGL extensions loading library (only for OpenGL 3.3 Core, 4.3 Core)
|
||||||
*
|
*
|
||||||
|
@ -148,7 +148,8 @@
|
||||||
!defined(GRAPHICS_API_OPENGL_21) && \
|
!defined(GRAPHICS_API_OPENGL_21) && \
|
||||||
!defined(GRAPHICS_API_OPENGL_33) && \
|
!defined(GRAPHICS_API_OPENGL_33) && \
|
||||||
!defined(GRAPHICS_API_OPENGL_43) && \
|
!defined(GRAPHICS_API_OPENGL_43) && \
|
||||||
!defined(GRAPHICS_API_OPENGL_ES2)
|
!defined(GRAPHICS_API_OPENGL_ES2) && \
|
||||||
|
!defined(GRAPHICS_API_OPENGL_ES3)
|
||||||
#define GRAPHICS_API_OPENGL_33
|
#define GRAPHICS_API_OPENGL_33
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -179,6 +180,11 @@
|
||||||
#define GRAPHICS_API_OPENGL_33
|
#define GRAPHICS_API_OPENGL_33
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// OpenGL ES 3.0 uses OpenGL ES 2.0 functionality (and more)
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_ES3)
|
||||||
|
#define GRAPHICS_API_OPENGL_ES2
|
||||||
|
#endif
|
||||||
|
|
||||||
// Support framebuffer objects by default
|
// Support framebuffer objects by default
|
||||||
// NOTE: Some driver implementation do not support it, despite they should
|
// NOTE: Some driver implementation do not support it, despite they should
|
||||||
#define RLGL_RENDER_TEXTURES_HINT
|
#define RLGL_RENDER_TEXTURES_HINT
|
||||||
|
@ -383,7 +389,8 @@ typedef enum {
|
||||||
RL_OPENGL_21, // OpenGL 2.1 (GLSL 120)
|
RL_OPENGL_21, // OpenGL 2.1 (GLSL 120)
|
||||||
RL_OPENGL_33, // OpenGL 3.3 (GLSL 330)
|
RL_OPENGL_33, // OpenGL 3.3 (GLSL 330)
|
||||||
RL_OPENGL_43, // OpenGL 4.3 (using GLSL 330)
|
RL_OPENGL_43, // OpenGL 4.3 (using GLSL 330)
|
||||||
RL_OPENGL_ES_20 // OpenGL ES 2.0 (GLSL 100)
|
RL_OPENGL_ES_20, // OpenGL ES 2.0 (GLSL 100)
|
||||||
|
RL_OPENGL_ES_30 // OpenGL ES 3.0 (GLSL 300 es)
|
||||||
} rlGlVersion;
|
} rlGlVersion;
|
||||||
|
|
||||||
// Trace log level
|
// Trace log level
|
||||||
|
@ -412,6 +419,9 @@ typedef enum {
|
||||||
RL_PIXELFORMAT_UNCOMPRESSED_R32, // 32 bpp (1 channel - float)
|
RL_PIXELFORMAT_UNCOMPRESSED_R32, // 32 bpp (1 channel - float)
|
||||||
RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32, // 32*3 bpp (3 channels - float)
|
RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32, // 32*3 bpp (3 channels - float)
|
||||||
RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32, // 32*4 bpp (4 channels - float)
|
RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32, // 32*4 bpp (4 channels - float)
|
||||||
|
RL_PIXELFORMAT_UNCOMPRESSED_R16, // 16 bpp (1 channel - half float)
|
||||||
|
RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16, // 16*3 bpp (3 channels - half float)
|
||||||
|
RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16, // 16*4 bpp (4 channels - half float)
|
||||||
RL_PIXELFORMAT_COMPRESSED_DXT1_RGB, // 4 bpp (no alpha)
|
RL_PIXELFORMAT_COMPRESSED_DXT1_RGB, // 4 bpp (no alpha)
|
||||||
RL_PIXELFORMAT_COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha)
|
RL_PIXELFORMAT_COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha)
|
||||||
RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA, // 8 bpp
|
RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA, // 8 bpp
|
||||||
|
@ -507,13 +517,13 @@ typedef enum {
|
||||||
// NOTE: By default up to 8 color channels defined, but it can be more
|
// NOTE: By default up to 8 color channels defined, but it can be more
|
||||||
typedef enum {
|
typedef enum {
|
||||||
RL_ATTACHMENT_COLOR_CHANNEL0 = 0, // Framebuffer attachment type: color 0
|
RL_ATTACHMENT_COLOR_CHANNEL0 = 0, // Framebuffer attachment type: color 0
|
||||||
RL_ATTACHMENT_COLOR_CHANNEL1, // Framebuffer attachment type: color 1
|
RL_ATTACHMENT_COLOR_CHANNEL1 = 1, // Framebuffer attachment type: color 1
|
||||||
RL_ATTACHMENT_COLOR_CHANNEL2, // Framebuffer attachment type: color 2
|
RL_ATTACHMENT_COLOR_CHANNEL2 = 2, // Framebuffer attachment type: color 2
|
||||||
RL_ATTACHMENT_COLOR_CHANNEL3, // Framebuffer attachment type: color 3
|
RL_ATTACHMENT_COLOR_CHANNEL3 = 3, // Framebuffer attachment type: color 3
|
||||||
RL_ATTACHMENT_COLOR_CHANNEL4, // Framebuffer attachment type: color 4
|
RL_ATTACHMENT_COLOR_CHANNEL4 = 4, // Framebuffer attachment type: color 4
|
||||||
RL_ATTACHMENT_COLOR_CHANNEL5, // Framebuffer attachment type: color 5
|
RL_ATTACHMENT_COLOR_CHANNEL5 = 5, // Framebuffer attachment type: color 5
|
||||||
RL_ATTACHMENT_COLOR_CHANNEL6, // Framebuffer attachment type: color 6
|
RL_ATTACHMENT_COLOR_CHANNEL6 = 6, // Framebuffer attachment type: color 6
|
||||||
RL_ATTACHMENT_COLOR_CHANNEL7, // Framebuffer attachment type: color 7
|
RL_ATTACHMENT_COLOR_CHANNEL7 = 7, // Framebuffer attachment type: color 7
|
||||||
RL_ATTACHMENT_DEPTH = 100, // Framebuffer attachment type: depth
|
RL_ATTACHMENT_DEPTH = 100, // Framebuffer attachment type: depth
|
||||||
RL_ATTACHMENT_STENCIL = 200, // Framebuffer attachment type: stencil
|
RL_ATTACHMENT_STENCIL = 200, // Framebuffer attachment type: stencil
|
||||||
} rlFramebufferAttachType;
|
} rlFramebufferAttachType;
|
||||||
|
@ -521,11 +531,11 @@ typedef enum {
|
||||||
// Framebuffer texture attachment type
|
// Framebuffer texture attachment type
|
||||||
typedef enum {
|
typedef enum {
|
||||||
RL_ATTACHMENT_CUBEMAP_POSITIVE_X = 0, // Framebuffer texture attachment type: cubemap, +X side
|
RL_ATTACHMENT_CUBEMAP_POSITIVE_X = 0, // Framebuffer texture attachment type: cubemap, +X side
|
||||||
RL_ATTACHMENT_CUBEMAP_NEGATIVE_X, // Framebuffer texture attachment type: cubemap, -X side
|
RL_ATTACHMENT_CUBEMAP_NEGATIVE_X = 1, // Framebuffer texture attachment type: cubemap, -X side
|
||||||
RL_ATTACHMENT_CUBEMAP_POSITIVE_Y, // Framebuffer texture attachment type: cubemap, +Y side
|
RL_ATTACHMENT_CUBEMAP_POSITIVE_Y = 2, // Framebuffer texture attachment type: cubemap, +Y side
|
||||||
RL_ATTACHMENT_CUBEMAP_NEGATIVE_Y, // Framebuffer texture attachment type: cubemap, -Y side
|
RL_ATTACHMENT_CUBEMAP_NEGATIVE_Y = 3, // Framebuffer texture attachment type: cubemap, -Y side
|
||||||
RL_ATTACHMENT_CUBEMAP_POSITIVE_Z, // Framebuffer texture attachment type: cubemap, +Z side
|
RL_ATTACHMENT_CUBEMAP_POSITIVE_Z = 4, // Framebuffer texture attachment type: cubemap, +Z side
|
||||||
RL_ATTACHMENT_CUBEMAP_NEGATIVE_Z, // Framebuffer texture attachment type: cubemap, -Z side
|
RL_ATTACHMENT_CUBEMAP_NEGATIVE_Z = 5, // Framebuffer texture attachment type: cubemap, -Z side
|
||||||
RL_ATTACHMENT_TEXTURE2D = 100, // Framebuffer texture attachment type: texture2d
|
RL_ATTACHMENT_TEXTURE2D = 100, // Framebuffer texture attachment type: texture2d
|
||||||
RL_ATTACHMENT_RENDERBUFFER = 200, // Framebuffer texture attachment type: renderbuffer
|
RL_ATTACHMENT_RENDERBUFFER = 200, // Framebuffer texture attachment type: renderbuffer
|
||||||
} rlFramebufferAttachTextureType;
|
} rlFramebufferAttachTextureType;
|
||||||
|
@ -607,6 +617,7 @@ RLAPI void rlDisableShader(void); // Disable shader progra
|
||||||
RLAPI void rlEnableFramebuffer(unsigned int id); // Enable render texture (fbo)
|
RLAPI void rlEnableFramebuffer(unsigned int id); // Enable render texture (fbo)
|
||||||
RLAPI void rlDisableFramebuffer(void); // Disable render texture (fbo), return to default framebuffer
|
RLAPI void rlDisableFramebuffer(void); // Disable render texture (fbo), return to default framebuffer
|
||||||
RLAPI void rlActiveDrawBuffers(int count); // Activate multiple draw color buffers
|
RLAPI void rlActiveDrawBuffers(int count); // Activate multiple draw color buffers
|
||||||
|
RLAPI void rlBlitFramebuffer(int srcX, int srcY, int srcWidth, int srcHeight, int dstX, int dstY, int dstWidth, int dstHeight, int bufferMask); // Blit active framebuffer to main framebuffer
|
||||||
|
|
||||||
// General render state
|
// General render state
|
||||||
RLAPI void rlEnableColorBlend(void); // Enable color blending
|
RLAPI void rlEnableColorBlend(void); // Enable color blending
|
||||||
|
@ -622,7 +633,8 @@ RLAPI void rlEnableScissorTest(void); // Enable scissor test
|
||||||
RLAPI void rlDisableScissorTest(void); // Disable scissor test
|
RLAPI void rlDisableScissorTest(void); // Disable scissor test
|
||||||
RLAPI void rlScissor(int x, int y, int width, int height); // Scissor test
|
RLAPI void rlScissor(int x, int y, int width, int height); // Scissor test
|
||||||
RLAPI void rlEnableWireMode(void); // Enable wire mode
|
RLAPI void rlEnableWireMode(void); // Enable wire mode
|
||||||
RLAPI void rlDisableWireMode(void); // Disable wire mode
|
RLAPI void rlEnablePointMode(void); // Enable point mode
|
||||||
|
RLAPI void rlDisableWireMode(void); // Disable wire mode ( and point ) maybe rename
|
||||||
RLAPI void rlSetLineWidth(float width); // Set the line drawing width
|
RLAPI void rlSetLineWidth(float width); // Set the line drawing width
|
||||||
RLAPI float rlGetLineWidth(void); // Get the line drawing width
|
RLAPI float rlGetLineWidth(void); // Get the line drawing width
|
||||||
RLAPI void rlEnableSmoothLines(void); // Enable line aliasing
|
RLAPI void rlEnableSmoothLines(void); // Enable line aliasing
|
||||||
|
@ -790,10 +802,14 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
|
||||||
#include "external/glad.h" // GLAD extensions loading library, includes OpenGL headers
|
#include "external/glad.h" // GLAD extensions loading library, includes OpenGL headers
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_ES3)
|
||||||
|
#include <GLES3/gl3.h> // OpenGL ES 3.0 library
|
||||||
|
#define GL_GLEXT_PROTOTYPES
|
||||||
|
#include <GLES2/gl2ext.h> // OpenGL ES 2.0 extensions library
|
||||||
|
#elif defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
// NOTE: OpenGL ES 2.0 can be enabled on PLATFORM_DESKTOP,
|
// NOTE: OpenGL ES 2.0 can be enabled on PLATFORM_DESKTOP,
|
||||||
// in that case, functions are loaded from a custom glad for OpenGL ES 2.0
|
// in that case, functions are loaded from a custom glad for OpenGL ES 2.0
|
||||||
#if defined(PLATFORM_DESKTOP)
|
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_DESKTOP_SDL)
|
||||||
#define GLAD_GLES2_IMPLEMENTATION
|
#define GLAD_GLES2_IMPLEMENTATION
|
||||||
#include "external/glad_gles2.h"
|
#include "external/glad_gles2.h"
|
||||||
#else
|
#else
|
||||||
|
@ -805,7 +821,7 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
|
||||||
|
|
||||||
// It seems OpenGL ES 2.0 instancing entry points are not defined on Raspberry Pi
|
// It seems OpenGL ES 2.0 instancing entry points are not defined on Raspberry Pi
|
||||||
// provided headers (despite being defined in official Khronos GLES2 headers)
|
// provided headers (despite being defined in official Khronos GLES2 headers)
|
||||||
#if defined(PLATFORM_RPI) || defined(PLATFORM_DRM)
|
#if defined(PLATFORM_DRM)
|
||||||
typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount);
|
typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount);
|
||||||
typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
|
typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
|
||||||
typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISOREXTPROC) (GLuint index, GLuint divisor);
|
typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISOREXTPROC) (GLuint index, GLuint divisor);
|
||||||
|
@ -887,8 +903,10 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
#define glClearDepth glClearDepthf
|
#define glClearDepth glClearDepthf
|
||||||
|
#if !defined(GRAPHICS_API_OPENGL_ES3)
|
||||||
#define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER
|
#define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER
|
||||||
#define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER
|
#define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Default shader vertex attribute names to set location points
|
// Default shader vertex attribute names to set location points
|
||||||
|
@ -999,6 +1017,7 @@ typedef struct rlglData {
|
||||||
bool texDepth; // Depth textures supported (GL_ARB_depth_texture, GL_OES_depth_texture)
|
bool texDepth; // Depth textures supported (GL_ARB_depth_texture, GL_OES_depth_texture)
|
||||||
bool texDepthWebGL; // Depth textures supported WebGL specific (GL_WEBGL_depth_texture)
|
bool texDepthWebGL; // Depth textures supported WebGL specific (GL_WEBGL_depth_texture)
|
||||||
bool texFloat32; // float textures support (32 bit per channel) (GL_OES_texture_float)
|
bool texFloat32; // float textures support (32 bit per channel) (GL_OES_texture_float)
|
||||||
|
bool texFloat16; // half float textures support (16 bit per channel) (GL_OES_texture_half_float)
|
||||||
bool texCompDXT; // DDS texture compression support (GL_EXT_texture_compression_s3tc, GL_WEBGL_compressed_texture_s3tc, GL_WEBKIT_WEBGL_compressed_texture_s3tc)
|
bool texCompDXT; // DDS texture compression support (GL_EXT_texture_compression_s3tc, GL_WEBGL_compressed_texture_s3tc, GL_WEBKIT_WEBGL_compressed_texture_s3tc)
|
||||||
bool texCompETC1; // ETC1 texture compression support (GL_OES_compressed_ETC1_RGB8_texture, GL_WEBGL_compressed_texture_etc1)
|
bool texCompETC1; // ETC1 texture compression support (GL_OES_compressed_ETC1_RGB8_texture, GL_WEBGL_compressed_texture_etc1)
|
||||||
bool texCompETC2; // ETC2/EAC texture compression support (GL_ARB_ES3_compatibility)
|
bool texCompETC2; // ETC2/EAC texture compression support (GL_ARB_ES3_compatibility)
|
||||||
|
@ -1026,7 +1045,7 @@ typedef void *(*rlglLoadProc)(const char *name); // OpenGL extension functions
|
||||||
static rlglData RLGL = { 0 };
|
static rlglData RLGL = { 0 };
|
||||||
#endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
|
#endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_ES2) && !defined(GRAPHICS_API_OPENGL_ES3)
|
||||||
// NOTE: VAO functionality is exposed through extensions (OES)
|
// NOTE: VAO functionality is exposed through extensions (OES)
|
||||||
static PFNGLGENVERTEXARRAYSOESPROC glGenVertexArrays = NULL;
|
static PFNGLGENVERTEXARRAYSOESPROC glGenVertexArrays = NULL;
|
||||||
static PFNGLBINDVERTEXARRAYOESPROC glBindVertexArray = NULL;
|
static PFNGLBINDVERTEXARRAYOESPROC glBindVertexArray = NULL;
|
||||||
|
@ -1416,8 +1435,7 @@ void rlVertex3f(float x, float y, float z)
|
||||||
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].texcoords[2*RLGL.State.vertexCounter] = RLGL.State.texcoordx;
|
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].texcoords[2*RLGL.State.vertexCounter] = RLGL.State.texcoordx;
|
||||||
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].texcoords[2*RLGL.State.vertexCounter + 1] = RLGL.State.texcoordy;
|
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].texcoords[2*RLGL.State.vertexCounter + 1] = RLGL.State.texcoordy;
|
||||||
|
|
||||||
// TODO: Add current normal
|
// WARNING: By default rlVertexBuffer struct does not store normals
|
||||||
// By default rlVertexBuffer type does not store normals
|
|
||||||
|
|
||||||
// Add current color
|
// Add current color
|
||||||
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.State.vertexCounter] = RLGL.State.colorr;
|
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.State.vertexCounter] = RLGL.State.colorr;
|
||||||
|
@ -1702,11 +1720,19 @@ void rlDisableFramebuffer(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Blit active framebuffer to main framebuffer
|
||||||
|
void rlBlitFramebuffer(int srcX, int srcY, int srcWidth, int srcHeight, int dstX, int dstY, int dstWidth, int dstHeight, int bufferMask)
|
||||||
|
{
|
||||||
|
#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES3)) && defined(RLGL_RENDER_TEXTURES_HINT)
|
||||||
|
glBlitFramebuffer(srcX, srcY, srcWidth, srcHeight, dstX, dstY, dstWidth, dstHeight, bufferMask, GL_NEAREST);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// Activate multiple draw color buffers
|
// Activate multiple draw color buffers
|
||||||
// NOTE: One color buffer is always active by default
|
// NOTE: One color buffer is always active by default
|
||||||
void rlActiveDrawBuffers(int count)
|
void rlActiveDrawBuffers(int count)
|
||||||
{
|
{
|
||||||
#if (defined(GRAPHICS_API_OPENGL_33) && defined(RLGL_RENDER_TEXTURES_HINT))
|
#if ((defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES3)) && defined(RLGL_RENDER_TEXTURES_HINT))
|
||||||
// NOTE: Maximum number of draw buffers supported is implementation dependant,
|
// NOTE: Maximum number of draw buffers supported is implementation dependant,
|
||||||
// it can be queried with glGet*() but it must be at least 8
|
// it can be queried with glGet*() but it must be at least 8
|
||||||
//GLint maxDrawBuffers = 0;
|
//GLint maxDrawBuffers = 0;
|
||||||
|
@ -1718,6 +1744,16 @@ void rlActiveDrawBuffers(int count)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned int buffers[8] = {
|
unsigned int buffers[8] = {
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_ES3)
|
||||||
|
GL_COLOR_ATTACHMENT0_EXT,
|
||||||
|
GL_COLOR_ATTACHMENT1_EXT,
|
||||||
|
GL_COLOR_ATTACHMENT2_EXT,
|
||||||
|
GL_COLOR_ATTACHMENT3_EXT,
|
||||||
|
GL_COLOR_ATTACHMENT4_EXT,
|
||||||
|
GL_COLOR_ATTACHMENT5_EXT,
|
||||||
|
GL_COLOR_ATTACHMENT6_EXT,
|
||||||
|
GL_COLOR_ATTACHMENT7_EXT,
|
||||||
|
#else
|
||||||
GL_COLOR_ATTACHMENT0,
|
GL_COLOR_ATTACHMENT0,
|
||||||
GL_COLOR_ATTACHMENT1,
|
GL_COLOR_ATTACHMENT1,
|
||||||
GL_COLOR_ATTACHMENT2,
|
GL_COLOR_ATTACHMENT2,
|
||||||
|
@ -1726,9 +1762,14 @@ void rlActiveDrawBuffers(int count)
|
||||||
GL_COLOR_ATTACHMENT5,
|
GL_COLOR_ATTACHMENT5,
|
||||||
GL_COLOR_ATTACHMENT6,
|
GL_COLOR_ATTACHMENT6,
|
||||||
GL_COLOR_ATTACHMENT7,
|
GL_COLOR_ATTACHMENT7,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_ES3)
|
||||||
|
glDrawBuffersEXT(count, buffers);
|
||||||
|
#else
|
||||||
glDrawBuffers(count, buffers);
|
glDrawBuffers(count, buffers);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else TRACELOG(LOG_WARNING, "GL: One color buffer active by default");
|
else TRACELOG(LOG_WARNING, "GL: One color buffer active by default");
|
||||||
|
@ -1792,6 +1833,14 @@ void rlEnableWireMode(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rlEnablePointMode(void)
|
||||||
|
{
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
|
||||||
|
// NOTE: glPolygonMode() not available on OpenGL ES
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
|
||||||
|
glEnable(GL_PROGRAM_POINT_SIZE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
// Disable wire mode
|
// Disable wire mode
|
||||||
void rlDisableWireMode(void)
|
void rlDisableWireMode(void)
|
||||||
{
|
{
|
||||||
|
@ -2047,7 +2096,7 @@ void rlglInit(int width, int height)
|
||||||
if ((glDebugMessageCallback != NULL) && (glDebugMessageControl != NULL))
|
if ((glDebugMessageCallback != NULL) && (glDebugMessageControl != NULL))
|
||||||
{
|
{
|
||||||
glDebugMessageCallback(rlDebugMessageCallback, 0);
|
glDebugMessageCallback(rlDebugMessageCallback, 0);
|
||||||
// glDebugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DEBUG_SEVERITY_HIGH, 0, 0, GL_TRUE); // TODO: Filter message
|
// glDebugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DEBUG_SEVERITY_HIGH, 0, 0, GL_TRUE);
|
||||||
|
|
||||||
// Debug context options:
|
// Debug context options:
|
||||||
// - GL_DEBUG_OUTPUT - Faster version but not useful for breakpoints
|
// - GL_DEBUG_OUTPUT - Faster version but not useful for breakpoints
|
||||||
|
@ -2168,6 +2217,7 @@ void rlLoadExtensions(void *loader)
|
||||||
RLGL.ExtSupported.instancing = (GLAD_GL_EXT_draw_instanced && GLAD_GL_ARB_instanced_arrays);
|
RLGL.ExtSupported.instancing = (GLAD_GL_EXT_draw_instanced && GLAD_GL_ARB_instanced_arrays);
|
||||||
RLGL.ExtSupported.texNPOT = GLAD_GL_ARB_texture_non_power_of_two;
|
RLGL.ExtSupported.texNPOT = GLAD_GL_ARB_texture_non_power_of_two;
|
||||||
RLGL.ExtSupported.texFloat32 = GLAD_GL_ARB_texture_float;
|
RLGL.ExtSupported.texFloat32 = GLAD_GL_ARB_texture_float;
|
||||||
|
RLGL.ExtSupported.texFloat16 = GLAD_GL_ARB_texture_float;
|
||||||
RLGL.ExtSupported.texDepth = GLAD_GL_ARB_depth_texture;
|
RLGL.ExtSupported.texDepth = GLAD_GL_ARB_depth_texture;
|
||||||
RLGL.ExtSupported.maxDepthBits = 32;
|
RLGL.ExtSupported.maxDepthBits = 32;
|
||||||
RLGL.ExtSupported.texAnisoFilter = GLAD_GL_EXT_texture_filter_anisotropic;
|
RLGL.ExtSupported.texAnisoFilter = GLAD_GL_EXT_texture_filter_anisotropic;
|
||||||
|
@ -2179,6 +2229,7 @@ void rlLoadExtensions(void *loader)
|
||||||
RLGL.ExtSupported.instancing = true;
|
RLGL.ExtSupported.instancing = true;
|
||||||
RLGL.ExtSupported.texNPOT = true;
|
RLGL.ExtSupported.texNPOT = true;
|
||||||
RLGL.ExtSupported.texFloat32 = true;
|
RLGL.ExtSupported.texFloat32 = true;
|
||||||
|
RLGL.ExtSupported.texFloat16 = true;
|
||||||
RLGL.ExtSupported.texDepth = true;
|
RLGL.ExtSupported.texDepth = true;
|
||||||
RLGL.ExtSupported.maxDepthBits = 32;
|
RLGL.ExtSupported.maxDepthBits = 32;
|
||||||
RLGL.ExtSupported.texAnisoFilter = true;
|
RLGL.ExtSupported.texAnisoFilter = true;
|
||||||
|
@ -2196,11 +2247,35 @@ void rlLoadExtensions(void *loader)
|
||||||
|
|
||||||
#endif // GRAPHICS_API_OPENGL_33
|
#endif // GRAPHICS_API_OPENGL_33
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_ES3)
|
||||||
|
// Register supported extensions flags
|
||||||
|
// OpenGL ES 3.0 extensions supported by default (or it should be)
|
||||||
|
RLGL.ExtSupported.vao = true;
|
||||||
|
RLGL.ExtSupported.instancing = true;
|
||||||
|
RLGL.ExtSupported.texNPOT = true;
|
||||||
|
RLGL.ExtSupported.texFloat32 = true;
|
||||||
|
RLGL.ExtSupported.texFloat16 = true;
|
||||||
|
RLGL.ExtSupported.texDepth = true;
|
||||||
|
RLGL.ExtSupported.texDepthWebGL = true;
|
||||||
|
RLGL.ExtSupported.maxDepthBits = 24;
|
||||||
|
RLGL.ExtSupported.texAnisoFilter = true;
|
||||||
|
RLGL.ExtSupported.texMirrorClamp = true;
|
||||||
|
// TODO: Check for additional OpenGL ES 3.0 supported extensions:
|
||||||
|
//RLGL.ExtSupported.texCompDXT = true;
|
||||||
|
//RLGL.ExtSupported.texCompETC1 = true;
|
||||||
|
//RLGL.ExtSupported.texCompETC2 = true;
|
||||||
|
//RLGL.ExtSupported.texCompPVRT = true;
|
||||||
|
//RLGL.ExtSupported.texCompASTC = true;
|
||||||
|
//RLGL.ExtSupported.maxAnisotropyLevel = true;
|
||||||
|
//RLGL.ExtSupported.computeShader = true;
|
||||||
|
//RLGL.ExtSupported.ssbo = true;
|
||||||
|
|
||||||
#if defined(PLATFORM_DESKTOP)
|
#elif defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
|
|
||||||
|
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_DESKTOP_SDL)
|
||||||
|
// TODO: Support GLAD loader for OpenGL ES 3.0
|
||||||
if (gladLoadGLES2((GLADloadfunc)loader) == 0) TRACELOG(RL_LOG_WARNING, "GLAD: Cannot load OpenGL ES2.0 functions");
|
if (gladLoadGLES2((GLADloadfunc)loader) == 0) TRACELOG(RL_LOG_WARNING, "GLAD: Cannot load OpenGL ES2.0 functions");
|
||||||
else TRACELOG(RL_LOG_INFO, "GLAD: OpenGL ES2.0 loaded successfully");
|
else TRACELOG(RL_LOG_INFO, "GLAD: OpenGL ES 2.0 loaded successfully");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Get supported extensions list
|
// Get supported extensions list
|
||||||
|
@ -2276,6 +2351,7 @@ void rlLoadExtensions(void *loader)
|
||||||
|
|
||||||
// Check texture float support
|
// Check texture float support
|
||||||
if (strcmp(extList[i], (const char *)"GL_OES_texture_float") == 0) RLGL.ExtSupported.texFloat32 = true;
|
if (strcmp(extList[i], (const char *)"GL_OES_texture_float") == 0) RLGL.ExtSupported.texFloat32 = true;
|
||||||
|
if (strcmp(extList[i], (const char *)"GL_OES_texture_half_float") == 0) RLGL.ExtSupported.texFloat16 = true;
|
||||||
|
|
||||||
// Check depth texture support
|
// Check depth texture support
|
||||||
if (strcmp(extList[i], (const char *)"GL_OES_depth_texture") == 0) RLGL.ExtSupported.texDepth = true;
|
if (strcmp(extList[i], (const char *)"GL_OES_depth_texture") == 0) RLGL.ExtSupported.texDepth = true;
|
||||||
|
@ -2391,15 +2467,17 @@ int rlGetVersion(void)
|
||||||
#endif
|
#endif
|
||||||
#if defined(GRAPHICS_API_OPENGL_21)
|
#if defined(GRAPHICS_API_OPENGL_21)
|
||||||
glVersion = RL_OPENGL_21;
|
glVersion = RL_OPENGL_21;
|
||||||
|
#elif defined(GRAPHICS_API_OPENGL_43)
|
||||||
|
glVersion = RL_OPENGL_43;
|
||||||
#elif defined(GRAPHICS_API_OPENGL_33)
|
#elif defined(GRAPHICS_API_OPENGL_33)
|
||||||
glVersion = RL_OPENGL_33;
|
glVersion = RL_OPENGL_33;
|
||||||
#endif
|
#endif
|
||||||
#if defined(GRAPHICS_API_OPENGL_43)
|
#if defined(GRAPHICS_API_OPENGL_ES3)
|
||||||
glVersion = RL_OPENGL_43;
|
glVersion = RL_OPENGL_ES_30;
|
||||||
#endif
|
#elif defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
#if defined(GRAPHICS_API_OPENGL_ES2)
|
|
||||||
glVersion = RL_OPENGL_ES_20;
|
glVersion = RL_OPENGL_ES_20;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return glVersion;
|
return glVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2648,7 +2726,7 @@ void rlDrawRenderBatch(rlRenderBatch *batch)
|
||||||
// Update batch vertex buffers
|
// Update batch vertex buffers
|
||||||
//------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------
|
||||||
// NOTE: If there is not vertex data, buffers doesn't need to be updated (vertexCount > 0)
|
// NOTE: If there is not vertex data, buffers doesn't need to be updated (vertexCount > 0)
|
||||||
// TODO: If no data changed on the CPU arrays --> No need to re-update GPU arrays (change flag required)
|
// TODO: If no data changed on the CPU arrays --> No need to re-update GPU arrays (use a change detector flag?)
|
||||||
if (RLGL.State.vertexCounter > 0)
|
if (RLGL.State.vertexCounter > 0)
|
||||||
{
|
{
|
||||||
// Activate elements VAO
|
// Activate elements VAO
|
||||||
|
@ -2943,7 +3021,11 @@ unsigned int rlLoadTexture(const void *data, int width, int height, int format,
|
||||||
|
|
||||||
int mipWidth = width;
|
int mipWidth = width;
|
||||||
int mipHeight = height;
|
int mipHeight = height;
|
||||||
int mipOffset = 0; // Mipmap data offset
|
int mipOffset = 0; // Mipmap data offset, only used for tracelog
|
||||||
|
|
||||||
|
// NOTE: Added pointer math separately from function to avoid UBSAN complaining
|
||||||
|
unsigned char *dataPtr = NULL;
|
||||||
|
if (data != NULL) dataPtr = (unsigned char *)data;
|
||||||
|
|
||||||
// Load the different mipmap levels
|
// Load the different mipmap levels
|
||||||
for (int i = 0; i < mipmapCount; i++)
|
for (int i = 0; i < mipmapCount; i++)
|
||||||
|
@ -2955,11 +3037,11 @@ unsigned int rlLoadTexture(const void *data, int width, int height, int format,
|
||||||
|
|
||||||
TRACELOGD("TEXTURE: Load mipmap level %i (%i x %i), size: %i, offset: %i", i, mipWidth, mipHeight, mipSize, mipOffset);
|
TRACELOGD("TEXTURE: Load mipmap level %i (%i x %i), size: %i, offset: %i", i, mipWidth, mipHeight, mipSize, mipOffset);
|
||||||
|
|
||||||
if (glInternalFormat != -1)
|
if (glInternalFormat != 0)
|
||||||
{
|
{
|
||||||
if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) glTexImage2D(GL_TEXTURE_2D, i, glInternalFormat, mipWidth, mipHeight, 0, glFormat, glType, (unsigned char *)data + mipOffset);
|
if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) glTexImage2D(GL_TEXTURE_2D, i, glInternalFormat, mipWidth, mipHeight, 0, glFormat, glType, dataPtr);
|
||||||
#if !defined(GRAPHICS_API_OPENGL_11)
|
#if !defined(GRAPHICS_API_OPENGL_11)
|
||||||
else glCompressedTexImage2D(GL_TEXTURE_2D, i, glInternalFormat, mipWidth, mipHeight, 0, mipSize, (unsigned char *)data + mipOffset);
|
else glCompressedTexImage2D(GL_TEXTURE_2D, i, glInternalFormat, mipWidth, mipHeight, 0, mipSize, dataPtr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_33)
|
#if defined(GRAPHICS_API_OPENGL_33)
|
||||||
|
@ -2982,7 +3064,8 @@ unsigned int rlLoadTexture(const void *data, int width, int height, int format,
|
||||||
|
|
||||||
mipWidth /= 2;
|
mipWidth /= 2;
|
||||||
mipHeight /= 2;
|
mipHeight /= 2;
|
||||||
mipOffset += mipSize;
|
mipOffset += mipSize; // Increment offset position to next mipmap
|
||||||
|
if (data != NULL) dataPtr += mipSize; // Increment data pointer to next mipmap
|
||||||
|
|
||||||
// Security check for NPOT textures
|
// Security check for NPOT textures
|
||||||
if (mipWidth < 1) mipWidth = 1;
|
if (mipWidth < 1) mipWidth = 1;
|
||||||
|
@ -3049,7 +3132,7 @@ unsigned int rlLoadTextureDepth(int width, int height, bool useRenderBuffer)
|
||||||
// Possible formats: GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT32 and GL_DEPTH_COMPONENT32F
|
// Possible formats: GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT32 and GL_DEPTH_COMPONENT32F
|
||||||
unsigned int glInternalFormat = GL_DEPTH_COMPONENT;
|
unsigned int glInternalFormat = GL_DEPTH_COMPONENT;
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_ES2)
|
#if (defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_ES3))
|
||||||
// WARNING: WebGL platform requires unsized internal format definition (GL_DEPTH_COMPONENT)
|
// WARNING: WebGL platform requires unsized internal format definition (GL_DEPTH_COMPONENT)
|
||||||
// while other platforms using OpenGL ES 2.0 require/support sized internal formats depending on the GPU capabilities
|
// while other platforms using OpenGL ES 2.0 require/support sized internal formats depending on the GPU capabilities
|
||||||
if (!RLGL.ExtSupported.texDepthWebGL || useRenderBuffer)
|
if (!RLGL.ExtSupported.texDepthWebGL || useRenderBuffer)
|
||||||
|
@ -3108,7 +3191,7 @@ unsigned int rlLoadTextureCubemap(const void *data, int size, int format)
|
||||||
unsigned int glInternalFormat, glFormat, glType;
|
unsigned int glInternalFormat, glFormat, glType;
|
||||||
rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType);
|
rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType);
|
||||||
|
|
||||||
if (glInternalFormat != -1)
|
if (glInternalFormat != 0)
|
||||||
{
|
{
|
||||||
// Load cubemap faces
|
// Load cubemap faces
|
||||||
for (unsigned int i = 0; i < 6; i++)
|
for (unsigned int i = 0; i < 6; i++)
|
||||||
|
@ -3117,13 +3200,9 @@ unsigned int rlLoadTextureCubemap(const void *data, int size, int format)
|
||||||
{
|
{
|
||||||
if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB)
|
if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB)
|
||||||
{
|
{
|
||||||
if (format == RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32)
|
if ((format == RL_PIXELFORMAT_UNCOMPRESSED_R32) || (format == RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32)
|
||||||
{
|
|| (format == RL_PIXELFORMAT_UNCOMPRESSED_R16) || (format == RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16))
|
||||||
// Instead of using a sized internal texture format (GL_RGB16F, GL_RGB32F), we let the driver to choose the better format for us (GL_RGB)
|
TRACELOG(RL_LOG_WARNING, "TEXTURES: Cubemap requested format not supported");
|
||||||
if (RLGL.ExtSupported.texFloat32) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, size, size, 0, GL_RGB, GL_FLOAT, NULL);
|
|
||||||
else TRACELOG(RL_LOG_WARNING, "TEXTURES: Cubemap requested format not supported");
|
|
||||||
}
|
|
||||||
else if ((format == RL_PIXELFORMAT_UNCOMPRESSED_R32) || (format == RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32)) TRACELOG(RL_LOG_WARNING, "TEXTURES: Cubemap requested format not supported");
|
|
||||||
else glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, size, size, 0, glFormat, glType, NULL);
|
else glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, size, size, 0, glFormat, glType, NULL);
|
||||||
}
|
}
|
||||||
else TRACELOG(RL_LOG_WARNING, "TEXTURES: Empty cubemap creation does not support compressed format");
|
else TRACELOG(RL_LOG_WARNING, "TEXTURES: Empty cubemap creation does not support compressed format");
|
||||||
|
@ -3180,7 +3259,7 @@ void rlUpdateTexture(unsigned int id, int offsetX, int offsetY, int width, int h
|
||||||
unsigned int glInternalFormat, glFormat, glType;
|
unsigned int glInternalFormat, glFormat, glType;
|
||||||
rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType);
|
rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType);
|
||||||
|
|
||||||
if ((glInternalFormat != -1) && (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB))
|
if ((glInternalFormat != 0) && (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB))
|
||||||
{
|
{
|
||||||
glTexSubImage2D(GL_TEXTURE_2D, 0, offsetX, offsetY, width, height, glFormat, glType, data);
|
glTexSubImage2D(GL_TEXTURE_2D, 0, offsetX, offsetY, width, height, glFormat, glType, data);
|
||||||
}
|
}
|
||||||
|
@ -3206,9 +3285,27 @@ void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned
|
||||||
case RL_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_4_4_4_4; break;
|
case RL_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_4_4_4_4; break;
|
||||||
case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_BYTE; break;
|
case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_BYTE; break;
|
||||||
#if !defined(GRAPHICS_API_OPENGL_11)
|
#if !defined(GRAPHICS_API_OPENGL_11)
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_ES3)
|
||||||
|
case RL_PIXELFORMAT_UNCOMPRESSED_R32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_R32F_EXT; *glFormat = GL_RED_EXT; *glType = GL_FLOAT; break;
|
||||||
|
case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGB32F_EXT; *glFormat = GL_RGB; *glType = GL_FLOAT; break;
|
||||||
|
case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGBA32F_EXT; *glFormat = GL_RGBA; *glType = GL_FLOAT; break;
|
||||||
|
case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_R16F_EXT; *glFormat = GL_RED_EXT; *glType = GL_HALF_FLOAT; break;
|
||||||
|
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB16F_EXT; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT; break;
|
||||||
|
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA16F_EXT; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT; break;
|
||||||
|
#else
|
||||||
case RL_PIXELFORMAT_UNCOMPRESSED_R32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
|
case RL_PIXELFORMAT_UNCOMPRESSED_R32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
|
||||||
case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
|
case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
|
||||||
case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
|
case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_21)
|
||||||
|
case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_HALF_FLOAT_ARB; break;
|
||||||
|
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT_ARB; break;
|
||||||
|
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT_ARB; break;
|
||||||
|
#else // defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
|
case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
|
||||||
|
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
|
||||||
|
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#elif defined(GRAPHICS_API_OPENGL_33)
|
#elif defined(GRAPHICS_API_OPENGL_33)
|
||||||
case RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: *glInternalFormat = GL_R8; *glFormat = GL_RED; *glType = GL_UNSIGNED_BYTE; break;
|
case RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: *glInternalFormat = GL_R8; *glFormat = GL_RED; *glType = GL_UNSIGNED_BYTE; break;
|
||||||
|
@ -3221,6 +3318,9 @@ void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned
|
||||||
case RL_PIXELFORMAT_UNCOMPRESSED_R32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_R32F; *glFormat = GL_RED; *glType = GL_FLOAT; break;
|
case RL_PIXELFORMAT_UNCOMPRESSED_R32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_R32F; *glFormat = GL_RED; *glType = GL_FLOAT; break;
|
||||||
case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGB32F; *glFormat = GL_RGB; *glType = GL_FLOAT; break;
|
case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGB32F; *glFormat = GL_RGB; *glType = GL_FLOAT; break;
|
||||||
case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGBA32F; *glFormat = GL_RGBA; *glType = GL_FLOAT; break;
|
case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGBA32F; *glFormat = GL_RGBA; *glType = GL_FLOAT; break;
|
||||||
|
case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_R16F; *glFormat = GL_RED; *glType = GL_HALF_FLOAT; break;
|
||||||
|
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB16F; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT; break;
|
||||||
|
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA16F; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT; break;
|
||||||
#endif
|
#endif
|
||||||
#if !defined(GRAPHICS_API_OPENGL_11)
|
#if !defined(GRAPHICS_API_OPENGL_11)
|
||||||
case RL_PIXELFORMAT_COMPRESSED_DXT1_RGB: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; break;
|
case RL_PIXELFORMAT_COMPRESSED_DXT1_RGB: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; break;
|
||||||
|
@ -3303,7 +3403,7 @@ void *rlReadTexturePixels(unsigned int id, int width, int height, int format)
|
||||||
rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType);
|
rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType);
|
||||||
unsigned int size = rlGetPixelDataSize(width, height, format);
|
unsigned int size = rlGetPixelDataSize(width, height, format);
|
||||||
|
|
||||||
if ((glInternalFormat != -1) && (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB))
|
if ((glInternalFormat != 0) && (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB))
|
||||||
{
|
{
|
||||||
pixels = RL_MALLOC(size);
|
pixels = RL_MALLOC(size);
|
||||||
glGetTexImage(GL_TEXTURE_2D, 0, glFormat, glType, pixels);
|
glGetTexImage(GL_TEXTURE_2D, 0, glFormat, glType, pixels);
|
||||||
|
@ -3466,11 +3566,14 @@ bool rlFramebufferComplete(unsigned int id)
|
||||||
void rlUnloadFramebuffer(unsigned int id)
|
void rlUnloadFramebuffer(unsigned int id)
|
||||||
{
|
{
|
||||||
#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(RLGL_RENDER_TEXTURES_HINT)
|
#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(RLGL_RENDER_TEXTURES_HINT)
|
||||||
|
|
||||||
// Query depth attachment to automatically delete texture/renderbuffer
|
// Query depth attachment to automatically delete texture/renderbuffer
|
||||||
int depthType = 0, depthId = 0;
|
int depthType = 0, depthId = 0;
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, id); // Bind framebuffer to query depth texture type
|
glBindFramebuffer(GL_FRAMEBUFFER, id); // Bind framebuffer to query depth texture type
|
||||||
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &depthType);
|
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &depthType);
|
||||||
|
|
||||||
|
// TODO: Review warning retrieving object name in WebGL
|
||||||
|
// WARNING: WebGL: INVALID_ENUM: getFramebufferAttachmentParameter: invalid parameter name
|
||||||
|
// https://registry.khronos.org/webgl/specs/latest/1.0/
|
||||||
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &depthId);
|
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &depthId);
|
||||||
|
|
||||||
unsigned int depthIdU = (unsigned int)depthId;
|
unsigned int depthIdU = (unsigned int)depthId;
|
||||||
|
@ -3616,7 +3719,11 @@ void rlDrawVertexArray(int offset, int count)
|
||||||
// Draw vertex array elements
|
// Draw vertex array elements
|
||||||
void rlDrawVertexArrayElements(int offset, int count, const void *buffer)
|
void rlDrawVertexArrayElements(int offset, int count, const void *buffer)
|
||||||
{
|
{
|
||||||
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (const unsigned short *)buffer + offset);
|
// NOTE: Added pointer math separately from function to avoid UBSAN complaining
|
||||||
|
unsigned short *bufferPtr = (unsigned short *)buffer;
|
||||||
|
if (offset > 0) bufferPtr += offset;
|
||||||
|
|
||||||
|
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (const unsigned short *)bufferPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw vertex array instanced
|
// Draw vertex array instanced
|
||||||
|
@ -3631,7 +3738,11 @@ void rlDrawVertexArrayInstanced(int offset, int count, int instances)
|
||||||
void rlDrawVertexArrayElementsInstanced(int offset, int count, const void *buffer, int instances)
|
void rlDrawVertexArrayElementsInstanced(int offset, int count, const void *buffer, int instances)
|
||||||
{
|
{
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
glDrawElementsInstanced(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (const unsigned short *)buffer + offset, instances);
|
// NOTE: Added pointer math separately from function to avoid UBSAN complaining
|
||||||
|
unsigned short *bufferPtr = (unsigned short *)buffer;
|
||||||
|
if (offset > 0) bufferPtr += offset;
|
||||||
|
|
||||||
|
glDrawElementsInstanced(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (const unsigned short *)bufferPtr, instances);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3923,8 +4034,8 @@ int rlGetLocationUniform(unsigned int shaderId, const char *uniformName)
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
location = glGetUniformLocation(shaderId, uniformName);
|
location = glGetUniformLocation(shaderId, uniformName);
|
||||||
|
|
||||||
if (location == -1) TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to find shader uniform: %s", shaderId, uniformName);
|
//if (location == -1) TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to find shader uniform: %s", shaderId, uniformName);
|
||||||
else TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Shader uniform (%s) set at location: %i", shaderId, uniformName, location);
|
//else TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Shader uniform (%s) set at location: %i", shaderId, uniformName, location);
|
||||||
#endif
|
#endif
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
@ -3936,8 +4047,8 @@ int rlGetLocationAttrib(unsigned int shaderId, const char *attribName)
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
location = glGetAttribLocation(shaderId, attribName);
|
location = glGetAttribLocation(shaderId, attribName);
|
||||||
|
|
||||||
if (location == -1) TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to find shader attribute: %s", shaderId, attribName);
|
//if (location == -1) TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to find shader attribute: %s", shaderId, attribName);
|
||||||
else TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Shader attribute (%s) set at location: %i", shaderId, attribName, location);
|
//else TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Shader attribute (%s) set at location: %i", shaderId, attribName, location);
|
||||||
#endif
|
#endif
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
@ -4091,7 +4202,7 @@ unsigned int rlLoadShaderBuffer(unsigned int size, const void *data, int usageHi
|
||||||
glGenBuffers(1, &ssbo);
|
glGenBuffers(1, &ssbo);
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
|
||||||
glBufferData(GL_SHADER_STORAGE_BUFFER, size, data, usageHint? usageHint : RL_STREAM_COPY);
|
glBufferData(GL_SHADER_STORAGE_BUFFER, size, data, usageHint? usageHint : RL_STREAM_COPY);
|
||||||
glClearBufferData(GL_SHADER_STORAGE_BUFFER, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, 0);
|
if (data == NULL) glClearBufferData(GL_SHADER_STORAGE_BUFFER, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, NULL); // Clear buffer data to 0
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -4162,7 +4273,7 @@ void rlBindImageTexture(unsigned int id, unsigned int index, int format, bool re
|
||||||
unsigned int glInternalFormat = 0, glFormat = 0, glType = 0;
|
unsigned int glInternalFormat = 0, glFormat = 0, glType = 0;
|
||||||
|
|
||||||
rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType);
|
rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType);
|
||||||
glBindImageTexture(index, id, 0, 0, 0, readonly ? GL_READ_ONLY : GL_READ_WRITE, glInternalFormat);
|
glBindImageTexture(index, id, 0, 0, 0, readonly? GL_READ_ONLY : GL_READ_WRITE, glInternalFormat);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4428,6 +4539,9 @@ const char *rlGetPixelFormatName(unsigned int format)
|
||||||
case RL_PIXELFORMAT_UNCOMPRESSED_R32: return "R32"; break; // 32 bpp (1 channel - float)
|
case RL_PIXELFORMAT_UNCOMPRESSED_R32: return "R32"; break; // 32 bpp (1 channel - float)
|
||||||
case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: return "R32G32B32"; break; // 32*3 bpp (3 channels - float)
|
case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: return "R32G32B32"; break; // 32*3 bpp (3 channels - float)
|
||||||
case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: return "R32G32B32A32"; break; // 32*4 bpp (4 channels - float)
|
case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: return "R32G32B32A32"; break; // 32*4 bpp (4 channels - float)
|
||||||
|
case RL_PIXELFORMAT_UNCOMPRESSED_R16: return "R16"; break; // 16 bpp (1 channel - half float)
|
||||||
|
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: return "R16G16B16"; break; // 16*3 bpp (3 channels - half float)
|
||||||
|
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: return "R16G16B16A16"; break; // 16*4 bpp (4 channels - half float)
|
||||||
case RL_PIXELFORMAT_COMPRESSED_DXT1_RGB: return "DXT1_RGB"; break; // 4 bpp (no alpha)
|
case RL_PIXELFORMAT_COMPRESSED_DXT1_RGB: return "DXT1_RGB"; break; // 4 bpp (no alpha)
|
||||||
case RL_PIXELFORMAT_COMPRESSED_DXT1_RGBA: return "DXT1_RGBA"; break; // 4 bpp (1 bit alpha)
|
case RL_PIXELFORMAT_COMPRESSED_DXT1_RGBA: return "DXT1_RGBA"; break; // 4 bpp (1 bit alpha)
|
||||||
case RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA: return "DXT3_RGBA"; break; // 8 bpp
|
case RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA: return "DXT3_RGBA"; break; // 8 bpp
|
||||||
|
@ -4476,6 +4590,7 @@ static void rlLoadShaderDefault(void)
|
||||||
#endif
|
#endif
|
||||||
#if defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
"#version 100 \n"
|
"#version 100 \n"
|
||||||
|
"precision mediump float; \n" // Precision required for OpenGL ES2 (WebGL) (on some browsers)
|
||||||
"attribute vec3 vertexPosition; \n"
|
"attribute vec3 vertexPosition; \n"
|
||||||
"attribute vec2 vertexTexCoord; \n"
|
"attribute vec2 vertexTexCoord; \n"
|
||||||
"attribute vec4 vertexColor; \n"
|
"attribute vec4 vertexColor; \n"
|
||||||
|
@ -4669,6 +4784,9 @@ static int rlGetPixelDataSize(int width, int height, int format)
|
||||||
case RL_PIXELFORMAT_UNCOMPRESSED_R32: bpp = 32; break;
|
case RL_PIXELFORMAT_UNCOMPRESSED_R32: bpp = 32; break;
|
||||||
case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: bpp = 32*3; break;
|
case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: bpp = 32*3; break;
|
||||||
case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: bpp = 32*4; break;
|
case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: bpp = 32*4; break;
|
||||||
|
case RL_PIXELFORMAT_UNCOMPRESSED_R16: bpp = 16; break;
|
||||||
|
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: bpp = 16*3; break;
|
||||||
|
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: bpp = 16*4; break;
|
||||||
case RL_PIXELFORMAT_COMPRESSED_DXT1_RGB:
|
case RL_PIXELFORMAT_COMPRESSED_DXT1_RGB:
|
||||||
case RL_PIXELFORMAT_COMPRESSED_DXT1_RGBA:
|
case RL_PIXELFORMAT_COMPRESSED_DXT1_RGBA:
|
||||||
case RL_PIXELFORMAT_COMPRESSED_ETC1_RGB:
|
case RL_PIXELFORMAT_COMPRESSED_ETC1_RGB:
|
||||||
|
|
393
raylib/rmodels.c
393
raylib/rmodels.c
|
@ -3,7 +3,6 @@
|
||||||
* rmodels - Basic functions to draw 3d shapes and load and draw 3d models
|
* rmodels - Basic functions to draw 3d shapes and load and draw 3d models
|
||||||
*
|
*
|
||||||
* CONFIGURATION:
|
* CONFIGURATION:
|
||||||
*
|
|
||||||
* #define SUPPORT_MODULE_RMODELS
|
* #define SUPPORT_MODULE_RMODELS
|
||||||
* rmodels module is included in the build
|
* rmodels module is included in the build
|
||||||
*
|
*
|
||||||
|
@ -102,19 +101,18 @@
|
||||||
#define PAR_REALLOC(T, BUF, N) ((T*)RL_REALLOC(BUF, sizeof(T)*(N)))
|
#define PAR_REALLOC(T, BUF, N) ((T*)RL_REALLOC(BUF, sizeof(T)*(N)))
|
||||||
#define PAR_FREE RL_FREE
|
#define PAR_FREE RL_FREE
|
||||||
|
|
||||||
#if defined(_MSC_VER ) // par shapes has 2 warnings on windows, so disable them just fof this file
|
#if defined(_MSC_VER) // Disable some MSVC warning
|
||||||
#pragma warning( push )
|
#pragma warning(push)
|
||||||
#pragma warning( disable : 4244)
|
#pragma warning(disable : 4244)
|
||||||
#pragma warning( disable : 4305)
|
#pragma warning(disable : 4305)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PAR_SHAPES_IMPLEMENTATION
|
#define PAR_SHAPES_IMPLEMENTATION
|
||||||
#include "external/par_shapes.h" // Shapes 3d parametric generation
|
#include "external/par_shapes.h" // Shapes 3d parametric generation
|
||||||
|
|
||||||
#if defined(_MSC_VER ) // disable MSVC warning suppression for par shapes
|
#if defined(_MSC_VER)
|
||||||
#pragma warning( pop )
|
#pragma warning(pop) // Disable MSVC warning suppression
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
@ -153,18 +151,18 @@ static Model LoadOBJ(const char *fileName); // Load OBJ mesh data
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_IQM)
|
#if defined(SUPPORT_FILEFORMAT_IQM)
|
||||||
static Model LoadIQM(const char *fileName); // Load IQM mesh data
|
static Model LoadIQM(const char *fileName); // Load IQM mesh data
|
||||||
static ModelAnimation *LoadModelAnimationsIQM(const char *fileName, unsigned int *animCount); // Load IQM animation data
|
static ModelAnimation *LoadModelAnimationsIQM(const char *fileName, int *animCount); // Load IQM animation data
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_GLTF)
|
#if defined(SUPPORT_FILEFORMAT_GLTF)
|
||||||
static Model LoadGLTF(const char *fileName); // Load GLTF mesh data
|
static Model LoadGLTF(const char *fileName); // Load GLTF mesh data
|
||||||
static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, unsigned int *animCount); // Load GLTF animation data
|
static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCount); // Load GLTF animation data
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_VOX)
|
#if defined(SUPPORT_FILEFORMAT_VOX)
|
||||||
static Model LoadVOX(const char *filename); // Load VOX mesh data
|
static Model LoadVOX(const char *filename); // Load VOX mesh data
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_M3D)
|
#if defined(SUPPORT_FILEFORMAT_M3D)
|
||||||
static Model LoadM3D(const char *filename); // Load M3D mesh data
|
static Model LoadM3D(const char *filename); // Load M3D mesh data
|
||||||
static ModelAnimation *LoadModelAnimationsM3D(const char *fileName, unsigned int *animCount); // Load M3D animation data
|
static ModelAnimation *LoadModelAnimationsM3D(const char *fileName, int *animCount); // Load M3D animation data
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_OBJ) || defined(SUPPORT_FILEFORMAT_MTL)
|
#if defined(SUPPORT_FILEFORMAT_OBJ) || defined(SUPPORT_FILEFORMAT_MTL)
|
||||||
static void ProcessMaterialsOBJ(Material *rayMaterials, tinyobj_material_t *materials, int materialCount); // Process obj materials
|
static void ProcessMaterialsOBJ(Material *rayMaterials, tinyobj_material_t *materials, int materialCount); // Process obj materials
|
||||||
|
@ -1054,26 +1052,16 @@ Model LoadModel(const char *fileName)
|
||||||
// Make sure model transform is set to identity matrix!
|
// Make sure model transform is set to identity matrix!
|
||||||
model.transform = MatrixIdentity();
|
model.transform = MatrixIdentity();
|
||||||
|
|
||||||
if (model.meshCount == 0)
|
if ((model.meshCount != 0) && (model.meshes != NULL))
|
||||||
{
|
{
|
||||||
model.meshCount = 1;
|
// Upload vertex data to GPU (static meshes)
|
||||||
model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));
|
|
||||||
#if defined(SUPPORT_MESH_GENERATION)
|
|
||||||
TRACELOG(LOG_WARNING, "MESH: [%s] Failed to load mesh data, default to cube mesh", fileName);
|
|
||||||
model.meshes[0] = GenMeshCube(1.0f, 1.0f, 1.0f);
|
|
||||||
#else
|
|
||||||
TRACELOG(LOG_WARNING, "MESH: [%s] Failed to load mesh data", fileName);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Upload vertex data to GPU (static mesh)
|
|
||||||
for (int i = 0; i < model.meshCount; i++) UploadMesh(&model.meshes[i], false);
|
for (int i = 0; i < model.meshCount; i++) UploadMesh(&model.meshes[i], false);
|
||||||
}
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "MESH: [%s] Failed to load model mesh(es) data", fileName);
|
||||||
|
|
||||||
if (model.materialCount == 0)
|
if (model.materialCount == 0)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "MATERIAL: [%s] Failed to load material data, default to white material", fileName);
|
TRACELOG(LOG_WARNING, "MATERIAL: [%s] Failed to load model material data, default to white material", fileName);
|
||||||
|
|
||||||
model.materialCount = 1;
|
model.materialCount = 1;
|
||||||
model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));
|
model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));
|
||||||
|
@ -1173,6 +1161,12 @@ BoundingBox GetModelBoundingBox(Model model)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply model.transform to bounding box
|
||||||
|
// WARNING: Current BoundingBox structure design does not support rotation transformations,
|
||||||
|
// in those cases is up to the user to calculate the proper box bounds (8 vertices transformed)
|
||||||
|
bounds.min = Vector3Transform(bounds.min, model.transform);
|
||||||
|
bounds.max = Vector3Transform(bounds.max, model.transform);
|
||||||
|
|
||||||
return bounds;
|
return bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1204,7 +1198,7 @@ void UploadMesh(Mesh *mesh, bool dynamic)
|
||||||
// NOTE: Vertex attributes must be uploaded considering default locations points and available vertex data
|
// NOTE: Vertex attributes must be uploaded considering default locations points and available vertex data
|
||||||
|
|
||||||
// Enable vertex attributes: position (shader-location = 0)
|
// Enable vertex attributes: position (shader-location = 0)
|
||||||
void *vertices = mesh->animVertices != NULL ? mesh->animVertices : mesh->vertices;
|
void *vertices = (mesh->animVertices != NULL)? mesh->animVertices : mesh->vertices;
|
||||||
mesh->vboId[0] = rlLoadVertexBuffer(vertices, mesh->vertexCount*3*sizeof(float), dynamic);
|
mesh->vboId[0] = rlLoadVertexBuffer(vertices, mesh->vertexCount*3*sizeof(float), dynamic);
|
||||||
rlSetVertexAttribute(0, 3, RL_FLOAT, 0, 0, 0);
|
rlSetVertexAttribute(0, 3, RL_FLOAT, 0, 0, 0);
|
||||||
rlEnableVertexAttribute(0);
|
rlEnableVertexAttribute(0);
|
||||||
|
@ -1220,7 +1214,7 @@ void UploadMesh(Mesh *mesh, bool dynamic)
|
||||||
if (mesh->normals != NULL)
|
if (mesh->normals != NULL)
|
||||||
{
|
{
|
||||||
// Enable vertex attributes: normals (shader-location = 2)
|
// Enable vertex attributes: normals (shader-location = 2)
|
||||||
void *normals = mesh->animNormals != NULL ? mesh->animNormals : mesh->normals;
|
void *normals = (mesh->animNormals != NULL)? mesh->animNormals : mesh->normals;
|
||||||
mesh->vboId[2] = rlLoadVertexBuffer(normals, mesh->vertexCount*3*sizeof(float), dynamic);
|
mesh->vboId[2] = rlLoadVertexBuffer(normals, mesh->vertexCount*3*sizeof(float), dynamic);
|
||||||
rlSetVertexAttribute(2, 3, RL_FLOAT, 0, 0, 0);
|
rlSetVertexAttribute(2, 3, RL_FLOAT, 0, 0, 0);
|
||||||
rlEnableVertexAttribute(2);
|
rlEnableVertexAttribute(2);
|
||||||
|
@ -1858,35 +1852,34 @@ bool ExportMesh(Mesh mesh, const char *fileName)
|
||||||
|
|
||||||
#if defined(SUPPORT_FILEFORMAT_OBJ) || defined(SUPPORT_FILEFORMAT_MTL)
|
#if defined(SUPPORT_FILEFORMAT_OBJ) || defined(SUPPORT_FILEFORMAT_MTL)
|
||||||
// Process obj materials
|
// Process obj materials
|
||||||
static void ProcessMaterialsOBJ(Material *rayMaterials, tinyobj_material_t *materials, int materialCount)
|
static void ProcessMaterialsOBJ(Material *materials, tinyobj_material_t *mats, int materialCount)
|
||||||
{
|
{
|
||||||
// Init model materials
|
// Init model mats
|
||||||
for (int m = 0; m < materialCount; m++)
|
for (int m = 0; m < materialCount; m++)
|
||||||
{
|
{
|
||||||
// Init material to default
|
// Init material to default
|
||||||
// NOTE: Uses default shader, which only supports MATERIAL_MAP_DIFFUSE
|
// NOTE: Uses default shader, which only supports MATERIAL_MAP_DIFFUSE
|
||||||
rayMaterials[m] = LoadMaterialDefault();
|
materials[m] = LoadMaterialDefault();
|
||||||
|
|
||||||
// Get default texture, in case no texture is defined
|
// Get default texture, in case no texture is defined
|
||||||
// NOTE: rlgl default texture is a 1x1 pixel UNCOMPRESSED_R8G8B8A8
|
// NOTE: rlgl default texture is a 1x1 pixel UNCOMPRESSED_R8G8B8A8
|
||||||
rayMaterials[m].maps[MATERIAL_MAP_DIFFUSE].texture = (Texture2D){ rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };
|
materials[m].maps[MATERIAL_MAP_DIFFUSE].texture = (Texture2D){ rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };
|
||||||
|
|
||||||
if (materials[m].diffuse_texname != NULL) rayMaterials[m].maps[MATERIAL_MAP_DIFFUSE].texture = LoadTexture(materials[m].diffuse_texname); //char *diffuse_texname; // map_Kd
|
if (mats[m].diffuse_texname != NULL) materials[m].maps[MATERIAL_MAP_DIFFUSE].texture = LoadTexture(mats[m].diffuse_texname); //char *diffuse_texname; // map_Kd
|
||||||
|
else materials[m].maps[MATERIAL_MAP_DIFFUSE].color = (Color){ (unsigned char)(mats[m].diffuse[0]*255.0f), (unsigned char)(mats[m].diffuse[1]*255.0f), (unsigned char)(mats[m].diffuse[2] * 255.0f), 255 }; //float diffuse[3];
|
||||||
|
materials[m].maps[MATERIAL_MAP_DIFFUSE].value = 0.0f;
|
||||||
|
|
||||||
rayMaterials[m].maps[MATERIAL_MAP_DIFFUSE].color = (Color){ (unsigned char)(materials[m].diffuse[0]*255.0f), (unsigned char)(materials[m].diffuse[1]*255.0f), (unsigned char)(materials[m].diffuse[2] * 255.0f), 255 }; //float diffuse[3];
|
if (mats[m].specular_texname != NULL) materials[m].maps[MATERIAL_MAP_SPECULAR].texture = LoadTexture(mats[m].specular_texname); //char *specular_texname; // map_Ks
|
||||||
rayMaterials[m].maps[MATERIAL_MAP_DIFFUSE].value = 0.0f;
|
materials[m].maps[MATERIAL_MAP_SPECULAR].color = (Color){ (unsigned char)(mats[m].specular[0]*255.0f), (unsigned char)(mats[m].specular[1]*255.0f), (unsigned char)(mats[m].specular[2] * 255.0f), 255 }; //float specular[3];
|
||||||
|
materials[m].maps[MATERIAL_MAP_SPECULAR].value = 0.0f;
|
||||||
|
|
||||||
if (materials[m].specular_texname != NULL) rayMaterials[m].maps[MATERIAL_MAP_SPECULAR].texture = LoadTexture(materials[m].specular_texname); //char *specular_texname; // map_Ks
|
if (mats[m].bump_texname != NULL) materials[m].maps[MATERIAL_MAP_NORMAL].texture = LoadTexture(mats[m].bump_texname); //char *bump_texname; // map_bump, bump
|
||||||
rayMaterials[m].maps[MATERIAL_MAP_SPECULAR].color = (Color){ (unsigned char)(materials[m].specular[0]*255.0f), (unsigned char)(materials[m].specular[1]*255.0f), (unsigned char)(materials[m].specular[2] * 255.0f), 255 }; //float specular[3];
|
materials[m].maps[MATERIAL_MAP_NORMAL].color = WHITE;
|
||||||
rayMaterials[m].maps[MATERIAL_MAP_SPECULAR].value = 0.0f;
|
materials[m].maps[MATERIAL_MAP_NORMAL].value = mats[m].shininess;
|
||||||
|
|
||||||
if (materials[m].bump_texname != NULL) rayMaterials[m].maps[MATERIAL_MAP_NORMAL].texture = LoadTexture(materials[m].bump_texname); //char *bump_texname; // map_bump, bump
|
materials[m].maps[MATERIAL_MAP_EMISSION].color = (Color){ (unsigned char)(mats[m].emission[0]*255.0f), (unsigned char)(mats[m].emission[1]*255.0f), (unsigned char)(mats[m].emission[2] * 255.0f), 255 }; //float emission[3];
|
||||||
rayMaterials[m].maps[MATERIAL_MAP_NORMAL].color = WHITE;
|
|
||||||
rayMaterials[m].maps[MATERIAL_MAP_NORMAL].value = materials[m].shininess;
|
|
||||||
|
|
||||||
rayMaterials[m].maps[MATERIAL_MAP_EMISSION].color = (Color){ (unsigned char)(materials[m].emission[0]*255.0f), (unsigned char)(materials[m].emission[1]*255.0f), (unsigned char)(materials[m].emission[2] * 255.0f), 255 }; //float emission[3];
|
if (mats[m].displacement_texname != NULL) materials[m].maps[MATERIAL_MAP_HEIGHT].texture = LoadTexture(mats[m].displacement_texname); //char *displacement_texname; // disp
|
||||||
|
|
||||||
if (materials[m].displacement_texname != NULL) rayMaterials[m].maps[MATERIAL_MAP_HEIGHT].texture = LoadTexture(materials[m].displacement_texname); //char *displacement_texname; // disp
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1907,7 +1900,7 @@ Material *LoadMaterials(const char *fileName, int *materialCount)
|
||||||
int result = tinyobj_parse_mtl_file(&mats, &count, fileName);
|
int result = tinyobj_parse_mtl_file(&mats, &count, fileName);
|
||||||
if (result != TINYOBJ_SUCCESS) TRACELOG(LOG_WARNING, "MATERIAL: [%s] Failed to parse materials file", fileName);
|
if (result != TINYOBJ_SUCCESS) TRACELOG(LOG_WARNING, "MATERIAL: [%s] Failed to parse materials file", fileName);
|
||||||
|
|
||||||
materials = MemAlloc(count*sizeof(Material));
|
materials = RL_MALLOC(count*sizeof(Material));
|
||||||
ProcessMaterialsOBJ(materials, mats, count);
|
ProcessMaterialsOBJ(materials, mats, count);
|
||||||
|
|
||||||
tinyobj_materials_free(mats, count);
|
tinyobj_materials_free(mats, count);
|
||||||
|
@ -1982,7 +1975,7 @@ void SetModelMeshMaterial(Model *model, int meshId, int materialId)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load model animations from file
|
// Load model animations from file
|
||||||
ModelAnimation *LoadModelAnimations(const char *fileName, unsigned int *animCount)
|
ModelAnimation *LoadModelAnimations(const char *fileName, int *animCount)
|
||||||
{
|
{
|
||||||
ModelAnimation *animations = NULL;
|
ModelAnimation *animations = NULL;
|
||||||
|
|
||||||
|
@ -2102,9 +2095,9 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, int frame)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unload animation array data
|
// Unload animation array data
|
||||||
void UnloadModelAnimations(ModelAnimation *animations, unsigned int count)
|
void UnloadModelAnimations(ModelAnimation *animations, int animCount)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < count; i++) UnloadModelAnimation(animations[i]);
|
for (int i = 0; i < animCount; i++) UnloadModelAnimation(animations[i]);
|
||||||
RL_FREE(animations);
|
RL_FREE(animations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2149,11 +2142,11 @@ Mesh GenMeshPoly(int sides, float radius)
|
||||||
Vector3 *vertices = (Vector3 *)RL_MALLOC(vertexCount*sizeof(Vector3));
|
Vector3 *vertices = (Vector3 *)RL_MALLOC(vertexCount*sizeof(Vector3));
|
||||||
|
|
||||||
float d = 0.0f, dStep = 360.0f/sides;
|
float d = 0.0f, dStep = 360.0f/sides;
|
||||||
for (int v = 0; v < vertexCount; v += 3)
|
for (int v = 0; v < vertexCount - 2; v += 3)
|
||||||
{
|
{
|
||||||
vertices[v] = (Vector3){ 0.0f, 0.0f, 0.0f };
|
vertices[v] = (Vector3){ 0.0f, 0.0f, 0.0f };
|
||||||
vertices[v + 1] = (Vector3){ sinf(DEG2RAD*d)*radius, 0.0f, cosf(DEG2RAD*d)*radius };
|
vertices[v + 1] = (Vector3){ sinf(DEG2RAD*d)*radius, 0.0f, cosf(DEG2RAD*d)*radius };
|
||||||
vertices[v + 2] = (Vector3){sinf(DEG2RAD*(d+dStep))*radius, 0.0f, cosf(DEG2RAD*(d+dStep))*radius };
|
vertices[v + 2] = (Vector3){ sinf(DEG2RAD*(d+dStep))*radius, 0.0f, cosf(DEG2RAD*(d+dStep))*radius };
|
||||||
d += dStep;
|
d += dStep;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2252,7 +2245,7 @@ Mesh GenMeshPlane(float width, float length, int resX, int resZ)
|
||||||
for (int face = 0; face < numFaces; face++)
|
for (int face = 0; face < numFaces; face++)
|
||||||
{
|
{
|
||||||
// Retrieve lower left corner from face ind
|
// Retrieve lower left corner from face ind
|
||||||
int i = face % (resX - 1) + (face/(resZ - 1)*resX);
|
int i = face + face / (resX - 1);
|
||||||
|
|
||||||
triangles[t++] = i + resX;
|
triangles[t++] = i + resX;
|
||||||
triangles[t++] = i + 1;
|
triangles[t++] = i + 1;
|
||||||
|
@ -2460,7 +2453,7 @@ Mesh GenMeshCube(float width, float height, float length)
|
||||||
// Platonic solids:
|
// Platonic solids:
|
||||||
par_shapes_mesh* par_shapes_create_tetrahedron(); // 4 sides polyhedron (pyramid)
|
par_shapes_mesh* par_shapes_create_tetrahedron(); // 4 sides polyhedron (pyramid)
|
||||||
par_shapes_mesh* par_shapes_create_cube(); // 6 sides polyhedron (cube)
|
par_shapes_mesh* par_shapes_create_cube(); // 6 sides polyhedron (cube)
|
||||||
par_shapes_mesh* par_shapes_create_octahedron(); // 8 sides polyhedron (dyamond)
|
par_shapes_mesh* par_shapes_create_octahedron(); // 8 sides polyhedron (diamond)
|
||||||
par_shapes_mesh* par_shapes_create_dodecahedron(); // 12 sides polyhedron
|
par_shapes_mesh* par_shapes_create_dodecahedron(); // 12 sides polyhedron
|
||||||
par_shapes_mesh* par_shapes_create_icosahedron(); // 20 sides polyhedron
|
par_shapes_mesh* par_shapes_create_icosahedron(); // 20 sides polyhedron
|
||||||
*/
|
*/
|
||||||
|
@ -2940,11 +2933,8 @@ Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize)
|
||||||
|
|
||||||
Color *pixels = LoadImageColors(cubicmap);
|
Color *pixels = LoadImageColors(cubicmap);
|
||||||
|
|
||||||
int mapWidth = cubicmap.width;
|
|
||||||
int mapHeight = cubicmap.height;
|
|
||||||
|
|
||||||
// NOTE: Max possible number of triangles numCubes*(12 triangles by cube)
|
// NOTE: Max possible number of triangles numCubes*(12 triangles by cube)
|
||||||
int maxTriangles = cubicmap.width*cubicmap.height*12;
|
int maxTriangles = cubicmap.width * cubicmap.height * 12;
|
||||||
|
|
||||||
int vCounter = 0; // Used to count vertices
|
int vCounter = 0; // Used to count vertices
|
||||||
int tcCounter = 0; // Used to count texcoords
|
int tcCounter = 0; // Used to count texcoords
|
||||||
|
@ -2981,9 +2971,9 @@ Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize)
|
||||||
RectangleF topTexUV = { 0.0f, 0.5f, 0.5f, 0.5f };
|
RectangleF topTexUV = { 0.0f, 0.5f, 0.5f, 0.5f };
|
||||||
RectangleF bottomTexUV = { 0.5f, 0.5f, 0.5f, 0.5f };
|
RectangleF bottomTexUV = { 0.5f, 0.5f, 0.5f, 0.5f };
|
||||||
|
|
||||||
for (int z = 0; z < mapHeight; ++z)
|
for (int z = 0; z < cubicmap.height; ++z)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < mapWidth; ++x)
|
for (int x = 0; x < cubicmap.width; ++x)
|
||||||
{
|
{
|
||||||
// Define the 8 vertex of the cube, we will combine them accordingly later...
|
// Define the 8 vertex of the cube, we will combine them accordingly later...
|
||||||
Vector3 v1 = { w*(x - 0.5f), h2, h*(z - 0.5f) };
|
Vector3 v1 = { w*(x - 0.5f), h2, h*(z - 0.5f) };
|
||||||
|
@ -3400,7 +3390,7 @@ void GenMeshTangents(Mesh *mesh)
|
||||||
{
|
{
|
||||||
if (mesh->vboId[SHADER_LOC_VERTEX_TANGENT] != 0)
|
if (mesh->vboId[SHADER_LOC_VERTEX_TANGENT] != 0)
|
||||||
{
|
{
|
||||||
// Upate existing vertex buffer
|
// Update existing vertex buffer
|
||||||
rlUpdateVertexBuffer(mesh->vboId[SHADER_LOC_VERTEX_TANGENT], mesh->tangents, mesh->vertexCount*4*sizeof(float), 0);
|
rlUpdateVertexBuffer(mesh->vboId[SHADER_LOC_VERTEX_TANGENT], mesh->tangents, mesh->vertexCount*4*sizeof(float), 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -3497,7 +3487,7 @@ void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector
|
||||||
void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector3 up, Vector2 size, Vector2 origin, float rotation, Color tint)
|
void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector3 up, Vector2 size, Vector2 origin, float rotation, Color tint)
|
||||||
{
|
{
|
||||||
// NOTE: Billboard size will maintain source rectangle aspect ratio, size will represent billboard width
|
// NOTE: Billboard size will maintain source rectangle aspect ratio, size will represent billboard width
|
||||||
Vector2 sizeRatio = { size.x*(float)source.width/source.height, size.y };
|
Vector2 sizeRatio = { size.x*fabsf((float)source.width/source.height), size.y };
|
||||||
|
|
||||||
Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up);
|
Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up);
|
||||||
|
|
||||||
|
@ -3563,6 +3553,8 @@ void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector
|
||||||
rlBegin(RL_QUADS);
|
rlBegin(RL_QUADS);
|
||||||
rlColor4ub(tint.r, tint.g, tint.b, tint.a);
|
rlColor4ub(tint.r, tint.g, tint.b, tint.a);
|
||||||
|
|
||||||
|
if (sizeRatio.x * sizeRatio.y >= 0.0f)
|
||||||
|
{
|
||||||
// Bottom-left corner for texture and quad
|
// Bottom-left corner for texture and quad
|
||||||
rlTexCoord2f((float)source.x/texture.width, (float)source.y/texture.height);
|
rlTexCoord2f((float)source.x/texture.width, (float)source.y/texture.height);
|
||||||
rlVertex3f(topLeft.x, topLeft.y, topLeft.z);
|
rlVertex3f(topLeft.x, topLeft.y, topLeft.z);
|
||||||
|
@ -3578,6 +3570,23 @@ void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector
|
||||||
// Bottom-right corner for texture and quad
|
// Bottom-right corner for texture and quad
|
||||||
rlTexCoord2f((float)(source.x + source.width)/texture.width, (float)source.y/texture.height);
|
rlTexCoord2f((float)(source.x + source.width)/texture.width, (float)source.y/texture.height);
|
||||||
rlVertex3f(topRight.x, topRight.y, topRight.z);
|
rlVertex3f(topRight.x, topRight.y, topRight.z);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Reverse vertex order if the size has only one negative dimension
|
||||||
|
rlTexCoord2f((float)(source.x + source.width)/texture.width, (float)source.y/texture.height);
|
||||||
|
rlVertex3f(topRight.x, topRight.y, topRight.z);
|
||||||
|
|
||||||
|
rlTexCoord2f((float)(source.x + source.width)/texture.width, (float)(source.y + source.height)/texture.height);
|
||||||
|
rlVertex3f(bottomRight.x, bottomRight.y, bottomRight.z);
|
||||||
|
|
||||||
|
rlTexCoord2f((float)source.x/texture.width, (float)(source.y + source.height)/texture.height);
|
||||||
|
rlVertex3f(bottomLeft.x, bottomLeft.y, bottomLeft.z);
|
||||||
|
|
||||||
|
rlTexCoord2f((float)source.x/texture.width, (float)source.y/texture.height);
|
||||||
|
rlVertex3f(topLeft.x, topLeft.y, topLeft.z);
|
||||||
|
}
|
||||||
|
|
||||||
rlEnd();
|
rlEnd();
|
||||||
|
|
||||||
rlSetTexture(0);
|
rlSetTexture(0);
|
||||||
|
@ -3922,9 +3931,10 @@ static Model LoadOBJ(const char *fileName)
|
||||||
if (fileText != NULL)
|
if (fileText != NULL)
|
||||||
{
|
{
|
||||||
unsigned int dataSize = (unsigned int)strlen(fileText);
|
unsigned int dataSize = (unsigned int)strlen(fileText);
|
||||||
|
|
||||||
char currentDir[1024] = { 0 };
|
char currentDir[1024] = { 0 };
|
||||||
strcpy(currentDir, GetWorkingDirectory());
|
strcpy(currentDir, GetWorkingDirectory()); // Save current working directory
|
||||||
const char *workingDir = GetDirectoryPath(fileName);
|
const char *workingDir = GetDirectoryPath(fileName); // Switch to OBJ directory for material path correctness
|
||||||
if (CHDIR(workingDir) != 0)
|
if (CHDIR(workingDir) != 0)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to change working directory", workingDir);
|
TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to change working directory", workingDir);
|
||||||
|
@ -3936,117 +3946,91 @@ static Model LoadOBJ(const char *fileName)
|
||||||
if (ret != TINYOBJ_SUCCESS) TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load OBJ data", fileName);
|
if (ret != TINYOBJ_SUCCESS) TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load OBJ data", fileName);
|
||||||
else TRACELOG(LOG_INFO, "MODEL: [%s] OBJ data loaded successfully: %i meshes/%i materials", fileName, meshCount, materialCount);
|
else TRACELOG(LOG_INFO, "MODEL: [%s] OBJ data loaded successfully: %i meshes/%i materials", fileName, meshCount, materialCount);
|
||||||
|
|
||||||
model.meshCount = materialCount;
|
// WARNING: We are not splitting meshes by materials (previous implementation)
|
||||||
|
// Depending on the provided OBJ that was not the best option and it just crashed
|
||||||
|
// so, implementation was simplified to prioritize parsed meshes
|
||||||
|
model.meshCount = meshCount;
|
||||||
|
|
||||||
// Init model materials array
|
// Set number of materials available
|
||||||
if (materialCount > 0)
|
// NOTE: There could be more materials available than meshes but it will be resolved at
|
||||||
{
|
// model.meshMaterial, just assigning the right material to corresponding mesh
|
||||||
model.materialCount = materialCount;
|
model.materialCount = materialCount;
|
||||||
model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));
|
if (model.materialCount == 0)
|
||||||
TRACELOG(LOG_INFO, "MODEL: model has %i material meshes", materialCount);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
model.meshCount = 1;
|
model.materialCount = 1;
|
||||||
TRACELOG(LOG_INFO, "MODEL: No materials, putting all meshes in a default material");
|
TRACELOG(LOG_INFO, "MODEL: No materials provided, setting one default material for all meshes");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init model meshes and materials
|
||||||
model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));
|
model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));
|
||||||
model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
|
model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int)); // Material index assigned to each mesh
|
||||||
|
model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));
|
||||||
|
|
||||||
// Count the faces for each material
|
// Process each provided mesh
|
||||||
int *matFaces = RL_CALLOC(model.meshCount, sizeof(int));
|
for (int i = 0; i < model.meshCount; i++)
|
||||||
|
|
||||||
// if no materials are present use all faces on one mesh
|
|
||||||
if (materialCount > 0)
|
|
||||||
{
|
{
|
||||||
for (unsigned int fi = 0; fi < attrib.num_faces; fi++)
|
// WARNING: We need to calculate the mesh triangles manually using meshes[i].face_offset
|
||||||
|
// because in case of triangulated quads, meshes[i].length actually report quads,
|
||||||
|
// despite the triangulation that is efectively considered on attrib.num_faces
|
||||||
|
unsigned int tris = 0;
|
||||||
|
if (i == model.meshCount - 1) tris = attrib.num_faces - meshes[i].face_offset;
|
||||||
|
else tris = meshes[i + 1].face_offset;
|
||||||
|
|
||||||
|
model.meshes[i].vertexCount = tris*3;
|
||||||
|
model.meshes[i].triangleCount = tris; // Face count (triangulated)
|
||||||
|
model.meshes[i].vertices = (float *)RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));
|
||||||
|
model.meshes[i].texcoords = (float *)RL_CALLOC(model.meshes[i].vertexCount*2, sizeof(float));
|
||||||
|
model.meshes[i].normals = (float *)RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));
|
||||||
|
model.meshMaterial[i] = 0; // By default, assign material 0 to each mesh
|
||||||
|
|
||||||
|
// Process all mesh faces
|
||||||
|
for (unsigned int face = 0, f = meshes[i].face_offset, v = 0, vt = 0, vn = 0; face < tris; face++, f++, v += 3, vt += 3, vn += 3)
|
||||||
{
|
{
|
||||||
//tinyobj_vertex_index_t face = attrib.faces[fi];
|
|
||||||
int idx = attrib.material_ids[fi];
|
|
||||||
matFaces[idx]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
matFaces[0] = attrib.num_faces;
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------
|
|
||||||
// Create the material meshes
|
|
||||||
|
|
||||||
// Running counts/indexes for each material mesh as we are
|
|
||||||
// building them at the same time
|
|
||||||
int *vCount = RL_CALLOC(model.meshCount, sizeof(int));
|
|
||||||
int *vtCount = RL_CALLOC(model.meshCount, sizeof(int));
|
|
||||||
int *vnCount = RL_CALLOC(model.meshCount, sizeof(int));
|
|
||||||
int *faceCount = RL_CALLOC(model.meshCount, sizeof(int));
|
|
||||||
|
|
||||||
// Allocate space for each of the material meshes
|
|
||||||
for (int mi = 0; mi < model.meshCount; mi++)
|
|
||||||
{
|
|
||||||
model.meshes[mi].vertexCount = matFaces[mi]*3;
|
|
||||||
model.meshes[mi].triangleCount = matFaces[mi];
|
|
||||||
model.meshes[mi].vertices = (float *)RL_CALLOC(model.meshes[mi].vertexCount*3, sizeof(float));
|
|
||||||
model.meshes[mi].texcoords = (float *)RL_CALLOC(model.meshes[mi].vertexCount*2, sizeof(float));
|
|
||||||
model.meshes[mi].normals = (float *)RL_CALLOC(model.meshes[mi].vertexCount*3, sizeof(float));
|
|
||||||
model.meshMaterial[mi] = mi;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scan through the combined sub meshes and pick out each material mesh
|
|
||||||
for (unsigned int af = 0; af < attrib.num_faces; af++)
|
|
||||||
{
|
|
||||||
int mm = attrib.material_ids[af]; // mesh material for this face
|
|
||||||
if (mm == -1) { mm = 0; } // no material object..
|
|
||||||
|
|
||||||
// Get indices for the face
|
// Get indices for the face
|
||||||
tinyobj_vertex_index_t idx0 = attrib.faces[3*af + 0];
|
tinyobj_vertex_index_t idx0 = attrib.faces[f*3 + 0];
|
||||||
tinyobj_vertex_index_t idx1 = attrib.faces[3*af + 1];
|
tinyobj_vertex_index_t idx1 = attrib.faces[f*3 + 1];
|
||||||
tinyobj_vertex_index_t idx2 = attrib.faces[3*af + 2];
|
tinyobj_vertex_index_t idx2 = attrib.faces[f*3 + 2];
|
||||||
|
|
||||||
// Fill vertices buffer (float) using vertex index of the face
|
// Fill vertices buffer (float) using vertex index of the face
|
||||||
for (int v = 0; v < 3; v++) { model.meshes[mm].vertices[vCount[mm] + v] = attrib.vertices[idx0.v_idx*3 + v]; } vCount[mm] +=3;
|
for (int n = 0; n < 3; n++) { model.meshes[i].vertices[v*3 + n] = attrib.vertices[idx0.v_idx*3 + n]; }
|
||||||
for (int v = 0; v < 3; v++) { model.meshes[mm].vertices[vCount[mm] + v] = attrib.vertices[idx1.v_idx*3 + v]; } vCount[mm] +=3;
|
for (int n = 0; n < 3; n++) { model.meshes[i].vertices[(v + 1)*3 + n] = attrib.vertices[idx1.v_idx*3 + n]; }
|
||||||
for (int v = 0; v < 3; v++) { model.meshes[mm].vertices[vCount[mm] + v] = attrib.vertices[idx2.v_idx*3 + v]; } vCount[mm] +=3;
|
for (int n = 0; n < 3; n++) { model.meshes[i].vertices[(v + 2)*3 + n] = attrib.vertices[idx2.v_idx*3 + n]; }
|
||||||
|
|
||||||
if (attrib.num_texcoords > 0)
|
if (attrib.num_texcoords > 0)
|
||||||
{
|
{
|
||||||
// Fill texcoords buffer (float) using vertex index of the face
|
// Fill texcoords buffer (float) using vertex index of the face
|
||||||
// NOTE: Y-coordinate must be flipped upside-down to account for
|
// NOTE: Y-coordinate must be flipped upside-down
|
||||||
// raylib's upside down textures...
|
model.meshes[i].texcoords[vt*2 + 0] = attrib.texcoords[idx0.vt_idx*2 + 0];
|
||||||
model.meshes[mm].texcoords[vtCount[mm] + 0] = attrib.texcoords[idx0.vt_idx*2 + 0];
|
model.meshes[i].texcoords[vt*2 + 1] = 1.0f - attrib.texcoords[idx0.vt_idx*2 + 1];
|
||||||
model.meshes[mm].texcoords[vtCount[mm] + 1] = 1.0f - attrib.texcoords[idx0.vt_idx*2 + 1]; vtCount[mm] += 2;
|
|
||||||
model.meshes[mm].texcoords[vtCount[mm] + 0] = attrib.texcoords[idx1.vt_idx*2 + 0];
|
model.meshes[i].texcoords[(vt + 1)*2 + 0] = attrib.texcoords[idx1.vt_idx*2 + 0];
|
||||||
model.meshes[mm].texcoords[vtCount[mm] + 1] = 1.0f - attrib.texcoords[idx1.vt_idx*2 + 1]; vtCount[mm] += 2;
|
model.meshes[i].texcoords[(vt + 1)*2 + 1] = 1.0f - attrib.texcoords[idx1.vt_idx*2 + 1];
|
||||||
model.meshes[mm].texcoords[vtCount[mm] + 0] = attrib.texcoords[idx2.vt_idx*2 + 0];
|
|
||||||
model.meshes[mm].texcoords[vtCount[mm] + 1] = 1.0f - attrib.texcoords[idx2.vt_idx*2 + 1]; vtCount[mm] += 2;
|
model.meshes[i].texcoords[(vt + 2)*2 + 0] = attrib.texcoords[idx2.vt_idx*2 + 0];
|
||||||
|
model.meshes[i].texcoords[(vt + 2)*2 + 1] = 1.0f - attrib.texcoords[idx2.vt_idx*2 + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attrib.num_normals > 0)
|
if (attrib.num_normals > 0)
|
||||||
{
|
{
|
||||||
// Fill normals buffer (float) using vertex index of the face
|
// Fill normals buffer (float) using vertex index of the face
|
||||||
for (int v = 0; v < 3; v++) { model.meshes[mm].normals[vnCount[mm] + v] = attrib.normals[idx0.vn_idx*3 + v]; } vnCount[mm] +=3;
|
for (int n = 0; n < 3; n++) { model.meshes[i].normals[vn*3 + n] = attrib.normals[idx0.vn_idx*3 + n]; }
|
||||||
for (int v = 0; v < 3; v++) { model.meshes[mm].normals[vnCount[mm] + v] = attrib.normals[idx1.vn_idx*3 + v]; } vnCount[mm] +=3;
|
for (int n = 0; n < 3; n++) { model.meshes[i].normals[(vn + 1)*3 + n] = attrib.normals[idx1.vn_idx*3 + n]; }
|
||||||
for (int v = 0; v < 3; v++) { model.meshes[mm].normals[vnCount[mm] + v] = attrib.normals[idx2.vn_idx*3 + v]; } vnCount[mm] +=3;
|
for (int n = 0; n < 3; n++) { model.meshes[i].normals[(vn + 2)*3 + n] = attrib.normals[idx2.vn_idx*3 + n]; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init model materials
|
// Init model materials
|
||||||
ProcessMaterialsOBJ(model.materials, materials, materialCount);
|
if (materialCount > 0) ProcessMaterialsOBJ(model.materials, materials, materialCount);
|
||||||
|
else model.materials[0] = LoadMaterialDefault(); // Set default material for the mesh
|
||||||
|
|
||||||
tinyobj_attrib_free(&attrib);
|
tinyobj_attrib_free(&attrib);
|
||||||
tinyobj_shapes_free(meshes, meshCount);
|
tinyobj_shapes_free(meshes, model.meshCount);
|
||||||
tinyobj_materials_free(materials, materialCount);
|
tinyobj_materials_free(materials, materialCount);
|
||||||
|
|
||||||
UnloadFileText(fileText);
|
UnloadFileText(fileText);
|
||||||
|
|
||||||
RL_FREE(matFaces);
|
// Restore current working directory
|
||||||
RL_FREE(vCount);
|
|
||||||
RL_FREE(vtCount);
|
|
||||||
RL_FREE(vnCount);
|
|
||||||
RL_FREE(faceCount);
|
|
||||||
|
|
||||||
if (CHDIR(currentDir) != 0)
|
if (CHDIR(currentDir) != 0)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to change working directory", currentDir);
|
TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to change working directory", currentDir);
|
||||||
|
@ -4068,8 +4052,8 @@ static Model LoadIQM(const char *fileName)
|
||||||
#define MESH_NAME_LENGTH 32 // Mesh name string length
|
#define MESH_NAME_LENGTH 32 // Mesh name string length
|
||||||
#define MATERIAL_NAME_LENGTH 32 // Material name string length
|
#define MATERIAL_NAME_LENGTH 32 // Material name string length
|
||||||
|
|
||||||
unsigned int fileSize = 0;
|
int dataSize = 0;
|
||||||
unsigned char *fileData = LoadFileData(fileName, &fileSize);
|
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
||||||
unsigned char *fileDataPtr = fileData;
|
unsigned char *fileDataPtr = fileData;
|
||||||
|
|
||||||
// IQM file structs
|
// IQM file structs
|
||||||
|
@ -4077,7 +4061,7 @@ static Model LoadIQM(const char *fileName)
|
||||||
typedef struct IQMHeader {
|
typedef struct IQMHeader {
|
||||||
char magic[16];
|
char magic[16];
|
||||||
unsigned int version;
|
unsigned int version;
|
||||||
unsigned int filesize;
|
unsigned int dataSize;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
unsigned int num_text, ofs_text;
|
unsigned int num_text, ofs_text;
|
||||||
unsigned int num_meshes, ofs_meshes;
|
unsigned int num_meshes, ofs_meshes;
|
||||||
|
@ -4231,7 +4215,7 @@ static Model LoadIQM(const char *fileName)
|
||||||
model.meshes[i].triangleCount = imesh[i].num_triangles;
|
model.meshes[i].triangleCount = imesh[i].num_triangles;
|
||||||
model.meshes[i].indices = RL_CALLOC(model.meshes[i].triangleCount*3, sizeof(unsigned short));
|
model.meshes[i].indices = RL_CALLOC(model.meshes[i].triangleCount*3, sizeof(unsigned short));
|
||||||
|
|
||||||
// Animated verted data, what we actually process for rendering
|
// Animated vertex data, what we actually process for rendering
|
||||||
// NOTE: Animated vertex should be re-uploaded to GPU (if not using GPU skinning)
|
// NOTE: Animated vertex should be re-uploaded to GPU (if not using GPU skinning)
|
||||||
model.meshes[i].animVertices = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));
|
model.meshes[i].animVertices = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));
|
||||||
model.meshes[i].animNormals = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));
|
model.meshes[i].animNormals = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));
|
||||||
|
@ -4430,19 +4414,19 @@ static Model LoadIQM(const char *fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load IQM animation data
|
// Load IQM animation data
|
||||||
static ModelAnimation *LoadModelAnimationsIQM(const char *fileName, unsigned int *animCount)
|
static ModelAnimation *LoadModelAnimationsIQM(const char *fileName, int *animCount)
|
||||||
{
|
{
|
||||||
#define IQM_MAGIC "INTERQUAKEMODEL" // IQM file magic number
|
#define IQM_MAGIC "INTERQUAKEMODEL" // IQM file magic number
|
||||||
#define IQM_VERSION 2 // only IQM version 2 supported
|
#define IQM_VERSION 2 // only IQM version 2 supported
|
||||||
|
|
||||||
unsigned int fileSize = 0;
|
int dataSize = 0;
|
||||||
unsigned char *fileData = LoadFileData(fileName, &fileSize);
|
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
||||||
unsigned char *fileDataPtr = fileData;
|
unsigned char *fileDataPtr = fileData;
|
||||||
|
|
||||||
typedef struct IQMHeader {
|
typedef struct IQMHeader {
|
||||||
char magic[16];
|
char magic[16];
|
||||||
unsigned int version;
|
unsigned int version;
|
||||||
unsigned int filesize;
|
unsigned int dataSize;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
unsigned int num_text, ofs_text;
|
unsigned int num_text, ofs_text;
|
||||||
unsigned int num_meshes, ofs_meshes;
|
unsigned int num_meshes, ofs_meshes;
|
||||||
|
@ -4525,7 +4509,7 @@ static ModelAnimation *LoadModelAnimationsIQM(const char *fileName, unsigned int
|
||||||
animations[a].boneCount = iqmHeader->num_poses;
|
animations[a].boneCount = iqmHeader->num_poses;
|
||||||
animations[a].bones = RL_MALLOC(iqmHeader->num_poses*sizeof(BoneInfo));
|
animations[a].bones = RL_MALLOC(iqmHeader->num_poses*sizeof(BoneInfo));
|
||||||
animations[a].framePoses = RL_MALLOC(anim[a].num_frames*sizeof(Transform *));
|
animations[a].framePoses = RL_MALLOC(anim[a].num_frames*sizeof(Transform *));
|
||||||
// animations[a].framerate = anim.framerate; // TODO: Use framerate?
|
// animations[a].framerate = anim.framerate; // TODO: Use animation framerate data?
|
||||||
|
|
||||||
for (unsigned int j = 0; j < iqmHeader->num_poses; j++)
|
for (unsigned int j = 0; j < iqmHeader->num_poses; j++)
|
||||||
{
|
{
|
||||||
|
@ -4691,7 +4675,7 @@ static Image LoadImageFromCgltfImage(cgltf_image *cgltfImage, const char *texPat
|
||||||
if (result == cgltf_result_success)
|
if (result == cgltf_result_success)
|
||||||
{
|
{
|
||||||
image = LoadImageFromMemory(".png", (unsigned char *)data, outSize);
|
image = LoadImageFromMemory(".png", (unsigned char *)data, outSize);
|
||||||
MemFree(data);
|
RL_FREE(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4774,7 +4758,7 @@ static Model LoadGLTF(const char *fileName)
|
||||||
|
|
||||||
RESTRICTIONS:
|
RESTRICTIONS:
|
||||||
- Only triangle meshes supported
|
- Only triangle meshes supported
|
||||||
- Vertex attibute types and formats supported:
|
- Vertex attribute types and formats supported:
|
||||||
> Vertices (position): vec3: float
|
> Vertices (position): vec3: float
|
||||||
> Normals: vec3: float
|
> Normals: vec3: float
|
||||||
> Texcoords: vec2: float
|
> Texcoords: vec2: float
|
||||||
|
@ -4802,7 +4786,7 @@ static Model LoadGLTF(const char *fileName)
|
||||||
Model model = { 0 };
|
Model model = { 0 };
|
||||||
|
|
||||||
// glTF file loading
|
// glTF file loading
|
||||||
unsigned int dataSize = 0;
|
int dataSize = 0;
|
||||||
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
||||||
|
|
||||||
if (fileData == NULL) return model;
|
if (fileData == NULL) return model;
|
||||||
|
@ -4825,7 +4809,7 @@ static Model LoadGLTF(const char *fileName)
|
||||||
TRACELOG(LOG_DEBUG, " > Textures count: %i", data->textures_count);
|
TRACELOG(LOG_DEBUG, " > Textures count: %i", data->textures_count);
|
||||||
|
|
||||||
// Force reading data buffers (fills buffer_view->buffer->data)
|
// Force reading data buffers (fills buffer_view->buffer->data)
|
||||||
// NOTE: If an uri is defined to base64 data or external path, it's automatically loaded -> TODO: Verify this assumption
|
// NOTE: If an uri is defined to base64 data or external path, it's automatically loaded
|
||||||
result = cgltf_load_buffers(&options, data, fileName);
|
result = cgltf_load_buffers(&options, data, fileName);
|
||||||
if (result != cgltf_result_success) TRACELOG(LOG_INFO, "MODEL: [%s] Failed to load mesh/material buffers", fileName);
|
if (result != cgltf_result_success) TRACELOG(LOG_INFO, "MODEL: [%s] Failed to load mesh/material buffers", fileName);
|
||||||
|
|
||||||
|
@ -5205,7 +5189,9 @@ static Model LoadGLTF(const char *fileName)
|
||||||
model.meshes[meshIndex].animVertices = RL_CALLOC(model.meshes[meshIndex].vertexCount*3, sizeof(float));
|
model.meshes[meshIndex].animVertices = RL_CALLOC(model.meshes[meshIndex].vertexCount*3, sizeof(float));
|
||||||
memcpy(model.meshes[meshIndex].animVertices, model.meshes[meshIndex].vertices, model.meshes[meshIndex].vertexCount*3*sizeof(float));
|
memcpy(model.meshes[meshIndex].animVertices, model.meshes[meshIndex].vertices, model.meshes[meshIndex].vertexCount*3*sizeof(float));
|
||||||
model.meshes[meshIndex].animNormals = RL_CALLOC(model.meshes[meshIndex].vertexCount*3, sizeof(float));
|
model.meshes[meshIndex].animNormals = RL_CALLOC(model.meshes[meshIndex].vertexCount*3, sizeof(float));
|
||||||
|
if (model.meshes[meshIndex].normals != NULL) {
|
||||||
memcpy(model.meshes[meshIndex].animNormals, model.meshes[meshIndex].normals, model.meshes[meshIndex].vertexCount*3*sizeof(float));
|
memcpy(model.meshes[meshIndex].animNormals, model.meshes[meshIndex].normals, model.meshes[meshIndex].vertexCount*3*sizeof(float));
|
||||||
|
}
|
||||||
|
|
||||||
meshIndex++; // Move to next mesh
|
meshIndex++; // Move to next mesh
|
||||||
}
|
}
|
||||||
|
@ -5231,7 +5217,7 @@ static bool GetPoseAtTimeGLTF(cgltf_accessor *input, cgltf_accessor *output, flo
|
||||||
float tend = 0.0f;
|
float tend = 0.0f;
|
||||||
int keyframe = 0; // Defaults to first pose
|
int keyframe = 0; // Defaults to first pose
|
||||||
|
|
||||||
for (int i = 0; i < input->count - 1; i++)
|
for (int i = 0; i < (int)input->count - 1; i++)
|
||||||
{
|
{
|
||||||
cgltf_bool r1 = cgltf_accessor_read_float(input, i, &tstart, 1);
|
cgltf_bool r1 = cgltf_accessor_read_float(input, i, &tstart, 1);
|
||||||
if (!r1) return false;
|
if (!r1) return false;
|
||||||
|
@ -5271,7 +5257,7 @@ static bool GetPoseAtTimeGLTF(cgltf_accessor *input, cgltf_accessor *output, flo
|
||||||
Vector4 v2 = {tmp[0], tmp[1], tmp[2], tmp[3]};
|
Vector4 v2 = {tmp[0], tmp[1], tmp[2], tmp[3]};
|
||||||
Vector4 *r = data;
|
Vector4 *r = data;
|
||||||
|
|
||||||
// Only v4 is for rotations, so we know it's a quat
|
// Only v4 is for rotations, so we know it's a quaternion
|
||||||
*r = QuaternionSlerp(v1, v2, t);
|
*r = QuaternionSlerp(v1, v2, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5280,10 +5266,10 @@ static bool GetPoseAtTimeGLTF(cgltf_accessor *input, cgltf_accessor *output, flo
|
||||||
|
|
||||||
#define GLTF_ANIMDELAY 17 // Animation frames delay, (~1000 ms/60 FPS = 16.666666* ms)
|
#define GLTF_ANIMDELAY 17 // Animation frames delay, (~1000 ms/60 FPS = 16.666666* ms)
|
||||||
|
|
||||||
static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, unsigned int *animCount)
|
static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCount)
|
||||||
{
|
{
|
||||||
// glTF file loading
|
// glTF file loading
|
||||||
unsigned int dataSize = 0;
|
int dataSize = 0;
|
||||||
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
||||||
|
|
||||||
ModelAnimation *animations = NULL;
|
ModelAnimation *animations = NULL;
|
||||||
|
@ -5379,6 +5365,9 @@ static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, unsigned in
|
||||||
animDuration = (t > animDuration)? t : animDuration;
|
animDuration = (t > animDuration)? t : animDuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
strncpy(animations[i].name, animData.name, sizeof(animations[i].name));
|
||||||
|
animations[i].name[sizeof(animations[i].name) - 1] = '\0';
|
||||||
|
|
||||||
animations[i].frameCount = (int)(animDuration*1000.0f/GLTF_ANIMDELAY);
|
animations[i].frameCount = (int)(animDuration*1000.0f/GLTF_ANIMDELAY);
|
||||||
animations[i].framePoses = RL_MALLOC(animations[i].frameCount*sizeof(Transform *));
|
animations[i].framePoses = RL_MALLOC(animations[i].frameCount*sizeof(Transform *));
|
||||||
|
|
||||||
|
@ -5435,7 +5424,7 @@ static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, unsigned in
|
||||||
|
|
||||||
cgltf_free(data);
|
cgltf_free(data);
|
||||||
}
|
}
|
||||||
|
UnloadFileData(fileData);
|
||||||
return animations;
|
return animations;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -5448,11 +5437,11 @@ static Model LoadVOX(const char *fileName)
|
||||||
|
|
||||||
int nbvertices = 0;
|
int nbvertices = 0;
|
||||||
int meshescount = 0;
|
int meshescount = 0;
|
||||||
unsigned int fileSize = 0;
|
|
||||||
unsigned char *fileData = NULL;
|
|
||||||
|
|
||||||
// Read vox file into buffer
|
// Read vox file into buffer
|
||||||
fileData = LoadFileData(fileName, &fileSize);
|
int dataSize = 0;
|
||||||
|
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
||||||
|
|
||||||
if (fileData == 0)
|
if (fileData == 0)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load VOX file", fileName);
|
TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load VOX file", fileName);
|
||||||
|
@ -5461,7 +5450,7 @@ static Model LoadVOX(const char *fileName)
|
||||||
|
|
||||||
// Read and build voxarray description
|
// Read and build voxarray description
|
||||||
VoxArray3D voxarray = { 0 };
|
VoxArray3D voxarray = { 0 };
|
||||||
int ret = Vox_LoadFromMemory(fileData, fileSize, &voxarray);
|
int ret = Vox_LoadFromMemory(fileData, dataSize, &voxarray);
|
||||||
|
|
||||||
if (ret != VOX_SUCCESS)
|
if (ret != VOX_SUCCESS)
|
||||||
{
|
{
|
||||||
|
@ -5517,7 +5506,6 @@ static Model LoadVOX(const char *fileName)
|
||||||
memcpy(pmesh->vertices, pvertices, size);
|
memcpy(pmesh->vertices, pvertices, size);
|
||||||
|
|
||||||
// Copy indices
|
// Copy indices
|
||||||
// TODO: Compute globals indices array
|
|
||||||
size = voxarray.indices.used*sizeof(unsigned short);
|
size = voxarray.indices.used*sizeof(unsigned short);
|
||||||
pmesh->indices = RL_MALLOC(size);
|
pmesh->indices = RL_MALLOC(size);
|
||||||
memcpy(pmesh->indices, pindices, size);
|
memcpy(pmesh->indices, pindices, size);
|
||||||
|
@ -5547,7 +5535,7 @@ static Model LoadVOX(const char *fileName)
|
||||||
|
|
||||||
#if defined(SUPPORT_FILEFORMAT_M3D)
|
#if defined(SUPPORT_FILEFORMAT_M3D)
|
||||||
// Hook LoadFileData()/UnloadFileData() calls to M3D loaders
|
// Hook LoadFileData()/UnloadFileData() calls to M3D loaders
|
||||||
unsigned char *m3d_loaderhook(char *fn, unsigned int *len) { return LoadFileData((const char *)fn, len); }
|
unsigned char *m3d_loaderhook(char *fn, unsigned int *len) { return LoadFileData((const char *)fn, (int *)len); }
|
||||||
void m3d_freehook(void *data) { UnloadFileData((unsigned char *)data); }
|
void m3d_freehook(void *data) { UnloadFileData((unsigned char *)data); }
|
||||||
|
|
||||||
// Load M3D mesh data
|
// Load M3D mesh data
|
||||||
|
@ -5557,9 +5545,10 @@ static Model LoadM3D(const char *fileName)
|
||||||
|
|
||||||
m3d_t *m3d = NULL;
|
m3d_t *m3d = NULL;
|
||||||
m3dp_t *prop = NULL;
|
m3dp_t *prop = NULL;
|
||||||
unsigned int bytesRead = 0;
|
int i, j, k, l, n, mi = -2, vcolor = 0;
|
||||||
unsigned char *fileData = LoadFileData(fileName, &bytesRead);
|
|
||||||
int i, j, k, l, n, mi = -2;
|
int dataSize = 0;
|
||||||
|
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
||||||
|
|
||||||
if (fileData != NULL)
|
if (fileData != NULL)
|
||||||
{
|
{
|
||||||
|
@ -5567,7 +5556,7 @@ static Model LoadM3D(const char *fileName)
|
||||||
|
|
||||||
if (!m3d || M3D_ERR_ISFATAL(m3d->errcode))
|
if (!m3d || M3D_ERR_ISFATAL(m3d->errcode))
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load M3D data, error code %d", fileName, m3d ? m3d->errcode : -2);
|
TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load M3D data, error code %d", fileName, m3d? m3d->errcode : -2);
|
||||||
if (m3d) m3d_free(m3d);
|
if (m3d) m3d_free(m3d);
|
||||||
UnloadFileData(fileData);
|
UnloadFileData(fileData);
|
||||||
return model;
|
return model;
|
||||||
|
@ -5589,10 +5578,36 @@ static Model LoadM3D(const char *fileName)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
model.meshCount = model.materialCount = 1;
|
model.meshCount = 1; model.materialCount = 0;
|
||||||
TRACELOG(LOG_INFO, "MODEL: No materials, putting all meshes in a default material");
|
TRACELOG(LOG_INFO, "MODEL: No materials, putting all meshes in a default material");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We always need a default material, so we add +1
|
||||||
|
model.materialCount++;
|
||||||
|
|
||||||
|
// Faces must be in non-decreasing materialid order. Verify that quickly, sorting them otherwise.
|
||||||
|
// WARNING: Sorting is not needed, valid M3D model files should already be sorted
|
||||||
|
// Just keeping the sorting function for reference (Check PR #3363 #3385)
|
||||||
|
/*
|
||||||
|
for (i = 1; i < m3d->numface; i++)
|
||||||
|
{
|
||||||
|
if (m3d->face[i-1].materialid <= m3d->face[i].materialid) continue;
|
||||||
|
|
||||||
|
// face[i-1] > face[i]. slide face[i] lower.
|
||||||
|
m3df_t slider = m3d->face[i];
|
||||||
|
j = i-1;
|
||||||
|
|
||||||
|
do
|
||||||
|
{ // face[j] > slider, face[j+1] is svailable vacant gap.
|
||||||
|
m3d->face[j+1] = m3d->face[j];
|
||||||
|
j = j-1;
|
||||||
|
}
|
||||||
|
while (j >= 0 && m3d->face[j].materialid > slider.materialid);
|
||||||
|
|
||||||
|
m3d->face[j+1] = slider;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));
|
model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));
|
||||||
model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
|
model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
|
||||||
model.materials = (Material *)RL_CALLOC(model.materialCount + 1, sizeof(Material));
|
model.materials = (Material *)RL_CALLOC(model.materialCount + 1, sizeof(Material));
|
||||||
|
@ -5617,7 +5632,14 @@ static Model LoadM3D(const char *fileName)
|
||||||
k++;
|
k++;
|
||||||
mi = m3d->face[i].materialid;
|
mi = m3d->face[i].materialid;
|
||||||
|
|
||||||
for (j = i, l = 0; (j < (int)m3d->numface) && (mi == m3d->face[j].materialid); j++, l++);
|
// Only allocate colors VertexBuffer if there's a color vertex in the model for this material batch
|
||||||
|
// if all colors are fully transparent black for all verteces of this materal, then we assume no vertex colors
|
||||||
|
for (j = i, l = vcolor = 0; (j < (int)m3d->numface) && (mi == m3d->face[j].materialid); j++, l++)
|
||||||
|
{
|
||||||
|
if (!m3d->vertex[m3d->face[j].vertex[0]].color ||
|
||||||
|
!m3d->vertex[m3d->face[j].vertex[1]].color ||
|
||||||
|
!m3d->vertex[m3d->face[j].vertex[2]].color) vcolor = 1;
|
||||||
|
}
|
||||||
|
|
||||||
model.meshes[k].vertexCount = l*3;
|
model.meshes[k].vertexCount = l*3;
|
||||||
model.meshes[k].triangleCount = l;
|
model.meshes[k].triangleCount = l;
|
||||||
|
@ -5625,9 +5647,9 @@ static Model LoadM3D(const char *fileName)
|
||||||
model.meshes[k].texcoords = (float *)RL_CALLOC(model.meshes[k].vertexCount*2, sizeof(float));
|
model.meshes[k].texcoords = (float *)RL_CALLOC(model.meshes[k].vertexCount*2, sizeof(float));
|
||||||
model.meshes[k].normals = (float *)RL_CALLOC(model.meshes[k].vertexCount*3, sizeof(float));
|
model.meshes[k].normals = (float *)RL_CALLOC(model.meshes[k].vertexCount*3, sizeof(float));
|
||||||
|
|
||||||
// If no map is provided, we allocate storage for vertex colors
|
// If no map is provided, or we have colors defined, we allocate storage for vertex colors
|
||||||
// M3D specs only consider vertex colors if no material is provided
|
// M3D specs only consider vertex colors if no material is provided, however raylib uses both and mixes the colors
|
||||||
if (mi != M3D_UNDEF) model.meshes[k].colors = RL_CALLOC(model.meshes[k].vertexCount*4, sizeof(unsigned char));
|
if ((mi == M3D_UNDEF) || vcolor) model.meshes[k].colors = RL_CALLOC(model.meshes[k].vertexCount*4, sizeof(unsigned char));
|
||||||
|
|
||||||
if (m3d->numbone && m3d->numskin)
|
if (m3d->numbone && m3d->numskin)
|
||||||
{
|
{
|
||||||
|
@ -5652,7 +5674,7 @@ static Model LoadM3D(const char *fileName)
|
||||||
model.meshes[k].vertices[l*9 + 7] = m3d->vertex[m3d->face[i].vertex[2]].y*m3d->scale;
|
model.meshes[k].vertices[l*9 + 7] = m3d->vertex[m3d->face[i].vertex[2]].y*m3d->scale;
|
||||||
model.meshes[k].vertices[l*9 + 8] = m3d->vertex[m3d->face[i].vertex[2]].z*m3d->scale;
|
model.meshes[k].vertices[l*9 + 8] = m3d->vertex[m3d->face[i].vertex[2]].z*m3d->scale;
|
||||||
|
|
||||||
// without vertex color (full transparency), we use the default color
|
// Without vertex color (full transparency), we use the default color
|
||||||
if (model.meshes[k].colors != NULL)
|
if (model.meshes[k].colors != NULL)
|
||||||
{
|
{
|
||||||
if (m3d->vertex[m3d->face[i].vertex[0]].color & 0xFF000000)
|
if (m3d->vertex[m3d->face[i].vertex[0]].color & 0xFF000000)
|
||||||
|
@ -5694,7 +5716,7 @@ static Model LoadM3D(const char *fileName)
|
||||||
int skinid = m3d->vertex[m3d->face[i].vertex[n]].skinid;
|
int skinid = m3d->vertex[m3d->face[i].vertex[n]].skinid;
|
||||||
|
|
||||||
// Check if there is a skin for this mesh, should be, just failsafe
|
// Check if there is a skin for this mesh, should be, just failsafe
|
||||||
if (skinid != M3D_UNDEF && skinid < (int)m3d->numskin)
|
if ((skinid != M3D_UNDEF) && (skinid < (int)m3d->numskin))
|
||||||
{
|
{
|
||||||
for (j = 0; j < 4; j++)
|
for (j = 0; j < 4; j++)
|
||||||
{
|
{
|
||||||
|
@ -5803,7 +5825,7 @@ static Model LoadM3D(const char *fileName)
|
||||||
model.bindPose[i].rotation.z = m3d->vertex[m3d->bone[i].ori].z;
|
model.bindPose[i].rotation.z = m3d->vertex[m3d->bone[i].ori].z;
|
||||||
model.bindPose[i].rotation.w = m3d->vertex[m3d->bone[i].ori].w;
|
model.bindPose[i].rotation.w = m3d->vertex[m3d->bone[i].ori].w;
|
||||||
|
|
||||||
// TODO: if the orientation quaternion not normalized, then that's encoding scaling
|
// TODO: If the orientation quaternion is not normalized, then that's encoding scaling
|
||||||
model.bindPose[i].rotation = QuaternionNormalize(model.bindPose[i].rotation);
|
model.bindPose[i].rotation = QuaternionNormalize(model.bindPose[i].rotation);
|
||||||
model.bindPose[i].scale.x = model.bindPose[i].scale.y = model.bindPose[i].scale.z = 1.0f;
|
model.bindPose[i].scale.x = model.bindPose[i].scale.y = model.bindPose[i].scale.z = 1.0f;
|
||||||
|
|
||||||
|
@ -5851,23 +5873,24 @@ static Model LoadM3D(const char *fileName)
|
||||||
#define M3D_ANIMDELAY 17 // Animation frames delay, (~1000 ms/60 FPS = 16.666666* ms)
|
#define M3D_ANIMDELAY 17 // Animation frames delay, (~1000 ms/60 FPS = 16.666666* ms)
|
||||||
|
|
||||||
// Load M3D animation data
|
// Load M3D animation data
|
||||||
static ModelAnimation *LoadModelAnimationsM3D(const char *fileName, unsigned int *animCount)
|
static ModelAnimation *LoadModelAnimationsM3D(const char *fileName, int *animCount)
|
||||||
{
|
{
|
||||||
m3d_t *m3d = NULL;
|
|
||||||
unsigned int bytesRead = 0;
|
|
||||||
unsigned char *fileData = LoadFileData(fileName, &bytesRead);
|
|
||||||
ModelAnimation *animations = NULL;
|
ModelAnimation *animations = NULL;
|
||||||
int i = 0, j = 0;
|
|
||||||
|
|
||||||
|
m3d_t *m3d = NULL;
|
||||||
|
int i = 0, j = 0;
|
||||||
*animCount = 0;
|
*animCount = 0;
|
||||||
|
|
||||||
|
int dataSize = 0;
|
||||||
|
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
||||||
|
|
||||||
if (fileData != NULL)
|
if (fileData != NULL)
|
||||||
{
|
{
|
||||||
m3d = m3d_load(fileData, m3d_loaderhook, m3d_freehook, NULL);
|
m3d = m3d_load(fileData, m3d_loaderhook, m3d_freehook, NULL);
|
||||||
|
|
||||||
if (!m3d || M3D_ERR_ISFATAL(m3d->errcode))
|
if (!m3d || M3D_ERR_ISFATAL(m3d->errcode))
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load M3D data, error code %d", fileName, m3d ? m3d->errcode : -2);
|
TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load M3D data, error code %d", fileName, m3d? m3d->errcode : -2);
|
||||||
UnloadFileData(fileData);
|
UnloadFileData(fileData);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -438,7 +438,7 @@ func SetModelMeshMaterial(model *Model, meshId int32, materialId int32) {
|
||||||
func LoadModelAnimations(fileName string) []ModelAnimation {
|
func LoadModelAnimations(fileName string) []ModelAnimation {
|
||||||
cfileName := C.CString(fileName)
|
cfileName := C.CString(fileName)
|
||||||
defer C.free(unsafe.Pointer(cfileName))
|
defer C.free(unsafe.Pointer(cfileName))
|
||||||
ccount := C.uint(0)
|
ccount := C.int(0)
|
||||||
ret := C.LoadModelAnimations(cfileName, &ccount)
|
ret := C.LoadModelAnimations(cfileName, &ccount)
|
||||||
v := (*[1 << 24]ModelAnimation)(unsafe.Pointer(ret))[:int(ccount)]
|
v := (*[1 << 24]ModelAnimation)(unsafe.Pointer(ret))[:int(ccount)]
|
||||||
return v
|
return v
|
||||||
|
@ -460,7 +460,7 @@ func UnloadModelAnimation(anim ModelAnimation) {
|
||||||
|
|
||||||
// UnloadModelAnimations - Unload animation array data
|
// UnloadModelAnimations - Unload animation array data
|
||||||
func UnloadModelAnimations(animations []ModelAnimation) {
|
func UnloadModelAnimations(animations []ModelAnimation) {
|
||||||
C.UnloadModelAnimations((*C.ModelAnimation)(unsafe.Pointer(&animations[0])), (C.uint)(len(animations)))
|
C.UnloadModelAnimations((*C.ModelAnimation)(unsafe.Pointer(&animations[0])), (C.int)(len(animations)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsModelAnimationValid - Check model animation skeleton match
|
// IsModelAnimationValid - Check model animation skeleton match
|
||||||
|
|
583
raylib/rshapes.c
583
raylib/rshapes.c
|
@ -2,7 +2,7 @@
|
||||||
*
|
*
|
||||||
* rshapes - Basic functions to draw 2d shapes and check collisions
|
* rshapes - Basic functions to draw 2d shapes and check collisions
|
||||||
*
|
*
|
||||||
* NOTES:
|
* ADDITIONAL NOTES:
|
||||||
* Shapes can be draw using 3 types of primitives: LINES, TRIANGLES and QUADS.
|
* Shapes can be draw using 3 types of primitives: LINES, TRIANGLES and QUADS.
|
||||||
* Some functions implement two drawing options: TRIANGLES and QUADS, by default TRIANGLES
|
* Some functions implement two drawing options: TRIANGLES and QUADS, by default TRIANGLES
|
||||||
* are used but QUADS implementation can be selected with SUPPORT_QUADS_DRAW_MODE define
|
* are used but QUADS implementation can be selected with SUPPORT_QUADS_DRAW_MODE define
|
||||||
|
@ -16,7 +16,6 @@
|
||||||
* a single draw call and it also allows users to configure it the same way with their own fonts.
|
* a single draw call and it also allows users to configure it the same way with their own fonts.
|
||||||
*
|
*
|
||||||
* CONFIGURATION:
|
* CONFIGURATION:
|
||||||
*
|
|
||||||
* #define SUPPORT_MODULE_RSHAPES
|
* #define SUPPORT_MODULE_RSHAPES
|
||||||
* rshapes module is included in the build
|
* rshapes module is included in the build
|
||||||
*
|
*
|
||||||
|
@ -68,8 +67,8 @@
|
||||||
#ifndef SMOOTH_CIRCLE_ERROR_RATE
|
#ifndef SMOOTH_CIRCLE_ERROR_RATE
|
||||||
#define SMOOTH_CIRCLE_ERROR_RATE 0.5f // Circle error rate
|
#define SMOOTH_CIRCLE_ERROR_RATE 0.5f // Circle error rate
|
||||||
#endif
|
#endif
|
||||||
#ifndef BEZIER_LINE_DIVISIONS
|
#ifndef SPLINE_LINE_DIVISIONS
|
||||||
#define BEZIER_LINE_DIVISIONS 24 // Bezier line divisions
|
#define SPLINE_LINE_DIVISIONS 24 // Spline lines segment divisions
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -81,7 +80,7 @@
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Global Variables Definition
|
// Global Variables Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
Texture2D texShapes = { 1, 1, 1, 1, 7 }; // Texture used on shapes drawing (usually a white pixel)
|
Texture2D texShapes = { 1, 1, 1, 1, 7 }; // Texture used on shapes drawing (white pixel loaded by rlgl)
|
||||||
Rectangle texShapesRec = { 0.0f, 0.0f, 1.0f, 1.0f }; // Texture source rectangle used on shapes drawing
|
Rectangle texShapesRec = { 0.0f, 0.0f, 1.0f, 1.0f }; // Texture source rectangle used on shapes drawing
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
@ -98,8 +97,19 @@ static float EaseCubicInOut(float t, float b, float c, float d); // Cubic eas
|
||||||
// defining a font char white rectangle would allow drawing everything in a single draw call
|
// defining a font char white rectangle would allow drawing everything in a single draw call
|
||||||
void SetShapesTexture(Texture2D texture, Rectangle source)
|
void SetShapesTexture(Texture2D texture, Rectangle source)
|
||||||
{
|
{
|
||||||
|
// Reset texture to default pixel if required
|
||||||
|
// WARNING: Shapes texture should be probably better validated,
|
||||||
|
// it can break the rendering of all shapes if misused
|
||||||
|
if ((texture.id == 0) || (source.width == 0) || (source.height == 0))
|
||||||
|
{
|
||||||
|
texShapes = (Texture2D){ 1, 1, 1, 1, 7 };
|
||||||
|
texShapesRec = (Rectangle){ 0.0f, 0.0f, 1.0f, 1.0f };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
texShapes = texture;
|
texShapes = texture;
|
||||||
texShapesRec = source;
|
texShapesRec = source;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a pixel
|
// Draw a pixel
|
||||||
|
@ -180,6 +190,7 @@ void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color)
|
||||||
if ((length > 0) && (thick > 0))
|
if ((length > 0) && (thick > 0))
|
||||||
{
|
{
|
||||||
float scale = thick/(2*length);
|
float scale = thick/(2*length);
|
||||||
|
|
||||||
Vector2 radius = { -scale*delta.y, scale*delta.x };
|
Vector2 radius = { -scale*delta.y, scale*delta.x };
|
||||||
Vector2 strip[4] = {
|
Vector2 strip[4] = {
|
||||||
{ startPos.x - radius.x, startPos.y - radius.y },
|
{ startPos.x - radius.x, startPos.y - radius.y },
|
||||||
|
@ -198,126 +209,270 @@ void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color)
|
||||||
Vector2 previous = startPos;
|
Vector2 previous = startPos;
|
||||||
Vector2 current = { 0 };
|
Vector2 current = { 0 };
|
||||||
|
|
||||||
Vector2 points[2*BEZIER_LINE_DIVISIONS + 2] = { 0 };
|
Vector2 points[2*SPLINE_LINE_DIVISIONS + 2] = { 0 };
|
||||||
|
|
||||||
for (int i = 1; i <= BEZIER_LINE_DIVISIONS; i++)
|
for (int i = 1; i <= SPLINE_LINE_DIVISIONS; i++)
|
||||||
{
|
{
|
||||||
// Cubic easing in-out
|
// Cubic easing in-out
|
||||||
// NOTE: Easing is calculated only for y position value
|
// NOTE: Easing is calculated only for y position value
|
||||||
current.y = EaseCubicInOut((float)i, startPos.y, endPos.y - startPos.y, (float)BEZIER_LINE_DIVISIONS);
|
current.y = EaseCubicInOut((float)i, startPos.y, endPos.y - startPos.y, (float)SPLINE_LINE_DIVISIONS);
|
||||||
current.x = previous.x + (endPos.x - startPos.x)/ (float)BEZIER_LINE_DIVISIONS;
|
current.x = previous.x + (endPos.x - startPos.x)/(float)SPLINE_LINE_DIVISIONS;
|
||||||
|
|
||||||
float dy = current.y-previous.y;
|
float dy = current.y - previous.y;
|
||||||
float dx = current.x-previous.x;
|
float dx = current.x - previous.x;
|
||||||
float size = 0.5f*thick/sqrtf(dx*dx+dy*dy);
|
float size = 0.5f*thick/sqrtf(dx*dx+dy*dy);
|
||||||
|
|
||||||
if (i==1)
|
if (i == 1)
|
||||||
{
|
{
|
||||||
points[0].x = previous.x+dy*size;
|
points[0].x = previous.x + dy*size;
|
||||||
points[0].y = previous.y-dx*size;
|
points[0].y = previous.y - dx*size;
|
||||||
points[1].x = previous.x-dy*size;
|
points[1].x = previous.x - dy*size;
|
||||||
points[1].y = previous.y+dx*size;
|
points[1].y = previous.y + dx*size;
|
||||||
}
|
}
|
||||||
|
|
||||||
points[2*i+1].x = current.x-dy*size;
|
points[2*i + 1].x = current.x - dy*size;
|
||||||
points[2*i+1].y = current.y+dx*size;
|
points[2*i + 1].y = current.y + dx*size;
|
||||||
points[2*i].x = current.x+dy*size;
|
points[2*i].x = current.x + dy*size;
|
||||||
points[2*i].y = current.y-dx*size;
|
points[2*i].y = current.y - dx*size;
|
||||||
|
|
||||||
previous = current;
|
previous = current;
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawTriangleStrip(points, 2*BEZIER_LINE_DIVISIONS+2, color);
|
DrawTriangleStrip(points, 2*SPLINE_LINE_DIVISIONS + 2, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw line using quadratic bezier curves with a control point
|
// Draw line using quadratic bezier curves with a control point
|
||||||
void DrawLineBezierQuad(Vector2 startPos, Vector2 endPos, Vector2 controlPos, float thick, Color color)
|
void DrawLineBezierQuad(Vector2 startPos, Vector2 endPos, Vector2 controlPos, float thick, Color color)
|
||||||
{
|
{
|
||||||
const float step = 1.0f/BEZIER_LINE_DIVISIONS;
|
const float step = 1.0f/SPLINE_LINE_DIVISIONS;
|
||||||
|
|
||||||
Vector2 previous = startPos;
|
Vector2 previous = startPos;
|
||||||
Vector2 current = { 0 };
|
Vector2 current = { 0 };
|
||||||
float t = 0.0f;
|
float t = 0.0f;
|
||||||
|
|
||||||
Vector2 points[2*BEZIER_LINE_DIVISIONS + 2] = { 0 };
|
Vector2 points[2*SPLINE_LINE_DIVISIONS + 2] = { 0 };
|
||||||
|
|
||||||
for (int i = 0; i <= BEZIER_LINE_DIVISIONS; i++)
|
for (int i = 1; i <= SPLINE_LINE_DIVISIONS; i++)
|
||||||
{
|
{
|
||||||
t = step*i;
|
t = step*i;
|
||||||
float a = powf(1 - t, 2);
|
|
||||||
float b = 2*(1 - t)*t;
|
float a = powf(1.0f - t, 2);
|
||||||
|
float b = 2.0f*(1.0f - t)*t;
|
||||||
float c = powf(t, 2);
|
float c = powf(t, 2);
|
||||||
|
|
||||||
// NOTE: The easing functions aren't suitable here because they don't take a control point
|
// NOTE: The easing functions aren't suitable here because they don't take a control point
|
||||||
current.y = a*startPos.y + b*controlPos.y + c*endPos.y;
|
current.y = a*startPos.y + b*controlPos.y + c*endPos.y;
|
||||||
current.x = a*startPos.x + b*controlPos.x + c*endPos.x;
|
current.x = a*startPos.x + b*controlPos.x + c*endPos.x;
|
||||||
|
|
||||||
float dy = current.y-previous.y;
|
float dy = current.y - previous.y;
|
||||||
float dx = current.x-previous.x;
|
float dx = current.x - previous.x;
|
||||||
float size = 0.5f*thick/sqrtf(dx*dx+dy*dy);
|
float size = 0.5f*thick/sqrtf(dx*dx+dy*dy);
|
||||||
|
|
||||||
if (i==1)
|
if (i == 1)
|
||||||
{
|
{
|
||||||
points[0].x = previous.x+dy*size;
|
points[0].x = previous.x + dy*size;
|
||||||
points[0].y = previous.y-dx*size;
|
points[0].y = previous.y - dx*size;
|
||||||
points[1].x = previous.x-dy*size;
|
points[1].x = previous.x - dy*size;
|
||||||
points[1].y = previous.y+dx*size;
|
points[1].y = previous.y + dx*size;
|
||||||
}
|
}
|
||||||
|
|
||||||
points[2*i+1].x = current.x-dy*size;
|
points[2*i + 1].x = current.x - dy*size;
|
||||||
points[2*i+1].y = current.y+dx*size;
|
points[2*i + 1].y = current.y + dx*size;
|
||||||
points[2*i].x = current.x+dy*size;
|
points[2*i].x = current.x + dy*size;
|
||||||
points[2*i].y = current.y-dx*size;
|
points[2*i].y = current.y - dx*size;
|
||||||
|
|
||||||
previous = current;
|
previous = current;
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawTriangleStrip(points, 2*BEZIER_LINE_DIVISIONS+2, color);
|
DrawTriangleStrip(points, 2*SPLINE_LINE_DIVISIONS + 2, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw line using cubic bezier curves with 2 control points
|
// Draw line using cubic bezier curves with 2 control points
|
||||||
void DrawLineBezierCubic(Vector2 startPos, Vector2 endPos, Vector2 startControlPos, Vector2 endControlPos, float thick, Color color)
|
void DrawLineBezierCubic(Vector2 startPos, Vector2 endPos, Vector2 startControlPos, Vector2 endControlPos, float thick, Color color)
|
||||||
{
|
{
|
||||||
const float step = 1.0f/BEZIER_LINE_DIVISIONS;
|
const float step = 1.0f/SPLINE_LINE_DIVISIONS;
|
||||||
|
|
||||||
Vector2 previous = startPos;
|
Vector2 previous = startPos;
|
||||||
Vector2 current = { 0 };
|
Vector2 current = { 0 };
|
||||||
float t = 0.0f;
|
float t = 0.0f;
|
||||||
|
|
||||||
Vector2 points[2*BEZIER_LINE_DIVISIONS + 2] = { 0 };
|
Vector2 points[2*SPLINE_LINE_DIVISIONS + 2] = { 0 };
|
||||||
|
|
||||||
for (int i = 0; i <= BEZIER_LINE_DIVISIONS; i++)
|
for (int i = 1; i <= SPLINE_LINE_DIVISIONS; i++)
|
||||||
{
|
{
|
||||||
t = step*i;
|
t = step*i;
|
||||||
float a = powf(1 - t, 3);
|
|
||||||
float b = 3*powf(1 - t, 2)*t;
|
float a = powf(1.0f - t, 3);
|
||||||
float c = 3*(1-t)*powf(t, 2);
|
float b = 3.0f*powf(1.0f - t, 2)*t;
|
||||||
|
float c = 3.0f*(1.0f - t)*powf(t, 2);
|
||||||
float d = powf(t, 3);
|
float d = powf(t, 3);
|
||||||
|
|
||||||
current.y = a*startPos.y + b*startControlPos.y + c*endControlPos.y + d*endPos.y;
|
current.y = a*startPos.y + b*startControlPos.y + c*endControlPos.y + d*endPos.y;
|
||||||
current.x = a*startPos.x + b*startControlPos.x + c*endControlPos.x + d*endPos.x;
|
current.x = a*startPos.x + b*startControlPos.x + c*endControlPos.x + d*endPos.x;
|
||||||
|
|
||||||
float dy = current.y-previous.y;
|
float dy = current.y - previous.y;
|
||||||
float dx = current.x-previous.x;
|
float dx = current.x - previous.x;
|
||||||
float size = 0.5f*thick/sqrtf(dx*dx+dy*dy);
|
float size = 0.5f*thick/sqrtf(dx*dx+dy*dy);
|
||||||
|
|
||||||
if (i==1)
|
if (i == 1)
|
||||||
{
|
{
|
||||||
points[0].x = previous.x+dy*size;
|
points[0].x = previous.x + dy*size;
|
||||||
points[0].y = previous.y-dx*size;
|
points[0].y = previous.y - dx*size;
|
||||||
points[1].x = previous.x-dy*size;
|
points[1].x = previous.x - dy*size;
|
||||||
points[1].y = previous.y+dx*size;
|
points[1].y = previous.y + dx*size;
|
||||||
}
|
}
|
||||||
|
|
||||||
points[2*i+1].x = current.x-dy*size;
|
points[2*i + 1].x = current.x - dy*size;
|
||||||
points[2*i+1].y = current.y+dx*size;
|
points[2*i + 1].y = current.y + dx*size;
|
||||||
points[2*i].x = current.x+dy*size;
|
points[2*i].x = current.x + dy*size;
|
||||||
points[2*i].y = current.y-dx*size;
|
points[2*i].y = current.y - dx*size;
|
||||||
|
|
||||||
previous = current;
|
previous = current;
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawTriangleStrip(points, 2*BEZIER_LINE_DIVISIONS+2, color);
|
DrawTriangleStrip(points, 2*SPLINE_LINE_DIVISIONS + 2, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a B-Spline line, minimum 4 points
|
||||||
|
void DrawLineBSpline(Vector2 *points, int pointCount, float thick, Color color)
|
||||||
|
{
|
||||||
|
if (pointCount < 4) return;
|
||||||
|
|
||||||
|
float a[4] = { 0 };
|
||||||
|
float b[4] = { 0 };
|
||||||
|
float dy = 0.0f;
|
||||||
|
float dx = 0.0f;
|
||||||
|
float size = 0.0f;
|
||||||
|
|
||||||
|
Vector2 currentPoint = { 0 };
|
||||||
|
Vector2 nextPoint = { 0 };
|
||||||
|
Vector2 vertices[2*SPLINE_LINE_DIVISIONS + 2] = { 0 };
|
||||||
|
|
||||||
|
for (int i = 0; i < (pointCount - 3); i++)
|
||||||
|
{
|
||||||
|
float t = 0.0f;
|
||||||
|
Vector2 p1 = points[i], p2 = points[i + 1], p3 = points[i + 2], p4 = points[i + 3];
|
||||||
|
|
||||||
|
a[0] = (-p1.x + 3.0f*p2.x - 3.0f*p3.x + p4.x)/6.0f;
|
||||||
|
a[1] = (3.0f*p1.x - 6.0f*p2.x + 3.0f*p3.x)/6.0f;
|
||||||
|
a[2] = (-3.0f*p1.x + 3.0f*p3.x)/6.0f;
|
||||||
|
a[3] = (p1.x + 4.0f*p2.x + p3.x)/6.0f;
|
||||||
|
|
||||||
|
b[0] = (-p1.y + 3.0f*p2.y - 3.0f*p3.y + p4.y)/6.0f;
|
||||||
|
b[1] = (3.0f*p1.y - 6.0f*p2.y + 3.0f*p3.y)/6.0f;
|
||||||
|
b[2] = (-3.0f*p1.y + 3.0f*p3.y)/6.0f;
|
||||||
|
b[3] = (p1.y + 4.0f*p2.y + p3.y)/6.0f;
|
||||||
|
|
||||||
|
currentPoint.x = a[3];
|
||||||
|
currentPoint.y = b[3];
|
||||||
|
|
||||||
|
if (i == 0) DrawCircleV(currentPoint, thick/2.0f, color); // Draw init line circle-cap
|
||||||
|
|
||||||
|
if (i > 0)
|
||||||
|
{
|
||||||
|
vertices[0].x = currentPoint.x + dy*size;
|
||||||
|
vertices[0].y = currentPoint.y - dx*size;
|
||||||
|
vertices[1].x = currentPoint.x - dy*size;
|
||||||
|
vertices[1].y = currentPoint.y + dx*size;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 1; j <= SPLINE_LINE_DIVISIONS; j++)
|
||||||
|
{
|
||||||
|
t = ((float)j)/((float)SPLINE_LINE_DIVISIONS);
|
||||||
|
|
||||||
|
nextPoint.x = a[3] + t*(a[2] + t*(a[1] + t*a[0]));
|
||||||
|
nextPoint.y = b[3] + t*(b[2] + t*(b[1] + t*b[0]));
|
||||||
|
|
||||||
|
dy = nextPoint.y - currentPoint.y;
|
||||||
|
dx = nextPoint.x - currentPoint.x;
|
||||||
|
size = 0.5f*thick/sqrtf(dx*dx+dy*dy);
|
||||||
|
|
||||||
|
if ((i == 0) && (j == 1))
|
||||||
|
{
|
||||||
|
vertices[0].x = currentPoint.x + dy*size;
|
||||||
|
vertices[0].y = currentPoint.y - dx*size;
|
||||||
|
vertices[1].x = currentPoint.x - dy*size;
|
||||||
|
vertices[1].y = currentPoint.y + dx*size;
|
||||||
|
}
|
||||||
|
|
||||||
|
vertices[2*j + 1].x = nextPoint.x - dy*size;
|
||||||
|
vertices[2*j + 1].y = nextPoint.y + dx*size;
|
||||||
|
vertices[2*j].x = nextPoint.x + dy*size;
|
||||||
|
vertices[2*j].y = nextPoint.y - dx*size;
|
||||||
|
|
||||||
|
currentPoint = nextPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawTriangleStrip(vertices, 2*SPLINE_LINE_DIVISIONS + 2, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawCircleV(currentPoint, thick/2.0f, color); // Draw end line circle-cap
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a Catmull Rom spline line, minimum 4 points
|
||||||
|
void DrawLineCatmullRom(Vector2 *points, int pointCount, float thick, Color color)
|
||||||
|
{
|
||||||
|
if (pointCount < 4) return;
|
||||||
|
|
||||||
|
float dy = 0.0f;
|
||||||
|
float dx = 0.0f;
|
||||||
|
float size = 0.0f;
|
||||||
|
|
||||||
|
Vector2 currentPoint = points[1];
|
||||||
|
Vector2 nextPoint = { 0 };
|
||||||
|
Vector2 vertices[2*SPLINE_LINE_DIVISIONS + 2] = { 0 };
|
||||||
|
|
||||||
|
DrawCircleV(currentPoint, thick/2.0f, color); // Draw init line circle-cap
|
||||||
|
|
||||||
|
for (int i = 0; i < (pointCount - 3); i++)
|
||||||
|
{
|
||||||
|
float t = 0.0f;
|
||||||
|
Vector2 p1 = points[i], p2 = points[i + 1], p3 = points[i + 2], p4 = points[i + 3];
|
||||||
|
|
||||||
|
if (i > 0)
|
||||||
|
{
|
||||||
|
vertices[0].x = currentPoint.x + dy*size;
|
||||||
|
vertices[0].y = currentPoint.y - dx*size;
|
||||||
|
vertices[1].x = currentPoint.x - dy*size;
|
||||||
|
vertices[1].y = currentPoint.y + dx*size;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 1; j <= SPLINE_LINE_DIVISIONS; j++)
|
||||||
|
{
|
||||||
|
t = ((float)j)/((float)SPLINE_LINE_DIVISIONS);
|
||||||
|
|
||||||
|
float q0 = (-1.0f*t*t*t) + (2.0f*t*t) + (-1.0f*t);
|
||||||
|
float q1 = (3.0f*t*t*t) + (-5.0f*t*t) + 2.0f;
|
||||||
|
float q2 = (-3.0f*t*t*t) + (4.0f*t*t) + t;
|
||||||
|
float q3 = t*t*t - t*t;
|
||||||
|
|
||||||
|
nextPoint.x = 0.5f*((p1.x*q0) + (p2.x*q1) + (p3.x*q2) + (p4.x*q3));
|
||||||
|
nextPoint.y = 0.5f*((p1.y*q0) + (p2.y*q1) + (p3.y*q2) + (p4.y*q3));
|
||||||
|
|
||||||
|
dy = nextPoint.y - currentPoint.y;
|
||||||
|
dx = nextPoint.x - currentPoint.x;
|
||||||
|
size = (0.5f*thick)/sqrtf(dx*dx + dy*dy);
|
||||||
|
|
||||||
|
if ((i == 0) && (j == 1))
|
||||||
|
{
|
||||||
|
vertices[0].x = currentPoint.x + dy*size;
|
||||||
|
vertices[0].y = currentPoint.y - dx*size;
|
||||||
|
vertices[1].x = currentPoint.x - dy*size;
|
||||||
|
vertices[1].y = currentPoint.y + dx*size;
|
||||||
|
}
|
||||||
|
|
||||||
|
vertices[2*j + 1].x = nextPoint.x - dy*size;
|
||||||
|
vertices[2*j + 1].y = nextPoint.y + dx*size;
|
||||||
|
vertices[2*j].x = nextPoint.x + dy*size;
|
||||||
|
vertices[2*j].y = nextPoint.y - dx*size;
|
||||||
|
|
||||||
|
currentPoint = nextPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawTriangleStrip(vertices, 2*SPLINE_LINE_DIVISIONS + 2, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawCircleV(currentPoint, thick/2.0f, color); // Draw end line circle-cap
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw lines sequence
|
// Draw lines sequence
|
||||||
|
@ -343,6 +498,13 @@ void DrawCircle(int centerX, int centerY, float radius, Color color)
|
||||||
DrawCircleV((Vector2){ (float)centerX, (float)centerY }, radius, color);
|
DrawCircleV((Vector2){ (float)centerX, (float)centerY }, radius, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw a color-filled circle (Vector version)
|
||||||
|
// NOTE: On OpenGL 3.3 and ES2 we use QUADS to avoid drawing order issues
|
||||||
|
void DrawCircleV(Vector2 center, float radius, Color color)
|
||||||
|
{
|
||||||
|
DrawCircleSector(center, radius, 0, 360, 36, color);
|
||||||
|
}
|
||||||
|
|
||||||
// Draw a piece of a circle
|
// Draw a piece of a circle
|
||||||
void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color)
|
void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color)
|
||||||
{
|
{
|
||||||
|
@ -375,6 +537,7 @@ void DrawCircleSector(Vector2 center, float radius, float startAngle, float endA
|
||||||
rlSetTexture(texShapes.id);
|
rlSetTexture(texShapes.id);
|
||||||
|
|
||||||
rlBegin(RL_QUADS);
|
rlBegin(RL_QUADS);
|
||||||
|
|
||||||
// NOTE: Every QUAD actually represents two segments
|
// NOTE: Every QUAD actually represents two segments
|
||||||
for (int i = 0; i < segments/2; i++)
|
for (int i = 0; i < segments/2; i++)
|
||||||
{
|
{
|
||||||
|
@ -383,35 +546,36 @@ void DrawCircleSector(Vector2 center, float radius, float startAngle, float endA
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlVertex2f(center.x, center.y);
|
rlVertex2f(center.x, center.y);
|
||||||
|
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength*2.0f))*radius, center.y + sinf(DEG2RAD*(angle + stepLength*2.0f))*radius);
|
||||||
|
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*radius, center.y + sinf(DEG2RAD*(angle + stepLength))*radius);
|
||||||
|
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength*2))*radius, center.y + cosf(DEG2RAD*(angle + stepLength*2))*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
|
||||||
|
|
||||||
angle += (stepLength*2);
|
angle += (stepLength*2.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: In case number of segments is odd, we add one last piece to the cake
|
// NOTE: In case number of segments is odd, we add one last piece to the cake
|
||||||
if (segments%2)
|
if ((segments%2) == 1)
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlVertex2f(center.x, center.y);
|
rlVertex2f(center.x, center.y);
|
||||||
|
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
|
|
||||||
|
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*radius, center.y + sinf(DEG2RAD*(angle + stepLength))*radius);
|
||||||
|
|
||||||
|
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
|
||||||
|
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlVertex2f(center.x, center.y);
|
rlVertex2f(center.x, center.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
rlEnd();
|
rlEnd();
|
||||||
|
|
||||||
rlSetTexture(0);
|
rlSetTexture(0);
|
||||||
|
@ -422,8 +586,8 @@ void DrawCircleSector(Vector2 center, float radius, float startAngle, float endA
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
rlVertex2f(center.x, center.y);
|
rlVertex2f(center.x, center.y);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*radius, center.y + sinf(DEG2RAD*(angle + stepLength))*radius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
|
||||||
|
|
||||||
angle += stepLength;
|
angle += stepLength;
|
||||||
}
|
}
|
||||||
|
@ -465,15 +629,15 @@ void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
rlVertex2f(center.x, center.y);
|
rlVertex2f(center.x, center.y);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < segments; i++)
|
for (int i = 0; i < segments; i++)
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*radius, center.y + sinf(DEG2RAD*(angle + stepLength))*radius);
|
||||||
|
|
||||||
angle += stepLength;
|
angle += stepLength;
|
||||||
}
|
}
|
||||||
|
@ -482,7 +646,7 @@ void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
rlVertex2f(center.x, center.y);
|
rlVertex2f(center.x, center.y);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
|
||||||
}
|
}
|
||||||
rlEnd();
|
rlEnd();
|
||||||
}
|
}
|
||||||
|
@ -497,22 +661,21 @@ void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Co
|
||||||
rlColor4ub(color1.r, color1.g, color1.b, color1.a);
|
rlColor4ub(color1.r, color1.g, color1.b, color1.a);
|
||||||
rlVertex2f((float)centerX, (float)centerY);
|
rlVertex2f((float)centerX, (float)centerY);
|
||||||
rlColor4ub(color2.r, color2.g, color2.b, color2.a);
|
rlColor4ub(color2.r, color2.g, color2.b, color2.a);
|
||||||
rlVertex2f((float)centerX + sinf(DEG2RAD*i)*radius, (float)centerY + cosf(DEG2RAD*i)*radius);
|
rlVertex2f((float)centerX + cosf(DEG2RAD*(i + 10))*radius, (float)centerY + sinf(DEG2RAD*(i + 10))*radius);
|
||||||
rlColor4ub(color2.r, color2.g, color2.b, color2.a);
|
rlColor4ub(color2.r, color2.g, color2.b, color2.a);
|
||||||
rlVertex2f((float)centerX + sinf(DEG2RAD*(i + 10))*radius, (float)centerY + cosf(DEG2RAD*(i + 10))*radius);
|
rlVertex2f((float)centerX + cosf(DEG2RAD*i)*radius, (float)centerY + sinf(DEG2RAD*i)*radius);
|
||||||
}
|
}
|
||||||
rlEnd();
|
rlEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a color-filled circle (Vector version)
|
|
||||||
// NOTE: On OpenGL 3.3 and ES2 we use QUADS to avoid drawing order issues
|
|
||||||
void DrawCircleV(Vector2 center, float radius, Color color)
|
|
||||||
{
|
|
||||||
DrawCircleSector(center, radius, 0, 360, 36, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw circle outline
|
// Draw circle outline
|
||||||
void DrawCircleLines(int centerX, int centerY, float radius, Color color)
|
void DrawCircleLines(int centerX, int centerY, float radius, Color color)
|
||||||
|
{
|
||||||
|
DrawCircleLinesV((Vector2){ (float)centerX, (float)centerY }, radius, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw circle outline (Vector version)
|
||||||
|
void DrawCircleLinesV(Vector2 center, float radius, Color color)
|
||||||
{
|
{
|
||||||
rlBegin(RL_LINES);
|
rlBegin(RL_LINES);
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
@ -520,8 +683,8 @@ void DrawCircleLines(int centerX, int centerY, float radius, Color color)
|
||||||
// NOTE: Circle outline is drawn pixel by pixel every degree (0 to 360)
|
// NOTE: Circle outline is drawn pixel by pixel every degree (0 to 360)
|
||||||
for (int i = 0; i < 360; i += 10)
|
for (int i = 0; i < 360; i += 10)
|
||||||
{
|
{
|
||||||
rlVertex2f(centerX + sinf(DEG2RAD*i)*radius, centerY + cosf(DEG2RAD*i)*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*i)*radius, center.y + sinf(DEG2RAD*i)*radius);
|
||||||
rlVertex2f(centerX + sinf(DEG2RAD*(i + 10))*radius, centerY + cosf(DEG2RAD*(i + 10))*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(i + 10))*radius, center.y + sinf(DEG2RAD*(i + 10))*radius);
|
||||||
}
|
}
|
||||||
rlEnd();
|
rlEnd();
|
||||||
}
|
}
|
||||||
|
@ -534,8 +697,8 @@ void DrawEllipse(int centerX, int centerY, float radiusH, float radiusV, Color c
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
rlVertex2f((float)centerX, (float)centerY);
|
rlVertex2f((float)centerX, (float)centerY);
|
||||||
rlVertex2f((float)centerX + sinf(DEG2RAD*i)*radiusH, (float)centerY + cosf(DEG2RAD*i)*radiusV);
|
rlVertex2f((float)centerX + cosf(DEG2RAD*(i + 10))*radiusH, (float)centerY + sinf(DEG2RAD*(i + 10))*radiusV);
|
||||||
rlVertex2f((float)centerX + sinf(DEG2RAD*(i + 10))*radiusH, (float)centerY + cosf(DEG2RAD*(i + 10))*radiusV);
|
rlVertex2f((float)centerX + cosf(DEG2RAD*i)*radiusH, (float)centerY + sinf(DEG2RAD*i)*radiusV);
|
||||||
}
|
}
|
||||||
rlEnd();
|
rlEnd();
|
||||||
}
|
}
|
||||||
|
@ -547,8 +710,8 @@ void DrawEllipseLines(int centerX, int centerY, float radiusH, float radiusV, Co
|
||||||
for (int i = 0; i < 360; i += 10)
|
for (int i = 0; i < 360; i += 10)
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
rlVertex2f(centerX + sinf(DEG2RAD*i)*radiusH, centerY + cosf(DEG2RAD*i)*radiusV);
|
rlVertex2f(centerX + cosf(DEG2RAD*(i + 10))*radiusH, centerY + sinf(DEG2RAD*(i + 10))*radiusV);
|
||||||
rlVertex2f(centerX + sinf(DEG2RAD*(i + 10))*radiusH, centerY + cosf(DEG2RAD*(i + 10))*radiusV);
|
rlVertex2f(centerX + cosf(DEG2RAD*i)*radiusH, centerY + sinf(DEG2RAD*i)*radiusV);
|
||||||
}
|
}
|
||||||
rlEnd();
|
rlEnd();
|
||||||
}
|
}
|
||||||
|
@ -606,17 +769,17 @@ void DrawRing(Vector2 center, float innerRadius, float outerRadius, float startA
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
|
|
||||||
|
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
|
||||||
|
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius);
|
||||||
|
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
|
||||||
|
|
||||||
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius);
|
||||||
|
|
||||||
angle += stepLength;
|
angle += stepLength;
|
||||||
}
|
}
|
||||||
|
@ -629,13 +792,13 @@ void DrawRing(Vector2 center, float innerRadius, float outerRadius, float startA
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
|
||||||
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
|
||||||
|
|
||||||
angle += stepLength;
|
angle += stepLength;
|
||||||
}
|
}
|
||||||
|
@ -692,19 +855,19 @@ void DrawRingLines(Vector2 center, float innerRadius, float outerRadius, float s
|
||||||
if (showCapLines)
|
if (showCapLines)
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < segments; i++)
|
for (int i = 0; i < segments; i++)
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius);
|
||||||
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
|
||||||
|
|
||||||
angle += stepLength;
|
angle += stepLength;
|
||||||
}
|
}
|
||||||
|
@ -712,8 +875,8 @@ void DrawRingLines(Vector2 center, float innerRadius, float outerRadius, float s
|
||||||
if (showCapLines)
|
if (showCapLines)
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius);
|
||||||
}
|
}
|
||||||
rlEnd();
|
rlEnd();
|
||||||
}
|
}
|
||||||
|
@ -972,7 +1135,7 @@ void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color co
|
||||||
};
|
};
|
||||||
|
|
||||||
const Vector2 centers[4] = { point[8], point[9], point[10], point[11] };
|
const Vector2 centers[4] = { point[8], point[9], point[10], point[11] };
|
||||||
const float angles[4] = { 180.0f, 90.0f, 0.0f, 270.0f };
|
const float angles[4] = { 180.0f, 270.0f, 0.0f, 90.0f };
|
||||||
|
|
||||||
#if defined(SUPPORT_QUADS_DRAW_MODE)
|
#if defined(SUPPORT_QUADS_DRAW_MODE)
|
||||||
rlSetTexture(texShapes.id);
|
rlSetTexture(texShapes.id);
|
||||||
|
@ -990,12 +1153,16 @@ void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color co
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlVertex2f(center.x, center.y);
|
rlVertex2f(center.x, center.y);
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
|
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
|
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength*2))*radius, center.y + cosf(DEG2RAD*(angle + stepLength*2))*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength*2))*radius, center.y + sinf(DEG2RAD*(angle + stepLength*2))*radius);
|
||||||
|
|
||||||
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*radius, center.y + sinf(DEG2RAD*(angle + stepLength))*radius);
|
||||||
|
|
||||||
|
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
|
||||||
|
|
||||||
angle += (stepLength*2);
|
angle += (stepLength*2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1005,10 +1172,13 @@ void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color co
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlVertex2f(center.x, center.y);
|
rlVertex2f(center.x, center.y);
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
|
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*radius, center.y + sinf(DEG2RAD*(angle + stepLength))*radius);
|
||||||
|
|
||||||
|
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
|
||||||
|
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlVertex2f(center.x, center.y);
|
rlVertex2f(center.x, center.y);
|
||||||
}
|
}
|
||||||
|
@ -1083,8 +1253,8 @@ void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color co
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
rlVertex2f(center.x, center.y);
|
rlVertex2f(center.x, center.y);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*radius, center.y + sinf(DEG2RAD*(angle + stepLength))*radius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
|
||||||
angle += stepLength;
|
angle += stepLength;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1198,7 +1368,7 @@ void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, flo
|
||||||
{(float)(rec.x + rec.width) - innerRadius, (float)(rec.y + rec.height) - innerRadius}, {(float)rec.x + innerRadius, (float)(rec.y + rec.height) - innerRadius} // P18, P19
|
{(float)(rec.x + rec.width) - innerRadius, (float)(rec.y + rec.height) - innerRadius}, {(float)rec.x + innerRadius, (float)(rec.y + rec.height) - innerRadius} // P18, P19
|
||||||
};
|
};
|
||||||
|
|
||||||
const float angles[4] = { 180.0f, 90.0f, 0.0f, 270.0f };
|
const float angles[4] = { 180.0f, 270.0f, 0.0f, 90.0f };
|
||||||
|
|
||||||
if (lineThick > 1)
|
if (lineThick > 1)
|
||||||
{
|
{
|
||||||
|
@ -1215,14 +1385,18 @@ void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, flo
|
||||||
for (int i = 0; i < segments; i++)
|
for (int i = 0; i < segments; i++)
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius);
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
|
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
|
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
|
||||||
|
|
||||||
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius);
|
||||||
|
|
||||||
|
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
|
||||||
|
|
||||||
angle += stepLength;
|
angle += stepLength;
|
||||||
}
|
}
|
||||||
|
@ -1287,13 +1461,13 @@ void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, flo
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
|
||||||
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
|
||||||
|
|
||||||
angle += stepLength;
|
angle += stepLength;
|
||||||
}
|
}
|
||||||
|
@ -1351,8 +1525,8 @@ void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, flo
|
||||||
for (int i = 0; i < segments; i++)
|
for (int i = 0; i < segments; i++)
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius);
|
||||||
angle += stepLength;
|
angle += stepLength;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1482,7 +1656,8 @@ void DrawTriangleStrip(Vector2 *points, int pointCount, Color color)
|
||||||
void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color)
|
void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color)
|
||||||
{
|
{
|
||||||
if (sides < 3) sides = 3;
|
if (sides < 3) sides = 3;
|
||||||
float centralAngle = rotation;
|
float centralAngle = rotation*DEG2RAD;
|
||||||
|
float angleStep = 360.0f/(float)sides*DEG2RAD;
|
||||||
|
|
||||||
#if defined(SUPPORT_QUADS_DRAW_MODE)
|
#if defined(SUPPORT_QUADS_DRAW_MODE)
|
||||||
rlSetTexture(texShapes.id);
|
rlSetTexture(texShapes.id);
|
||||||
|
@ -1491,19 +1666,21 @@ void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color col
|
||||||
for (int i = 0; i < sides; i++)
|
for (int i = 0; i < sides; i++)
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
float nextAngle = centralAngle + angleStep;
|
||||||
|
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlVertex2f(center.x, center.y);
|
rlVertex2f(center.x, center.y);
|
||||||
|
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*centralAngle)*radius, center.y + cosf(DEG2RAD*centralAngle)*radius);
|
rlVertex2f(center.x + cosf(centralAngle)*radius, center.y + sinf(centralAngle)*radius);
|
||||||
|
|
||||||
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
|
rlVertex2f(center.x + cosf(nextAngle)*radius, center.y + sinf(nextAngle)*radius);
|
||||||
|
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*centralAngle)*radius, center.y + cosf(DEG2RAD*centralAngle)*radius);
|
rlVertex2f(center.x + cosf(centralAngle)*radius, center.y + sinf(centralAngle)*radius);
|
||||||
|
|
||||||
centralAngle += 360.0f/(float)sides;
|
centralAngle = nextAngle;
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*centralAngle)*radius, center.y + cosf(DEG2RAD*centralAngle)*radius);
|
|
||||||
}
|
}
|
||||||
rlEnd();
|
rlEnd();
|
||||||
rlSetTexture(0);
|
rlSetTexture(0);
|
||||||
|
@ -1514,10 +1691,10 @@ void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color col
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
rlVertex2f(center.x, center.y);
|
rlVertex2f(center.x, center.y);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*centralAngle)*radius, center.y + cosf(DEG2RAD*centralAngle)*radius);
|
rlVertex2f(center.x + cosf(centralAngle + angleStep)*radius, center.y + sinf(centralAngle + angleStep)*radius);
|
||||||
|
rlVertex2f(center.x + cosf(centralAngle)*radius, center.y + sinf(centralAngle)*radius);
|
||||||
|
|
||||||
centralAngle += 360.0f/(float)sides;
|
centralAngle += angleStep;
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*centralAngle)*radius, center.y + cosf(DEG2RAD*centralAngle)*radius);
|
|
||||||
}
|
}
|
||||||
rlEnd();
|
rlEnd();
|
||||||
#endif
|
#endif
|
||||||
|
@ -1527,16 +1704,18 @@ void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color col
|
||||||
void DrawPolyLines(Vector2 center, int sides, float radius, float rotation, Color color)
|
void DrawPolyLines(Vector2 center, int sides, float radius, float rotation, Color color)
|
||||||
{
|
{
|
||||||
if (sides < 3) sides = 3;
|
if (sides < 3) sides = 3;
|
||||||
float centralAngle = rotation;
|
float centralAngle = rotation*DEG2RAD;
|
||||||
|
float angleStep = 360.0f/(float)sides*DEG2RAD;
|
||||||
|
|
||||||
rlBegin(RL_LINES);
|
rlBegin(RL_LINES);
|
||||||
for (int i = 0; i < sides; i++)
|
for (int i = 0; i < sides; i++)
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*centralAngle)*radius, center.y + cosf(DEG2RAD*centralAngle)*radius);
|
rlVertex2f(center.x + cosf(centralAngle)*radius, center.y + sinf(centralAngle)*radius);
|
||||||
centralAngle += 360.0f/(float)sides;
|
rlVertex2f(center.x + cosf(centralAngle + angleStep)*radius, center.y + sinf(centralAngle + angleStep)*radius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*centralAngle)*radius, center.y + cosf(DEG2RAD*centralAngle)*radius);
|
|
||||||
|
centralAngle += angleStep;
|
||||||
}
|
}
|
||||||
rlEnd();
|
rlEnd();
|
||||||
}
|
}
|
||||||
|
@ -1544,8 +1723,8 @@ void DrawPolyLines(Vector2 center, int sides, float radius, float rotation, Colo
|
||||||
void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, float lineThick, Color color)
|
void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, float lineThick, Color color)
|
||||||
{
|
{
|
||||||
if (sides < 3) sides = 3;
|
if (sides < 3) sides = 3;
|
||||||
float centralAngle = rotation;
|
float centralAngle = rotation*DEG2RAD;
|
||||||
float exteriorAngle = 360.0f/(float)sides;
|
float exteriorAngle = 360.0f/(float)sides*DEG2RAD;
|
||||||
float innerRadius = radius - (lineThick*cosf(DEG2RAD*exteriorAngle/2.0f));
|
float innerRadius = radius - (lineThick*cosf(DEG2RAD*exteriorAngle/2.0f));
|
||||||
|
|
||||||
#if defined(SUPPORT_QUADS_DRAW_MODE)
|
#if defined(SUPPORT_QUADS_DRAW_MODE)
|
||||||
|
@ -1555,19 +1734,21 @@ void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, fl
|
||||||
for (int i = 0; i < sides; i++)
|
for (int i = 0; i < sides; i++)
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
float nextAngle = centralAngle + exteriorAngle;
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*centralAngle)*innerRadius, center.y + cosf(DEG2RAD*centralAngle)*innerRadius);
|
|
||||||
|
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*centralAngle)*radius, center.y + cosf(DEG2RAD*centralAngle)*radius);
|
rlVertex2f(center.x + cosf(centralAngle)*radius, center.y + sinf(centralAngle)*radius);
|
||||||
|
|
||||||
centralAngle += exteriorAngle;
|
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
rlVertex2f(center.x + cosf(centralAngle)*innerRadius, center.y + sinf(centralAngle)*innerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*centralAngle)*radius, center.y + cosf(DEG2RAD*centralAngle)*radius);
|
|
||||||
|
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*centralAngle)*innerRadius, center.y + cosf(DEG2RAD*centralAngle)*innerRadius);
|
rlVertex2f(center.x + cosf(nextAngle)*innerRadius, center.y + sinf(nextAngle)*innerRadius);
|
||||||
|
|
||||||
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
|
rlVertex2f(center.x + cosf(nextAngle)*radius, center.y + sinf(nextAngle)*radius);
|
||||||
|
|
||||||
|
centralAngle = nextAngle;
|
||||||
}
|
}
|
||||||
rlEnd();
|
rlEnd();
|
||||||
rlSetTexture(0);
|
rlSetTexture(0);
|
||||||
|
@ -1578,13 +1759,13 @@ void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, fl
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
float nextAngle = centralAngle + exteriorAngle;
|
float nextAngle = centralAngle + exteriorAngle;
|
||||||
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*centralAngle)*radius, center.y + cosf(DEG2RAD*centralAngle)*radius);
|
rlVertex2f(center.x + cosf(nextAngle)*radius, center.y + sinf(nextAngle)*radius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*centralAngle)*innerRadius, center.y + cosf(DEG2RAD*centralAngle)*innerRadius);
|
rlVertex2f(center.x + cosf(centralAngle)*radius, center.y + sinf(centralAngle)*radius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*nextAngle)*radius, center.y + cosf(DEG2RAD*nextAngle)*radius);
|
rlVertex2f(center.x + cosf(centralAngle)*innerRadius, center.y + sinf(centralAngle)*innerRadius);
|
||||||
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*centralAngle)*innerRadius, center.y + cosf(DEG2RAD*centralAngle)*innerRadius);
|
rlVertex2f(center.x + cosf(centralAngle)*innerRadius, center.y + sinf(centralAngle)*innerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*nextAngle)*radius, center.y + cosf(DEG2RAD*nextAngle)*radius);
|
rlVertex2f(center.x + cosf(nextAngle)*innerRadius, center.y + sinf(nextAngle)*innerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*nextAngle)*innerRadius, center.y + cosf(DEG2RAD*nextAngle)*innerRadius);
|
rlVertex2f(center.x + cosf(nextAngle)*radius, center.y + sinf(nextAngle)*radius);
|
||||||
|
|
||||||
centralAngle = nextAngle;
|
centralAngle = nextAngle;
|
||||||
}
|
}
|
||||||
|
@ -1601,7 +1782,7 @@ bool CheckCollisionPointRec(Vector2 point, Rectangle rec)
|
||||||
{
|
{
|
||||||
bool collision = false;
|
bool collision = false;
|
||||||
|
|
||||||
if ((point.x >= rec.x) && (point.x <= (rec.x + rec.width)) && (point.y >= rec.y) && (point.y <= (rec.y + rec.height))) collision = true;
|
if ((point.x >= rec.x) && (point.x < (rec.x + rec.width)) && (point.y >= rec.y) && (point.y < (rec.y + rec.height))) collision = true;
|
||||||
|
|
||||||
return collision;
|
return collision;
|
||||||
}
|
}
|
||||||
|
@ -1759,68 +1940,26 @@ bool CheckCollisionPointLine(Vector2 point, Vector2 p1, Vector2 p2, int threshol
|
||||||
// Get collision rectangle for two rectangles collision
|
// Get collision rectangle for two rectangles collision
|
||||||
Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2)
|
Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2)
|
||||||
{
|
{
|
||||||
Rectangle rec = { 0, 0, 0, 0 };
|
Rectangle overlap = { 0 };
|
||||||
|
|
||||||
if (CheckCollisionRecs(rec1, rec2))
|
float left = (rec1.x > rec2.x)? rec1.x : rec2.x;
|
||||||
{
|
float right1 = rec1.x + rec1.width;
|
||||||
float dxx = fabsf(rec1.x - rec2.x);
|
float right2 = rec2.x + rec2.width;
|
||||||
float dyy = fabsf(rec1.y - rec2.y);
|
float right = (right1 < right2)? right1 : right2;
|
||||||
|
float top = (rec1.y > rec2.y)? rec1.y : rec2.y;
|
||||||
|
float bottom1 = rec1.y + rec1.height;
|
||||||
|
float bottom2 = rec2.y + rec2.height;
|
||||||
|
float bottom = (bottom1 < bottom2)? bottom1 : bottom2;
|
||||||
|
|
||||||
if (rec1.x <= rec2.x)
|
if ((left < right) && (top < bottom))
|
||||||
{
|
{
|
||||||
if (rec1.y <= rec2.y)
|
overlap.x = left;
|
||||||
{
|
overlap.y = top;
|
||||||
rec.x = rec2.x;
|
overlap.width = right - left;
|
||||||
rec.y = rec2.y;
|
overlap.height = bottom - top;
|
||||||
rec.width = rec1.width - dxx;
|
|
||||||
rec.height = rec1.height - dyy;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rec.x = rec2.x;
|
|
||||||
rec.y = rec1.y;
|
|
||||||
rec.width = rec1.width - dxx;
|
|
||||||
rec.height = rec2.height - dyy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (rec1.y <= rec2.y)
|
|
||||||
{
|
|
||||||
rec.x = rec1.x;
|
|
||||||
rec.y = rec2.y;
|
|
||||||
rec.width = rec2.width - dxx;
|
|
||||||
rec.height = rec1.height - dyy;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rec.x = rec1.x;
|
|
||||||
rec.y = rec1.y;
|
|
||||||
rec.width = rec2.width - dxx;
|
|
||||||
rec.height = rec2.height - dyy;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rec1.width > rec2.width)
|
return overlap;
|
||||||
{
|
|
||||||
if (rec.width >= rec2.width) rec.width = rec2.width;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (rec.width >= rec1.width) rec.width = rec1.width;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rec1.height > rec2.height)
|
|
||||||
{
|
|
||||||
if (rec.height >= rec2.height) rec.height = rec2.height;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (rec.height >= rec1.height) rec.height = rec1.height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return rec;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
355
raylib/rtext.c
355
raylib/rtext.c
|
@ -3,18 +3,22 @@
|
||||||
* rtext - Basic functions to load fonts and draw text
|
* rtext - Basic functions to load fonts and draw text
|
||||||
*
|
*
|
||||||
* CONFIGURATION:
|
* CONFIGURATION:
|
||||||
*
|
|
||||||
* #define SUPPORT_MODULE_RTEXT
|
* #define SUPPORT_MODULE_RTEXT
|
||||||
* rtext module is included in the build
|
* rtext module is included in the build
|
||||||
*
|
*
|
||||||
|
* #define SUPPORT_DEFAULT_FONT
|
||||||
|
* Load default raylib font on initialization to be used by DrawText() and MeasureText().
|
||||||
|
* If no default font loaded, DrawTextEx() and MeasureTextEx() are required.
|
||||||
|
*
|
||||||
* #define SUPPORT_FILEFORMAT_FNT
|
* #define SUPPORT_FILEFORMAT_FNT
|
||||||
* #define SUPPORT_FILEFORMAT_TTF
|
* #define SUPPORT_FILEFORMAT_TTF
|
||||||
* Selected desired fileformats to be supported for loading. Some of those formats are
|
* Selected desired fileformats to be supported for loading. Some of those formats are
|
||||||
* supported by default, to remove support, just comment unrequired #define in this module
|
* supported by default, to remove support, just comment unrequired #define in this module
|
||||||
*
|
*
|
||||||
* #define SUPPORT_DEFAULT_FONT
|
* #define SUPPORT_FONT_ATLAS_WHITE_REC
|
||||||
* Load default raylib font on initialization to be used by DrawText() and MeasureText().
|
* On font atlas image generation [GenImageFontAtlas()], add a 3x3 pixels white rectangle
|
||||||
* If no default font loaded, DrawTextEx() and MeasureTextEx() are required.
|
* at the bottom-right corner of the atlas. It can be useful to for shapes drawing, to allow
|
||||||
|
* drawing text and shapes with a single draw call [SetShapesTexture()].
|
||||||
*
|
*
|
||||||
* #define TEXTSPLIT_MAX_TEXT_BUFFER_LENGTH
|
* #define TEXTSPLIT_MAX_TEXT_BUFFER_LENGTH
|
||||||
* TextSplit() function static buffer max size
|
* TextSplit() function static buffer max size
|
||||||
|
@ -22,7 +26,6 @@
|
||||||
* #define MAX_TEXTSPLIT_COUNT
|
* #define MAX_TEXTSPLIT_COUNT
|
||||||
* TextSplit() function static substrings pointers array (pointing to static buffer)
|
* TextSplit() function static substrings pointers array (pointing to static buffer)
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* DEPENDENCIES:
|
* DEPENDENCIES:
|
||||||
* stb_truetype - Load TTF file and rasterize characters data
|
* stb_truetype - Load TTF file and rasterize characters data
|
||||||
* stb_rect_pack - Rectangles packing algorithms, required for font atlas generation
|
* stb_rect_pack - Rectangles packing algorithms, required for font atlas generation
|
||||||
|
@ -68,12 +71,21 @@
|
||||||
#include <ctype.h> // Required for: toupper(), tolower() [Used in TextToUpper(), TextToLower()]
|
#include <ctype.h> // Required for: toupper(), tolower() [Used in TextToUpper(), TextToLower()]
|
||||||
|
|
||||||
#if defined(SUPPORT_FILEFORMAT_TTF)
|
#if defined(SUPPORT_FILEFORMAT_TTF)
|
||||||
|
#if defined(__GNUC__) // GCC and Clang
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define STB_RECT_PACK_IMPLEMENTATION
|
#define STB_RECT_PACK_IMPLEMENTATION
|
||||||
#include "external/stb_rect_pack.h" // Required for: ttf font rectangles packaging
|
#include "external/stb_rect_pack.h" // Required for: ttf font rectangles packaging
|
||||||
|
|
||||||
#define STBTT_STATIC
|
#define STBTT_STATIC
|
||||||
#define STB_TRUETYPE_IMPLEMENTATION
|
#define STB_TRUETYPE_IMPLEMENTATION
|
||||||
#include "external/stb_truetype.h" // Required for: ttf font data reading
|
#include "external/stb_truetype.h" // Required for: ttf font data reading
|
||||||
|
|
||||||
|
#if defined(__GNUC__) // GCC and Clang
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
@ -115,6 +127,7 @@ static Font defaultFont = { 0 };
|
||||||
#if defined(SUPPORT_FILEFORMAT_FNT)
|
#if defined(SUPPORT_FILEFORMAT_FNT)
|
||||||
static Font LoadBMFont(const char *fileName); // Load a BMFont file (AngelCode font file)
|
static Font LoadBMFont(const char *fileName); // Load a BMFont file (AngelCode font file)
|
||||||
#endif
|
#endif
|
||||||
|
static int textLineSpacing = 15; // Text vertical line spacing in pixels
|
||||||
|
|
||||||
#if defined(SUPPORT_DEFAULT_FONT)
|
#if defined(SUPPORT_DEFAULT_FONT)
|
||||||
extern void LoadFontDefault(void);
|
extern void LoadFontDefault(void);
|
||||||
|
@ -125,7 +138,6 @@ extern void UnloadFontDefault(void);
|
||||||
// Module Functions Definition
|
// Module Functions Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
#if defined(SUPPORT_DEFAULT_FONT)
|
#if defined(SUPPORT_DEFAULT_FONT)
|
||||||
|
|
||||||
// Load raylib default font
|
// Load raylib default font
|
||||||
extern void LoadFontDefault(void)
|
extern void LoadFontDefault(void)
|
||||||
{
|
{
|
||||||
|
@ -346,18 +358,18 @@ Font LoadFont(const char *fileName)
|
||||||
// Load Font from TTF font file with generation parameters
|
// Load Font from TTF font file with generation parameters
|
||||||
// NOTE: You can pass an array with desired characters, those characters should be available in the font
|
// NOTE: You can pass an array with desired characters, those characters should be available in the font
|
||||||
// if array is NULL, default char set is selected 32..126
|
// if array is NULL, default char set is selected 32..126
|
||||||
Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int glyphCount)
|
Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount)
|
||||||
{
|
{
|
||||||
Font font = { 0 };
|
Font font = { 0 };
|
||||||
|
|
||||||
// Loading file to memory
|
// Loading file to memory
|
||||||
unsigned int fileSize = 0;
|
int dataSize = 0;
|
||||||
unsigned char *fileData = LoadFileData(fileName, &fileSize);
|
unsigned char *fileData = LoadFileData(fileName, &dataSize);
|
||||||
|
|
||||||
if (fileData != NULL)
|
if (fileData != NULL)
|
||||||
{
|
{
|
||||||
// Loading font from memory data
|
// Loading font from memory data
|
||||||
font = LoadFontFromMemory(GetFileExtension(fileName), fileData, fileSize, fontSize, fontChars, glyphCount);
|
font = LoadFontFromMemory(GetFileExtension(fileName), fileData, dataSize, fontSize, codepoints, codepointCount);
|
||||||
|
|
||||||
UnloadFileData(fileData);
|
UnloadFileData(fileData);
|
||||||
}
|
}
|
||||||
|
@ -492,7 +504,7 @@ Font LoadFontFromImage(Image image, Color key, int firstChar)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load font from memory buffer, fileType refers to extension: i.e. ".ttf"
|
// Load font from memory buffer, fileType refers to extension: i.e. ".ttf"
|
||||||
Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int glyphCount)
|
Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount)
|
||||||
{
|
{
|
||||||
Font font = { 0 };
|
Font font = { 0 };
|
||||||
|
|
||||||
|
@ -504,9 +516,9 @@ Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int
|
||||||
TextIsEqual(fileExtLower, ".otf"))
|
TextIsEqual(fileExtLower, ".otf"))
|
||||||
{
|
{
|
||||||
font.baseSize = fontSize;
|
font.baseSize = fontSize;
|
||||||
font.glyphCount = (glyphCount > 0)? glyphCount : 95;
|
font.glyphCount = (codepointCount > 0)? codepointCount : 95;
|
||||||
font.glyphPadding = 0;
|
font.glyphPadding = 0;
|
||||||
font.glyphs = LoadFontData(fileData, dataSize, font.baseSize, fontChars, font.glyphCount, FONT_DEFAULT);
|
font.glyphs = LoadFontData(fileData, dataSize, font.baseSize, codepoints, font.glyphCount, FONT_DEFAULT);
|
||||||
|
|
||||||
if (font.glyphs != NULL)
|
if (font.glyphs != NULL)
|
||||||
{
|
{
|
||||||
|
@ -550,7 +562,7 @@ bool IsFontReady(Font font)
|
||||||
|
|
||||||
// Load font data for further use
|
// Load font data for further use
|
||||||
// NOTE: Requires TTF font memory data and can generate SDF data
|
// NOTE: Requires TTF font memory data and can generate SDF data
|
||||||
GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int glyphCount, int type)
|
GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount, int type)
|
||||||
{
|
{
|
||||||
// NOTE: Using some SDF generation default values,
|
// NOTE: Using some SDF generation default values,
|
||||||
// trades off precision with ability to handle *smaller* sizes
|
// trades off precision with ability to handle *smaller* sizes
|
||||||
|
@ -588,25 +600,25 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
|
||||||
stbtt_GetFontVMetrics(&fontInfo, &ascent, &descent, &lineGap);
|
stbtt_GetFontVMetrics(&fontInfo, &ascent, &descent, &lineGap);
|
||||||
|
|
||||||
// In case no chars count provided, default to 95
|
// In case no chars count provided, default to 95
|
||||||
glyphCount = (glyphCount > 0)? glyphCount : 95;
|
codepointCount = (codepointCount > 0)? codepointCount : 95;
|
||||||
|
|
||||||
// Fill fontChars in case not provided externally
|
// Fill fontChars in case not provided externally
|
||||||
// NOTE: By default we fill glyphCount consecutively, starting at 32 (Space)
|
// NOTE: By default we fill glyphCount consecutively, starting at 32 (Space)
|
||||||
|
|
||||||
if (fontChars == NULL)
|
if (codepoints == NULL)
|
||||||
{
|
{
|
||||||
fontChars = (int *)RL_MALLOC(glyphCount*sizeof(int));
|
codepoints = (int *)RL_MALLOC(codepointCount*sizeof(int));
|
||||||
for (int i = 0; i < glyphCount; i++) fontChars[i] = i + 32;
|
for (int i = 0; i < codepointCount; i++) codepoints[i] = i + 32;
|
||||||
genFontChars = true;
|
genFontChars = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
chars = (GlyphInfo *)RL_MALLOC(glyphCount*sizeof(GlyphInfo));
|
chars = (GlyphInfo *)RL_MALLOC(codepointCount*sizeof(GlyphInfo));
|
||||||
|
|
||||||
// NOTE: Using simple packaging, one char after another
|
// NOTE: Using simple packaging, one char after another
|
||||||
for (int i = 0; i < glyphCount; i++)
|
for (int i = 0; i < codepointCount; i++)
|
||||||
{
|
{
|
||||||
int chw = 0, chh = 0; // Character width and height (on generation)
|
int chw = 0, chh = 0; // Character width and height (on generation)
|
||||||
int ch = fontChars[i]; // Character value to get info for
|
int ch = codepoints[i]; // Character value to get info for
|
||||||
chars[i].value = ch;
|
chars[i].value = ch;
|
||||||
|
|
||||||
// Render a unicode codepoint to a bitmap
|
// Render a unicode codepoint to a bitmap
|
||||||
|
@ -666,7 +678,7 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
|
||||||
}
|
}
|
||||||
else TRACELOG(LOG_WARNING, "FONT: Failed to process TTF font data");
|
else TRACELOG(LOG_WARNING, "FONT: Failed to process TTF font data");
|
||||||
|
|
||||||
if (genFontChars) RL_FREE(fontChars);
|
if (genFontChars) RL_FREE(codepoints);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -676,17 +688,17 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
|
||||||
// Generate image font atlas using chars info
|
// Generate image font atlas using chars info
|
||||||
// NOTE: Packing method: 0-Default, 1-Skyline
|
// NOTE: Packing method: 0-Default, 1-Skyline
|
||||||
#if defined(SUPPORT_FILEFORMAT_TTF)
|
#if defined(SUPPORT_FILEFORMAT_TTF)
|
||||||
Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphCount, int fontSize, int padding, int packMethod)
|
Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyphCount, int fontSize, int padding, int packMethod)
|
||||||
{
|
{
|
||||||
Image atlas = { 0 };
|
Image atlas = { 0 };
|
||||||
|
|
||||||
if (chars == NULL)
|
if (glyphs == NULL)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "FONT: Provided chars info not valid, returning empty image atlas");
|
TRACELOG(LOG_WARNING, "FONT: Provided chars info not valid, returning empty image atlas");
|
||||||
return atlas;
|
return atlas;
|
||||||
}
|
}
|
||||||
|
|
||||||
*charRecs = NULL;
|
*glyphRecs = NULL;
|
||||||
|
|
||||||
// In case no chars count provided we suppose default of 95
|
// In case no chars count provided we suppose default of 95
|
||||||
glyphCount = (glyphCount > 0)? glyphCount : 95;
|
glyphCount = (glyphCount > 0)? glyphCount : 95;
|
||||||
|
@ -694,17 +706,48 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
|
||||||
// NOTE: Rectangles memory is loaded here!
|
// NOTE: Rectangles memory is loaded here!
|
||||||
Rectangle *recs = (Rectangle *)RL_MALLOC(glyphCount*sizeof(Rectangle));
|
Rectangle *recs = (Rectangle *)RL_MALLOC(glyphCount*sizeof(Rectangle));
|
||||||
|
|
||||||
// Calculate image size based on required pixel area
|
// Calculate image size based on total glyph width and glyph row count
|
||||||
// NOTE 1: Image is forced to be squared and POT... very conservative!
|
int totalWidth = 0;
|
||||||
// NOTE 2: SDF font characters already contain an internal padding,
|
int maxGlyphWidth = 0;
|
||||||
// so image size would result bigger than default font type
|
|
||||||
float requiredArea = 0;
|
for (int i = 0; i < glyphCount; i++)
|
||||||
for (int i = 0; i < glyphCount; i++) requiredArea += ((chars[i].image.width + 2*padding)*(fontSize + 2*padding));
|
{
|
||||||
float guessSize = sqrtf(requiredArea)*1.4f;
|
if (glyphs[i].image.width > maxGlyphWidth) maxGlyphWidth = glyphs[i].image.width;
|
||||||
int imageSize = (int)powf(2, ceilf(logf((float)guessSize)/logf(2))); // Calculate next POT
|
totalWidth += glyphs[i].image.width + 4*padding;
|
||||||
|
}
|
||||||
|
|
||||||
|
//#define SUPPORT_FONT_ATLAS_SIZE_CONSERVATIVE
|
||||||
|
#if defined(SUPPORT_FONT_ATLAS_SIZE_CONSERVATIVE)
|
||||||
|
int rowCount = 0;
|
||||||
|
int imageSize = 64; // Define minimum starting value to avoid unnecessary calculation steps for very small images
|
||||||
|
|
||||||
|
// NOTE: maxGlyphWidth is maximum possible space left at the end of row
|
||||||
|
while (totalWidth > (imageSize - maxGlyphWidth)*rowCount)
|
||||||
|
{
|
||||||
|
imageSize *= 2; // Double the size of image (to keep POT)
|
||||||
|
rowCount = imageSize/(fontSize + 2*padding); // Calculate new row count for the new image size
|
||||||
|
}
|
||||||
|
|
||||||
atlas.width = imageSize; // Atlas bitmap width
|
atlas.width = imageSize; // Atlas bitmap width
|
||||||
atlas.height = imageSize; // Atlas bitmap height
|
atlas.height = imageSize; // Atlas bitmap height
|
||||||
|
#else
|
||||||
|
// No need for a so-conservative atlas generation
|
||||||
|
float totalArea = totalWidth*fontSize*1.2f;
|
||||||
|
float imageMinSize = sqrtf(totalArea);
|
||||||
|
int imageSize = (int)powf(2, ceilf(logf(imageMinSize)/logf(2)));
|
||||||
|
|
||||||
|
if (totalArea < ((imageSize*imageSize)/2))
|
||||||
|
{
|
||||||
|
atlas.width = imageSize; // Atlas bitmap width
|
||||||
|
atlas.height = imageSize/2; // Atlas bitmap height
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
atlas.width = imageSize; // Atlas bitmap width
|
||||||
|
atlas.height = imageSize; // Atlas bitmap height
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
atlas.data = (unsigned char *)RL_CALLOC(1, atlas.width*atlas.height); // Create a bitmap to store characters (8 bpp)
|
atlas.data = (unsigned char *)RL_CALLOC(1, atlas.width*atlas.height); // Create a bitmap to store characters (8 bpp)
|
||||||
atlas.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE;
|
atlas.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE;
|
||||||
atlas.mipmaps = 1;
|
atlas.mipmaps = 1;
|
||||||
|
@ -720,25 +763,8 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
|
||||||
// NOTE: Using simple packaging, one char after another
|
// NOTE: Using simple packaging, one char after another
|
||||||
for (int i = 0; i < glyphCount; i++)
|
for (int i = 0; i < glyphCount; i++)
|
||||||
{
|
{
|
||||||
// Copy pixel data from fc.data to atlas
|
// Check remaining space for glyph
|
||||||
for (int y = 0; y < chars[i].image.height; y++)
|
if (offsetX >= (atlas.width - glyphs[i].image.width - 2*padding))
|
||||||
{
|
|
||||||
for (int x = 0; x < chars[i].image.width; x++)
|
|
||||||
{
|
|
||||||
((unsigned char *)atlas.data)[(offsetY + y)*atlas.width + (offsetX + x)] = ((unsigned char *)chars[i].image.data)[y*chars[i].image.width + x];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill chars rectangles in atlas info
|
|
||||||
recs[i].x = (float)offsetX;
|
|
||||||
recs[i].y = (float)offsetY;
|
|
||||||
recs[i].width = (float)chars[i].image.width;
|
|
||||||
recs[i].height = (float)chars[i].image.height;
|
|
||||||
|
|
||||||
// Move atlas position X for next character drawing
|
|
||||||
offsetX += (chars[i].image.width + 2*padding);
|
|
||||||
|
|
||||||
if (offsetX >= (atlas.width - chars[i].image.width - 2*padding))
|
|
||||||
{
|
{
|
||||||
offsetX = padding;
|
offsetX = padding;
|
||||||
|
|
||||||
|
@ -761,6 +787,24 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy pixel data from glyph image to atlas
|
||||||
|
for (int y = 0; y < glyphs[i].image.height; y++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < glyphs[i].image.width; x++)
|
||||||
|
{
|
||||||
|
((unsigned char *)atlas.data)[(offsetY + y)*atlas.width + (offsetX + x)] = ((unsigned char *)glyphs[i].image.data)[y*glyphs[i].image.width + x];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill chars rectangles in atlas info
|
||||||
|
recs[i].x = (float)offsetX;
|
||||||
|
recs[i].y = (float)offsetY;
|
||||||
|
recs[i].width = (float)glyphs[i].image.width;
|
||||||
|
recs[i].height = (float)glyphs[i].image.height;
|
||||||
|
|
||||||
|
// Move atlas position X for next character drawing
|
||||||
|
offsetX += (glyphs[i].image.width + 2*padding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (packMethod == 1) // Use Skyline rect packing algorithm (stb_pack_rect)
|
else if (packMethod == 1) // Use Skyline rect packing algorithm (stb_pack_rect)
|
||||||
|
@ -775,8 +819,8 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
|
||||||
for (int i = 0; i < glyphCount; i++)
|
for (int i = 0; i < glyphCount; i++)
|
||||||
{
|
{
|
||||||
rects[i].id = i;
|
rects[i].id = i;
|
||||||
rects[i].w = chars[i].image.width + 2*padding;
|
rects[i].w = glyphs[i].image.width + 2*padding;
|
||||||
rects[i].h = chars[i].image.height + 2*padding;
|
rects[i].h = glyphs[i].image.height + 2*padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Package rectangles into atlas
|
// Package rectangles into atlas
|
||||||
|
@ -787,17 +831,17 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
|
||||||
// It returns char rectangles in atlas
|
// It returns char rectangles in atlas
|
||||||
recs[i].x = rects[i].x + (float)padding;
|
recs[i].x = rects[i].x + (float)padding;
|
||||||
recs[i].y = rects[i].y + (float)padding;
|
recs[i].y = rects[i].y + (float)padding;
|
||||||
recs[i].width = (float)chars[i].image.width;
|
recs[i].width = (float)glyphs[i].image.width;
|
||||||
recs[i].height = (float)chars[i].image.height;
|
recs[i].height = (float)glyphs[i].image.height;
|
||||||
|
|
||||||
if (rects[i].was_packed)
|
if (rects[i].was_packed)
|
||||||
{
|
{
|
||||||
// Copy pixel data from fc.data to atlas
|
// Copy pixel data from fc.data to atlas
|
||||||
for (int y = 0; y < chars[i].image.height; y++)
|
for (int y = 0; y < glyphs[i].image.height; y++)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < chars[i].image.width; x++)
|
for (int x = 0; x < glyphs[i].image.width; x++)
|
||||||
{
|
{
|
||||||
((unsigned char *)atlas.data)[(rects[i].y + padding + y)*atlas.width + (rects[i].x + padding + x)] = ((unsigned char *)chars[i].image.data)[y*chars[i].image.width + x];
|
((unsigned char *)atlas.data)[(rects[i].y + padding + y)*atlas.width + (rects[i].x + padding + x)] = ((unsigned char *)glyphs[i].image.data)[y*glyphs[i].image.width + x];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -809,6 +853,19 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
|
||||||
RL_FREE(context);
|
RL_FREE(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(SUPPORT_FONT_ATLAS_WHITE_REC)
|
||||||
|
// Add a 3x3 white rectangle at the bottom-right corner of the generated atlas,
|
||||||
|
// useful to use as the white texture to draw shapes with raylib, using this rectangle
|
||||||
|
// shapes and text can be backed into a single draw call: SetShapesTexture()
|
||||||
|
for (int i = 0, k = atlas.width*atlas.height - 1; i < 3; i++)
|
||||||
|
{
|
||||||
|
((unsigned char *)atlas.data)[k - 0] = 255;
|
||||||
|
((unsigned char *)atlas.data)[k - 1] = 255;
|
||||||
|
((unsigned char *)atlas.data)[k - 2] = 255;
|
||||||
|
k -= atlas.width;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Convert image data from GRAYSCALE to GRAY_ALPHA
|
// Convert image data from GRAYSCALE to GRAY_ALPHA
|
||||||
unsigned char *dataGrayAlpha = (unsigned char *)RL_MALLOC(atlas.width*atlas.height*sizeof(unsigned char)*2); // Two channels
|
unsigned char *dataGrayAlpha = (unsigned char *)RL_MALLOC(atlas.width*atlas.height*sizeof(unsigned char)*2); // Two channels
|
||||||
|
|
||||||
|
@ -822,7 +879,7 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
|
||||||
atlas.data = dataGrayAlpha;
|
atlas.data = dataGrayAlpha;
|
||||||
atlas.format = PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA;
|
atlas.format = PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA;
|
||||||
|
|
||||||
*charRecs = recs;
|
*glyphRecs = recs;
|
||||||
|
|
||||||
return atlas;
|
return atlas;
|
||||||
}
|
}
|
||||||
|
@ -918,7 +975,7 @@ bool ExportFontAsCode(Font font, const char *fileName)
|
||||||
byteCount += sprintf(txtData + byteCount, "static unsigned char fontData_%s[COMPRESSED_DATA_SIZE_FONT_%s] = { ", fileNamePascal, TextToUpper(fileNamePascal));
|
byteCount += sprintf(txtData + byteCount, "static unsigned char fontData_%s[COMPRESSED_DATA_SIZE_FONT_%s] = { ", fileNamePascal, TextToUpper(fileNamePascal));
|
||||||
for (int i = 0; i < compDataSize - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%02x,\n " : "0x%02x, "), compData[i]);
|
for (int i = 0; i < compDataSize - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%02x,\n " : "0x%02x, "), compData[i]);
|
||||||
byteCount += sprintf(txtData + byteCount, "0x%02x };\n\n", compData[compDataSize - 1]);
|
byteCount += sprintf(txtData + byteCount, "0x%02x };\n\n", compData[compDataSize - 1]);
|
||||||
MemFree(compData);
|
RL_FREE(compData);
|
||||||
#else
|
#else
|
||||||
// Save font image data (uncompressed)
|
// Save font image data (uncompressed)
|
||||||
byteCount += sprintf(txtData + byteCount, "// Font image pixels data\n");
|
byteCount += sprintf(txtData + byteCount, "// Font image pixels data\n");
|
||||||
|
@ -1018,7 +1075,7 @@ void DrawFPS(int posX, int posY)
|
||||||
if ((fps < 30) && (fps >= 15)) color = ORANGE; // Warning FPS
|
if ((fps < 30) && (fps >= 15)) color = ORANGE; // Warning FPS
|
||||||
else if (fps < 15) color = RED; // Low FPS
|
else if (fps < 15) color = RED; // Low FPS
|
||||||
|
|
||||||
DrawText(TextFormat("%2i FPS", GetFPS()), posX, posY, 20, color);
|
DrawText(TextFormat("%2i FPS", fps), posX, posY, 20, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw text (using default font)
|
// Draw text (using default font)
|
||||||
|
@ -1059,15 +1116,10 @@ void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, f
|
||||||
int codepoint = GetCodepointNext(&text[i], &codepointByteCount);
|
int codepoint = GetCodepointNext(&text[i], &codepointByteCount);
|
||||||
int index = GetGlyphIndex(font, codepoint);
|
int index = GetGlyphIndex(font, codepoint);
|
||||||
|
|
||||||
// NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
|
|
||||||
// but we need to draw all the bad bytes using the '?' symbol moving one byte
|
|
||||||
if (codepoint == 0x3f) codepointByteCount = 1;
|
|
||||||
|
|
||||||
if (codepoint == '\n')
|
if (codepoint == '\n')
|
||||||
{
|
{
|
||||||
// NOTE: Fixed line spacing of 1.5 line-height
|
// NOTE: Line spacing is a global variable, use SetTextLineSpacing() to setup
|
||||||
// TODO: Support custom line spacing defined by user
|
textOffsetY += textLineSpacing;
|
||||||
textOffsetY += (int)((font.baseSize + font.baseSize/2.0f)*scaleFactor);
|
|
||||||
textOffsetX = 0.0f;
|
textOffsetX = 0.0f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1124,22 +1176,21 @@ void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSiz
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw multiple character (codepoints)
|
// Draw multiple character (codepoints)
|
||||||
void DrawTextCodepoints(Font font, const int *codepoints, int count, Vector2 position, float fontSize, float spacing, Color tint)
|
void DrawTextCodepoints(Font font, const int *codepoints, int codepointCount, Vector2 position, float fontSize, float spacing, Color tint)
|
||||||
{
|
{
|
||||||
int textOffsetY = 0; // Offset between lines (on linebreak '\n')
|
int textOffsetY = 0; // Offset between lines (on linebreak '\n')
|
||||||
float textOffsetX = 0.0f; // Offset X to next character to draw
|
float textOffsetX = 0.0f; // Offset X to next character to draw
|
||||||
|
|
||||||
float scaleFactor = fontSize/font.baseSize; // Character quad scaling factor
|
float scaleFactor = fontSize/font.baseSize; // Character quad scaling factor
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < codepointCount; i++)
|
||||||
{
|
{
|
||||||
int index = GetGlyphIndex(font, codepoints[i]);
|
int index = GetGlyphIndex(font, codepoints[i]);
|
||||||
|
|
||||||
if (codepoints[i] == '\n')
|
if (codepoints[i] == '\n')
|
||||||
{
|
{
|
||||||
// NOTE: Fixed line spacing of 1.5 line-height
|
// NOTE: Line spacing is a global variable, use SetTextLineSpacing() to setup
|
||||||
// TODO: Support custom line spacing defined by user
|
textOffsetY += textLineSpacing;
|
||||||
textOffsetY += (int)((font.baseSize + font.baseSize/2.0f)*scaleFactor);
|
|
||||||
textOffsetX = 0.0f;
|
textOffsetX = 0.0f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1155,6 +1206,12 @@ void DrawTextCodepoints(Font font, const int *codepoints, int count, Vector2 pos
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set vertical line spacing when drawing with line-breaks
|
||||||
|
void SetTextLineSpacing(int spacing)
|
||||||
|
{
|
||||||
|
textLineSpacing = spacing;
|
||||||
|
}
|
||||||
|
|
||||||
// Measure string width for default font
|
// Measure string width for default font
|
||||||
int MeasureText(const char *text, int fontSize)
|
int MeasureText(const char *text, int fontSize)
|
||||||
{
|
{
|
||||||
|
@ -1193,7 +1250,7 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
|
||||||
int letter = 0; // Current character
|
int letter = 0; // Current character
|
||||||
int index = 0; // Index position in sprite font
|
int index = 0; // Index position in sprite font
|
||||||
|
|
||||||
for (int i = 0; i < size; i++)
|
for (int i = 0; i < size;)
|
||||||
{
|
{
|
||||||
byteCounter++;
|
byteCounter++;
|
||||||
|
|
||||||
|
@ -1201,10 +1258,7 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
|
||||||
letter = GetCodepointNext(&text[i], &next);
|
letter = GetCodepointNext(&text[i], &next);
|
||||||
index = GetGlyphIndex(font, letter);
|
index = GetGlyphIndex(font, letter);
|
||||||
|
|
||||||
// NOTE: normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
|
i += next;
|
||||||
// but we need to draw all the bad bytes using the '?' symbol so to not skip any we set next = 1
|
|
||||||
if (letter == 0x3f) next = 1;
|
|
||||||
i += next - 1;
|
|
||||||
|
|
||||||
if (letter != '\n')
|
if (letter != '\n')
|
||||||
{
|
{
|
||||||
|
@ -1216,7 +1270,9 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
|
||||||
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
|
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
|
||||||
byteCounter = 0;
|
byteCounter = 0;
|
||||||
textWidth = 0;
|
textWidth = 0;
|
||||||
textHeight += ((float)font.baseSize*1.5f); // NOTE: Fixed line spacing of 1.5 lines
|
|
||||||
|
// NOTE: Line spacing is a global variable, use SetTextLineSpacing() to setup
|
||||||
|
textHeight += (float)textLineSpacing;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tempByteCounter < byteCounter) tempByteCounter = byteCounter;
|
if (tempByteCounter < byteCounter) tempByteCounter = byteCounter;
|
||||||
|
@ -1224,7 +1280,7 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
|
||||||
|
|
||||||
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
|
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
|
||||||
|
|
||||||
textSize.x = tempTextWidth*scaleFactor + (float)((tempByteCounter - 1)*spacing); // Adds chars spacing to measure
|
textSize.x = tempTextWidth*scaleFactor + (float)((tempByteCounter - 1)*spacing);
|
||||||
textSize.y = textHeight*scaleFactor;
|
textSize.y = textHeight*scaleFactor;
|
||||||
|
|
||||||
return textSize;
|
return textSize;
|
||||||
|
@ -1234,17 +1290,17 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
|
||||||
// NOTE: If codepoint is not found in the font it fallbacks to '?'
|
// NOTE: If codepoint is not found in the font it fallbacks to '?'
|
||||||
int GetGlyphIndex(Font font, int codepoint)
|
int GetGlyphIndex(Font font, int codepoint)
|
||||||
{
|
{
|
||||||
#ifndef GLYPH_NOTFOUND_CHAR_FALLBACK
|
int index = 0;
|
||||||
#define GLYPH_NOTFOUND_CHAR_FALLBACK 63 // Character used if requested codepoint is not found: '?'
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Support charsets with any characters order
|
|
||||||
#define SUPPORT_UNORDERED_CHARSET
|
#define SUPPORT_UNORDERED_CHARSET
|
||||||
#if defined(SUPPORT_UNORDERED_CHARSET)
|
#if defined(SUPPORT_UNORDERED_CHARSET)
|
||||||
int index = GLYPH_NOTFOUND_CHAR_FALLBACK;
|
int fallbackIndex = 0; // Get index of fallback glyph '?'
|
||||||
|
|
||||||
|
// Look for character index in the unordered charset
|
||||||
for (int i = 0; i < font.glyphCount; i++)
|
for (int i = 0; i < font.glyphCount; i++)
|
||||||
{
|
{
|
||||||
|
if (font.glyphs[i].value == 63) fallbackIndex = i;
|
||||||
|
|
||||||
if (font.glyphs[i].value == codepoint)
|
if (font.glyphs[i].value == codepoint)
|
||||||
{
|
{
|
||||||
index = i;
|
index = i;
|
||||||
|
@ -1252,10 +1308,12 @@ int GetGlyphIndex(Font font, int codepoint)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return index;
|
if ((index == 0) && (font.glyphs[0].value != codepoint)) index = fallbackIndex;
|
||||||
#else
|
#else
|
||||||
return (codepoint - 32);
|
index = codepoint - 32;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get glyph font info data for a codepoint (unicode character)
|
// Get glyph font info data for a codepoint (unicode character)
|
||||||
|
@ -1286,10 +1344,12 @@ Rectangle GetGlyphAtlasRec(Font font, int codepoint)
|
||||||
// Get text length in bytes, check for \0 character
|
// Get text length in bytes, check for \0 character
|
||||||
unsigned int TextLength(const char *text)
|
unsigned int TextLength(const char *text)
|
||||||
{
|
{
|
||||||
unsigned int length = 0; //strlen(text)
|
unsigned int length = 0;
|
||||||
|
|
||||||
if (text != NULL)
|
if (text != NULL)
|
||||||
{
|
{
|
||||||
|
// NOTE: Alternative: use strlen(text)
|
||||||
|
|
||||||
while (*text++) length++;
|
while (*text++) length++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1313,15 +1373,24 @@ const char *TextFormat(const char *text, ...)
|
||||||
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, text);
|
va_start(args, text);
|
||||||
vsnprintf(currentBuffer, MAX_TEXT_BUFFER_LENGTH, text, args);
|
int requiredByteCount = vsnprintf(currentBuffer, MAX_TEXT_BUFFER_LENGTH, text, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
|
// If requiredByteCount is larger than the MAX_TEXT_BUFFER_LENGTH, then overflow occured
|
||||||
|
if (requiredByteCount >= MAX_TEXT_BUFFER_LENGTH)
|
||||||
|
{
|
||||||
|
// Inserting "..." at the end of the string to mark as truncated
|
||||||
|
char *truncBuffer = buffers[index] + MAX_TEXT_BUFFER_LENGTH - 4; // Adding 4 bytes = "...\0"
|
||||||
|
sprintf(truncBuffer, "...");
|
||||||
|
}
|
||||||
|
|
||||||
index += 1; // Move to next buffer for next function call
|
index += 1; // Move to next buffer for next function call
|
||||||
if (index >= MAX_TEXTFORMAT_BUFFERS) index = 0;
|
if (index >= MAX_TEXTFORMAT_BUFFERS) index = 0;
|
||||||
|
|
||||||
return currentBuffer;
|
return currentBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Get integer value from text
|
// Get integer value from text
|
||||||
// NOTE: This function replaces atoi() [stdlib.h]
|
// NOTE: This function replaces atoi() [stdlib.h]
|
||||||
int TextToInteger(const char *text)
|
int TextToInteger(const char *text)
|
||||||
|
@ -1335,7 +1404,7 @@ int TextToInteger(const char *text)
|
||||||
text++;
|
text++;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; ((text[i] >= '0') && (text[i] <= '9')); ++i) value = value*10 + (int)(text[i] - '0');
|
for (int i = 0; ((text[i] >= '0') && (text[i] <= '9')); i++) value = value*10 + (int)(text[i] - '0');
|
||||||
|
|
||||||
return value*sign;
|
return value*sign;
|
||||||
}
|
}
|
||||||
|
@ -1348,6 +1417,8 @@ int TextCopy(char *dst, const char *src)
|
||||||
|
|
||||||
if ((src != NULL) && (dst != NULL))
|
if ((src != NULL) && (dst != NULL))
|
||||||
{
|
{
|
||||||
|
// NOTE: Alternative: use strcpy(dst, src)
|
||||||
|
|
||||||
while (*src != '\0')
|
while (*src != '\0')
|
||||||
{
|
{
|
||||||
*dst = *src;
|
*dst = *src;
|
||||||
|
@ -1393,6 +1464,8 @@ const char *TextSubtext(const char *text, int position, int length)
|
||||||
|
|
||||||
if (length >= textLength) length = textLength;
|
if (length >= textLength) length = textLength;
|
||||||
|
|
||||||
|
// NOTE: Alternative: memcpy(buffer, text + position, length)
|
||||||
|
|
||||||
for (int c = 0 ; c < length ; c++)
|
for (int c = 0 ; c < length ; c++)
|
||||||
{
|
{
|
||||||
*(buffer + c) = *(text + position);
|
*(buffer + c) = *(text + position);
|
||||||
|
@ -1569,7 +1642,8 @@ int TextFindIndex(const char *text, const char *find)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get upper case version of provided string
|
// Get upper case version of provided string
|
||||||
// REQUIRES: toupper()
|
// WARNING: Limited functionality, only basic characters set
|
||||||
|
// TODO: Support UTF-8 diacritics to upper-case, check codepoints
|
||||||
const char *TextToUpper(const char *text)
|
const char *TextToUpper(const char *text)
|
||||||
{
|
{
|
||||||
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||||
|
@ -1577,17 +1651,10 @@ const char *TextToUpper(const char *text)
|
||||||
|
|
||||||
if (text != NULL)
|
if (text != NULL)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < MAX_TEXT_BUFFER_LENGTH; i++)
|
for (int i = 0; (i < MAX_TEXT_BUFFER_LENGTH - 1) && (text[i] != '\0'); i++)
|
||||||
{
|
{
|
||||||
if (text[i] != '\0')
|
if ((text[i] >= 'a') && (text[i] <= 'z')) buffer[i] = text[i] - 32;
|
||||||
{
|
else buffer[i] = text[i];
|
||||||
buffer[i] = (char)toupper(text[i]);
|
|
||||||
//if ((text[i] >= 'a') && (text[i] <= 'z')) buffer[i] = text[i] - 32;
|
|
||||||
|
|
||||||
// TODO: Support UTF-8 diacritics to upper-case
|
|
||||||
//if ((text[i] >= 'à') && (text[i] <= 'ý')) buffer[i] = text[i] - 32;
|
|
||||||
}
|
|
||||||
else { buffer[i] = '\0'; break; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1595,7 +1662,7 @@ const char *TextToUpper(const char *text)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get lower case version of provided string
|
// Get lower case version of provided string
|
||||||
// REQUIRES: tolower()
|
// WARNING: Limited functionality, only basic characters set
|
||||||
const char *TextToLower(const char *text)
|
const char *TextToLower(const char *text)
|
||||||
{
|
{
|
||||||
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||||
|
@ -1603,14 +1670,10 @@ const char *TextToLower(const char *text)
|
||||||
|
|
||||||
if (text != NULL)
|
if (text != NULL)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < MAX_TEXT_BUFFER_LENGTH; i++)
|
for (int i = 0; (i < MAX_TEXT_BUFFER_LENGTH - 1) && (text[i] != '\0'); i++)
|
||||||
{
|
{
|
||||||
if (text[i] != '\0')
|
if ((text[i] >= 'A') && (text[i] <= 'Z')) buffer[i] = text[i] + 32;
|
||||||
{
|
else buffer[i] = text[i];
|
||||||
buffer[i] = (char)tolower(text[i]);
|
|
||||||
//if ((text[i] >= 'A') && (text[i] <= 'Z')) buffer[i] = text[i] + 32;
|
|
||||||
}
|
|
||||||
else { buffer[i] = '\0'; break; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1618,7 +1681,7 @@ const char *TextToLower(const char *text)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get Pascal case notation version of provided string
|
// Get Pascal case notation version of provided string
|
||||||
// REQUIRES: toupper()
|
// WARNING: Limited functionality, only basic characters set
|
||||||
const char *TextToPascal(const char *text)
|
const char *TextToPascal(const char *text)
|
||||||
{
|
{
|
||||||
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||||
|
@ -1626,21 +1689,20 @@ const char *TextToPascal(const char *text)
|
||||||
|
|
||||||
if (text != NULL)
|
if (text != NULL)
|
||||||
{
|
{
|
||||||
buffer[0] = (char)toupper(text[0]);
|
// Upper case first character
|
||||||
|
if ((text[0] >= 'a') && (text[0] <= 'z')) buffer[0] = text[0] - 32;
|
||||||
|
else buffer[0] = text[0];
|
||||||
|
|
||||||
for (int i = 1, j = 1; i < MAX_TEXT_BUFFER_LENGTH; i++, j++)
|
// Check for next separator to upper case another character
|
||||||
{
|
for (int i = 1, j = 1; (i < MAX_TEXT_BUFFER_LENGTH - 1) && (text[j] != '\0'); i++, j++)
|
||||||
if (text[j] != '\0')
|
|
||||||
{
|
{
|
||||||
if (text[j] != '_') buffer[i] = text[j];
|
if (text[j] != '_') buffer[i] = text[j];
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
j++;
|
j++;
|
||||||
buffer[i] = (char)toupper(text[j]);
|
if ((text[j] >= 'a') && (text[j] <= 'z')) buffer[i] = text[j] - 32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { buffer[i] = '\0'; break; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
|
@ -1651,7 +1713,7 @@ const char *TextToPascal(const char *text)
|
||||||
// WARNING: Allocated memory must be manually freed
|
// WARNING: Allocated memory must be manually freed
|
||||||
char *LoadUTF8(const int *codepoints, int length)
|
char *LoadUTF8(const int *codepoints, int length)
|
||||||
{
|
{
|
||||||
// We allocate enough memory fo fit all possible codepoints
|
// We allocate enough memory to fit all possible codepoints
|
||||||
// NOTE: 5 bytes for every codepoint should be enough
|
// NOTE: 5 bytes for every codepoint should be enough
|
||||||
char *text = (char *)RL_CALLOC(length*5, 1);
|
char *text = (char *)RL_CALLOC(length*5, 1);
|
||||||
const char *utf8 = NULL;
|
const char *utf8 = NULL;
|
||||||
|
@ -1720,10 +1782,9 @@ int GetCodepointCount(const char *text)
|
||||||
while (*ptr != '\0')
|
while (*ptr != '\0')
|
||||||
{
|
{
|
||||||
int next = 0;
|
int next = 0;
|
||||||
int letter = GetCodepointNext(ptr, &next);
|
GetCodepointNext(ptr, &next);
|
||||||
|
|
||||||
if (letter == 0x3f) ptr += 1;
|
ptr += next;
|
||||||
else ptr += next;
|
|
||||||
|
|
||||||
length++;
|
length++;
|
||||||
}
|
}
|
||||||
|
@ -1884,28 +1945,31 @@ int GetCodepointNext(const char *text, int *codepointSize)
|
||||||
{
|
{
|
||||||
const char *ptr = text;
|
const char *ptr = text;
|
||||||
int codepoint = 0x3f; // Codepoint (defaults to '?')
|
int codepoint = 0x3f; // Codepoint (defaults to '?')
|
||||||
*codepointSize = 0;
|
*codepointSize = 1;
|
||||||
|
|
||||||
// Get current codepoint and bytes processed
|
// Get current codepoint and bytes processed
|
||||||
if (0xf0 == (0xf8 & ptr[0]))
|
if (0xf0 == (0xf8 & ptr[0]))
|
||||||
{
|
{
|
||||||
// 4 byte UTF-8 codepoint
|
// 4 byte UTF-8 codepoint
|
||||||
|
if(((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80) || ((ptr[3] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks
|
||||||
codepoint = ((0x07 & ptr[0]) << 18) | ((0x3f & ptr[1]) << 12) | ((0x3f & ptr[2]) << 6) | (0x3f & ptr[3]);
|
codepoint = ((0x07 & ptr[0]) << 18) | ((0x3f & ptr[1]) << 12) | ((0x3f & ptr[2]) << 6) | (0x3f & ptr[3]);
|
||||||
*codepointSize = 4;
|
*codepointSize = 4;
|
||||||
}
|
}
|
||||||
else if (0xe0 == (0xf0 & ptr[0]))
|
else if (0xe0 == (0xf0 & ptr[0]))
|
||||||
{
|
{
|
||||||
// 3 byte UTF-8 codepoint */
|
// 3 byte UTF-8 codepoint */
|
||||||
|
if(((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks
|
||||||
codepoint = ((0x0f & ptr[0]) << 12) | ((0x3f & ptr[1]) << 6) | (0x3f & ptr[2]);
|
codepoint = ((0x0f & ptr[0]) << 12) | ((0x3f & ptr[1]) << 6) | (0x3f & ptr[2]);
|
||||||
*codepointSize = 3;
|
*codepointSize = 3;
|
||||||
}
|
}
|
||||||
else if (0xc0 == (0xe0 & ptr[0]))
|
else if (0xc0 == (0xe0 & ptr[0]))
|
||||||
{
|
{
|
||||||
// 2 byte UTF-8 codepoint
|
// 2 byte UTF-8 codepoint
|
||||||
|
if((ptr[1] & 0xC0) ^ 0x80) { return codepoint; } //10xxxxxx checks
|
||||||
codepoint = ((0x1f & ptr[0]) << 6) | (0x3f & ptr[1]);
|
codepoint = ((0x1f & ptr[0]) << 6) | (0x3f & ptr[1]);
|
||||||
*codepointSize = 2;
|
*codepointSize = 2;
|
||||||
}
|
}
|
||||||
else
|
else if (0x00 == (0x80 & ptr[0]))
|
||||||
{
|
{
|
||||||
// 1 byte UTF-8 codepoint
|
// 1 byte UTF-8 codepoint
|
||||||
codepoint = ptr[0];
|
codepoint = ptr[0];
|
||||||
|
@ -1938,7 +2002,6 @@ int GetCodepointPrevious(const char *text, int *codepointSize)
|
||||||
// Module specific Functions Definition
|
// Module specific Functions Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
#if defined(SUPPORT_FILEFORMAT_FNT)
|
#if defined(SUPPORT_FILEFORMAT_FNT)
|
||||||
|
|
||||||
// Read a line from memory
|
// Read a line from memory
|
||||||
// REQUIRES: memcpy()
|
// REQUIRES: memcpy()
|
||||||
// NOTE: Returns the number of bytes read
|
// NOTE: Returns the number of bytes read
|
||||||
|
@ -1969,6 +2032,8 @@ static Font LoadBMFont(const char *fileName)
|
||||||
char imFileName[129] = { 0 };
|
char imFileName[129] = { 0 };
|
||||||
|
|
||||||
int base = 0; // Useless data
|
int base = 0; // Useless data
|
||||||
|
int readBytes = 0; // Data bytes read
|
||||||
|
int readVars = 0; // Variables filled by sscanf()
|
||||||
|
|
||||||
char *fileText = LoadFileText(fileName);
|
char *fileText = LoadFileText(fileName);
|
||||||
|
|
||||||
|
@ -1977,32 +2042,30 @@ static Font LoadBMFont(const char *fileName)
|
||||||
char *fileTextPtr = fileText;
|
char *fileTextPtr = fileText;
|
||||||
|
|
||||||
// NOTE: We skip first line, it contains no useful information
|
// NOTE: We skip first line, it contains no useful information
|
||||||
int lineBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
|
readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
|
||||||
fileTextPtr += (lineBytes + 1);
|
fileTextPtr += (readBytes + 1);
|
||||||
|
|
||||||
// Read line data
|
// Read line data
|
||||||
lineBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
|
readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
|
||||||
searchPoint = strstr(buffer, "lineHeight");
|
searchPoint = strstr(buffer, "lineHeight");
|
||||||
sscanf(searchPoint, "lineHeight=%i base=%i scaleW=%i scaleH=%i", &fontSize, &base, &imWidth, &imHeight);
|
readVars = sscanf(searchPoint, "lineHeight=%i base=%i scaleW=%i scaleH=%i", &fontSize, &base, &imWidth, &imHeight);
|
||||||
fileTextPtr += (lineBytes + 1);
|
fileTextPtr += (readBytes + 1);
|
||||||
|
|
||||||
TRACELOGD("FONT: [%s] Loaded font info:", fileName);
|
if (readVars < 4) { UnloadFileText(fileText); return font; } // Some data not available, file malformed
|
||||||
TRACELOGD(" > Base size: %i", fontSize);
|
|
||||||
TRACELOGD(" > Texture scale: %ix%i", imWidth, imHeight);
|
|
||||||
|
|
||||||
lineBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
|
readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
|
||||||
searchPoint = strstr(buffer, "file");
|
searchPoint = strstr(buffer, "file");
|
||||||
sscanf(searchPoint, "file=\"%128[^\"]\"", imFileName);
|
readVars = sscanf(searchPoint, "file=\"%128[^\"]\"", imFileName);
|
||||||
fileTextPtr += (lineBytes + 1);
|
fileTextPtr += (readBytes + 1);
|
||||||
|
|
||||||
TRACELOGD(" > Texture filename: %s", imFileName);
|
if (readVars < 1) { UnloadFileText(fileText); return font; } // No fileName read
|
||||||
|
|
||||||
lineBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
|
readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
|
||||||
searchPoint = strstr(buffer, "count");
|
searchPoint = strstr(buffer, "count");
|
||||||
sscanf(searchPoint, "count=%i", &glyphCount);
|
readVars = sscanf(searchPoint, "count=%i", &glyphCount);
|
||||||
fileTextPtr += (lineBytes + 1);
|
fileTextPtr += (readBytes + 1);
|
||||||
|
|
||||||
TRACELOGD(" > Chars count: %i", glyphCount);
|
if (readVars < 1) { UnloadFileText(fileText); return font; } // No glyphCount read
|
||||||
|
|
||||||
// Compose correct path using route of .fnt file (fileName) and imFileName
|
// Compose correct path using route of .fnt file (fileName) and imFileName
|
||||||
char *imPath = NULL;
|
char *imPath = NULL;
|
||||||
|
@ -2060,11 +2123,13 @@ static Font LoadBMFont(const char *fileName)
|
||||||
|
|
||||||
for (int i = 0; i < glyphCount; i++)
|
for (int i = 0; i < glyphCount; i++)
|
||||||
{
|
{
|
||||||
lineBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
|
readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
|
||||||
sscanf(buffer, "char id=%i x=%i y=%i width=%i height=%i xoffset=%i yoffset=%i xadvance=%i",
|
readVars = sscanf(buffer, "char id=%i x=%i y=%i width=%i height=%i xoffset=%i yoffset=%i xadvance=%i",
|
||||||
&charId, &charX, &charY, &charWidth, &charHeight, &charOffsetX, &charOffsetY, &charAdvanceX);
|
&charId, &charX, &charY, &charWidth, &charHeight, &charOffsetX, &charOffsetY, &charAdvanceX);
|
||||||
fileTextPtr += (lineBytes + 1);
|
fileTextPtr += (readBytes + 1);
|
||||||
|
|
||||||
|
if (readVars == 8) // Make sure all char data has been properly read
|
||||||
|
{
|
||||||
// Get character rectangle in the font atlas texture
|
// Get character rectangle in the font atlas texture
|
||||||
font.recs[i] = (Rectangle){ (float)charX, (float)charY, (float)charWidth, (float)charHeight };
|
font.recs[i] = (Rectangle){ (float)charX, (float)charY, (float)charWidth, (float)charHeight };
|
||||||
|
|
||||||
|
@ -2077,6 +2142,8 @@ static Font LoadBMFont(const char *fileName)
|
||||||
// Fill character image data from imFont data
|
// Fill character image data from imFont data
|
||||||
font.glyphs[i].image = ImageFromImage(imFont, font.recs[i]);
|
font.glyphs[i].image = ImageFromImage(imFont, font.recs[i]);
|
||||||
}
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "FONT: [%s] Some characters data not correctly provided", fileName);
|
||||||
|
}
|
||||||
|
|
||||||
UnloadImage(imFont);
|
UnloadImage(imFont);
|
||||||
UnloadFileText(fileText);
|
UnloadFileText(fileText);
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -575,30 +575,6 @@ func GenImageColor(width, height int, col color.RGBA) *Image {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenImageGradientV - Generate image: vertical gradient
|
|
||||||
func GenImageGradientV(width, height int, top, bottom color.RGBA) *Image {
|
|
||||||
cwidth := (C.int)(width)
|
|
||||||
cheight := (C.int)(height)
|
|
||||||
ctop := colorCptr(top)
|
|
||||||
cbottom := colorCptr(bottom)
|
|
||||||
|
|
||||||
ret := C.GenImageGradientV(cwidth, cheight, *ctop, *cbottom)
|
|
||||||
v := newImageFromPointer(unsafe.Pointer(&ret))
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
// GenImageGradientH - Generate image: horizontal gradient
|
|
||||||
func GenImageGradientH(width, height int, left, right color.RGBA) *Image {
|
|
||||||
cwidth := (C.int)(width)
|
|
||||||
cheight := (C.int)(height)
|
|
||||||
cleft := colorCptr(left)
|
|
||||||
cright := colorCptr(right)
|
|
||||||
|
|
||||||
ret := C.GenImageGradientH(cwidth, cheight, *cleft, *cright)
|
|
||||||
v := newImageFromPointer(unsafe.Pointer(&ret))
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
// GenImageGradientRadial - Generate image: radial gradient
|
// GenImageGradientRadial - Generate image: radial gradient
|
||||||
func GenImageGradientRadial(width, height int, density float32, inner, outer color.RGBA) *Image {
|
func GenImageGradientRadial(width, height int, density float32, inner, outer color.RGBA) *Image {
|
||||||
cwidth := (C.int)(width)
|
cwidth := (C.int)(width)
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
* raylib.utils - Some common utility functions
|
* raylib.utils - Some common utility functions
|
||||||
*
|
*
|
||||||
* CONFIGURATION:
|
* CONFIGURATION:
|
||||||
*
|
|
||||||
* #define SUPPORT_TRACELOG
|
* #define SUPPORT_TRACELOG
|
||||||
* Show TraceLog() output messages
|
* Show TraceLog() output messages
|
||||||
* NOTE: By default LOG_DEBUG traces not shown
|
* NOTE: By default LOG_DEBUG traces not shown
|
||||||
|
@ -145,7 +144,7 @@ void TraceLog(int logType, const char *text, ...)
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int textSize = strlen(text);
|
unsigned int textSize = (unsigned int)strlen(text);
|
||||||
memcpy(buffer + strlen(buffer), text, (textSize < (MAX_TRACELOG_MSG_LENGTH - 12))? textSize : (MAX_TRACELOG_MSG_LENGTH - 12));
|
memcpy(buffer + strlen(buffer), text, (textSize < (MAX_TRACELOG_MSG_LENGTH - 12))? textSize : (MAX_TRACELOG_MSG_LENGTH - 12));
|
||||||
strcat(buffer, "\n");
|
strcat(buffer, "\n");
|
||||||
vprintf(buffer, args);
|
vprintf(buffer, args);
|
||||||
|
@ -181,16 +180,16 @@ void MemFree(void *ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load data from file into a buffer
|
// Load data from file into a buffer
|
||||||
unsigned char *LoadFileData(const char *fileName, unsigned int *bytesRead)
|
unsigned char *LoadFileData(const char *fileName, int *dataSize)
|
||||||
{
|
{
|
||||||
unsigned char *data = NULL;
|
unsigned char *data = NULL;
|
||||||
*bytesRead = 0;
|
*dataSize = 0;
|
||||||
|
|
||||||
if (fileName != NULL)
|
if (fileName != NULL)
|
||||||
{
|
{
|
||||||
if (loadFileData)
|
if (loadFileData)
|
||||||
{
|
{
|
||||||
data = loadFileData(fileName, bytesRead);
|
data = loadFileData(fileName, dataSize);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
#if defined(SUPPORT_STANDARD_FILEIO)
|
#if defined(SUPPORT_STANDARD_FILEIO)
|
||||||
|
@ -201,20 +200,37 @@ unsigned char *LoadFileData(const char *fileName, unsigned int *bytesRead)
|
||||||
// WARNING: On binary streams SEEK_END could not be found,
|
// WARNING: On binary streams SEEK_END could not be found,
|
||||||
// using fseek() and ftell() could not work in some (rare) cases
|
// using fseek() and ftell() could not work in some (rare) cases
|
||||||
fseek(file, 0, SEEK_END);
|
fseek(file, 0, SEEK_END);
|
||||||
int size = ftell(file);
|
int size = ftell(file); // WARNING: ftell() returns 'long int', maximum size returned is INT_MAX (2147483647 bytes)
|
||||||
fseek(file, 0, SEEK_SET);
|
fseek(file, 0, SEEK_SET);
|
||||||
|
|
||||||
if (size > 0)
|
if (size > 0)
|
||||||
{
|
{
|
||||||
data = (unsigned char *)RL_MALLOC(size*sizeof(unsigned char));
|
data = (unsigned char *)RL_MALLOC(size*sizeof(unsigned char));
|
||||||
|
|
||||||
|
if (data != NULL)
|
||||||
|
{
|
||||||
// NOTE: fread() returns number of read elements instead of bytes, so we read [1 byte, size elements]
|
// NOTE: fread() returns number of read elements instead of bytes, so we read [1 byte, size elements]
|
||||||
unsigned int count = (unsigned int)fread(data, sizeof(unsigned char), size, file);
|
size_t count = fread(data, sizeof(unsigned char), size, file);
|
||||||
*bytesRead = count;
|
|
||||||
|
|
||||||
if (count != size) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially loaded", fileName);
|
// WARNING: fread() returns a size_t value, usually 'unsigned int' (32bit compilation) and 'unsigned long long' (64bit compilation)
|
||||||
|
// dataSize is unified along raylib as a 'int' type, so, for file-sizes > INT_MAX (2147483647 bytes) we have a limitation
|
||||||
|
if (count > 2147483647)
|
||||||
|
{
|
||||||
|
TRACELOG(LOG_WARNING, "FILEIO: [%s] File is bigger than 2147483647 bytes, avoid using LoadFileData()", fileName);
|
||||||
|
|
||||||
|
RL_FREE(data);
|
||||||
|
data = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*dataSize = (int)count;
|
||||||
|
|
||||||
|
if ((*dataSize) != size) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially loaded (%i bytes out of %i)", fileName, dataSize, count);
|
||||||
else TRACELOG(LOG_INFO, "FILEIO: [%s] File loaded successfully", fileName);
|
else TRACELOG(LOG_INFO, "FILEIO: [%s] File loaded successfully", fileName);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to allocated memory for file reading", fileName);
|
||||||
|
}
|
||||||
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to read file", fileName);
|
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to read file", fileName);
|
||||||
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
@ -236,7 +252,7 @@ void UnloadFileData(unsigned char *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save data to file from buffer
|
// Save data to file from buffer
|
||||||
bool SaveFileData(const char *fileName, void *data, unsigned int bytesToWrite)
|
bool SaveFileData(const char *fileName, void *data, int dataSize)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
|
||||||
|
@ -244,17 +260,19 @@ bool SaveFileData(const char *fileName, void *data, unsigned int bytesToWrite)
|
||||||
{
|
{
|
||||||
if (saveFileData)
|
if (saveFileData)
|
||||||
{
|
{
|
||||||
return saveFileData(fileName, data, bytesToWrite);
|
return saveFileData(fileName, data, dataSize);
|
||||||
}
|
}
|
||||||
#if defined(SUPPORT_STANDARD_FILEIO)
|
#if defined(SUPPORT_STANDARD_FILEIO)
|
||||||
FILE *file = fopen(fileName, "wb");
|
FILE *file = fopen(fileName, "wb");
|
||||||
|
|
||||||
if (file != NULL)
|
if (file != NULL)
|
||||||
{
|
{
|
||||||
unsigned int count = (unsigned int)fwrite(data, sizeof(unsigned char), bytesToWrite, file);
|
// WARNING: fwrite() returns a size_t value, usually 'unsigned int' (32bit compilation) and 'unsigned long long' (64bit compilation)
|
||||||
|
// and expects a size_t input value but as dataSize is limited to INT_MAX (2147483647 bytes), there shouldn't be a problem
|
||||||
|
int count = (int)fwrite(data, sizeof(unsigned char), dataSize, file);
|
||||||
|
|
||||||
if (count == 0) TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to write file", fileName);
|
if (count == 0) TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to write file", fileName);
|
||||||
else if (count != bytesToWrite) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially written", fileName);
|
else if (count != dataSize) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially written", fileName);
|
||||||
else TRACELOG(LOG_INFO, "FILEIO: [%s] File saved successfully", fileName);
|
else TRACELOG(LOG_INFO, "FILEIO: [%s] File saved successfully", fileName);
|
||||||
|
|
||||||
int result = fclose(file);
|
int result = fclose(file);
|
||||||
|
@ -271,7 +289,7 @@ bool SaveFileData(const char *fileName, void *data, unsigned int bytesToWrite)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Export data to code (.h), returns true on success
|
// Export data to code (.h), returns true on success
|
||||||
bool ExportDataAsCode(const unsigned char *data, unsigned int size, const char *fileName)
|
bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileName)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
|
||||||
|
@ -281,7 +299,7 @@ bool ExportDataAsCode(const unsigned char *data, unsigned int size, const char *
|
||||||
|
|
||||||
// NOTE: Text data buffer size is estimated considering raw data size in bytes
|
// NOTE: Text data buffer size is estimated considering raw data size in bytes
|
||||||
// and requiring 6 char bytes for every byte: "0x00, "
|
// and requiring 6 char bytes for every byte: "0x00, "
|
||||||
char *txtData = (char *)RL_CALLOC(size*6 + 2000, sizeof(char));
|
char *txtData = (char *)RL_CALLOC(dataSize*6 + 2000, sizeof(char));
|
||||||
|
|
||||||
int byteCount = 0;
|
int byteCount = 0;
|
||||||
byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n");
|
byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n");
|
||||||
|
@ -300,9 +318,11 @@ bool ExportDataAsCode(const unsigned char *data, unsigned int size, const char *
|
||||||
strcpy(varFileName, GetFileNameWithoutExt(fileName));
|
strcpy(varFileName, GetFileNameWithoutExt(fileName));
|
||||||
for (int i = 0; varFileName[i] != '\0'; i++) if ((varFileName[i] >= 'a') && (varFileName[i] <= 'z')) { varFileName[i] = varFileName[i] - 32; }
|
for (int i = 0; varFileName[i] != '\0'; i++) if ((varFileName[i] >= 'a') && (varFileName[i] <= 'z')) { varFileName[i] = varFileName[i] - 32; }
|
||||||
|
|
||||||
byteCount += sprintf(txtData + byteCount, "static unsigned char %s_DATA[%i] = { ", varFileName, size);
|
byteCount += sprintf(txtData + byteCount, "#define %s_DATA_SIZE %i\n\n", varFileName, dataSize);
|
||||||
for (unsigned int i = 0; i < size - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%x,\n" : "0x%x, "), data[i]);
|
|
||||||
byteCount += sprintf(txtData + byteCount, "0x%x };\n", data[size - 1]);
|
byteCount += sprintf(txtData + byteCount, "static unsigned char %s_DATA[%s_DATA_SIZE] = { ", varFileName, varFileName);
|
||||||
|
for (int i = 0; i < (dataSize - 1); i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%x,\n" : "0x%x, "), data[i]);
|
||||||
|
byteCount += sprintf(txtData + byteCount, "0x%x };\n", data[dataSize - 1]);
|
||||||
|
|
||||||
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
||||||
success = SaveFileText(fileName, txtData);
|
success = SaveFileText(fileName, txtData);
|
||||||
|
@ -343,6 +363,9 @@ char *LoadFileText(const char *fileName)
|
||||||
if (size > 0)
|
if (size > 0)
|
||||||
{
|
{
|
||||||
text = (char *)RL_MALLOC((size + 1)*sizeof(char));
|
text = (char *)RL_MALLOC((size + 1)*sizeof(char));
|
||||||
|
|
||||||
|
if (text != NULL)
|
||||||
|
{
|
||||||
unsigned int count = (unsigned int)fread(text, sizeof(char), size, file);
|
unsigned int count = (unsigned int)fread(text, sizeof(char), size, file);
|
||||||
|
|
||||||
// WARNING: \r\n is converted to \n on reading, so,
|
// WARNING: \r\n is converted to \n on reading, so,
|
||||||
|
@ -354,6 +377,8 @@ char *LoadFileText(const char *fileName)
|
||||||
|
|
||||||
TRACELOG(LOG_INFO, "FILEIO: [%s] Text file loaded successfully", fileName);
|
TRACELOG(LOG_INFO, "FILEIO: [%s] Text file loaded successfully", fileName);
|
||||||
}
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to allocated memory for file reading", fileName);
|
||||||
|
}
|
||||||
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to read text file", fileName);
|
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to read text file", fileName);
|
||||||
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
@ -455,12 +480,12 @@ FILE *android_fopen(const char *fileName, const char *mode)
|
||||||
// Module specific Functions Definition
|
// Module specific Functions Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
#if defined(PLATFORM_ANDROID)
|
#if defined(PLATFORM_ANDROID)
|
||||||
static int android_read(void *cookie, char *buf, int size)
|
static int android_read(void *cookie, char *data, int dataSize)
|
||||||
{
|
{
|
||||||
return AAsset_read((AAsset *)cookie, buf, size);
|
return AAsset_read((AAsset *)cookie, data, dataSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int android_write(void *cookie, const char *buf, int size)
|
static int android_write(void *cookie, const char *data, int dataSize)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "ANDROID: Failed to provide write access to APK");
|
TRACELOG(LOG_WARNING, "ANDROID: Failed to provide write access to APK");
|
||||||
|
|
||||||
|
|
141
rres/raylib.h
141
rres/raylib.h
|
@ -1,6 +1,6 @@
|
||||||
/**********************************************************************************************
|
/**********************************************************************************************
|
||||||
*
|
*
|
||||||
* raylib v4.5 - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com)
|
* raylib v4.6-dev - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com)
|
||||||
*
|
*
|
||||||
* FEATURES:
|
* FEATURES:
|
||||||
* - NO external dependencies, all required libraries included with raylib
|
* - NO external dependencies, all required libraries included with raylib
|
||||||
|
@ -81,10 +81,10 @@
|
||||||
|
|
||||||
#include <stdarg.h> // Required for: va_list - Only used by TraceLogCallback
|
#include <stdarg.h> // Required for: va_list - Only used by TraceLogCallback
|
||||||
|
|
||||||
#define RAYLIB_VERSION_MAJOR 4
|
#define RAYLIB_VERSION_MAJOR 5
|
||||||
#define RAYLIB_VERSION_MINOR 5
|
#define RAYLIB_VERSION_MINOR 0
|
||||||
#define RAYLIB_VERSION_PATCH 0
|
#define RAYLIB_VERSION_PATCH 0
|
||||||
#define RAYLIB_VERSION "4.5"
|
#define RAYLIB_VERSION "5.0"
|
||||||
|
|
||||||
// Function specifiers in case library is build/used as a shared library (Windows)
|
// Function specifiers in case library is build/used as a shared library (Windows)
|
||||||
// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
|
// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
|
||||||
|
@ -133,12 +133,20 @@
|
||||||
|
|
||||||
// NOTE: MSVC C++ compiler does not support compound literals (C99 feature)
|
// NOTE: MSVC C++ compiler does not support compound literals (C99 feature)
|
||||||
// Plain structures in C++ (without constructors) can be initialized with { }
|
// Plain structures in C++ (without constructors) can be initialized with { }
|
||||||
|
// This is called aggregate initialization (C++11 feature)
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
#define CLITERAL(type) type
|
#define CLITERAL(type) type
|
||||||
#else
|
#else
|
||||||
#define CLITERAL(type) (type)
|
#define CLITERAL(type) (type)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Some compilers (mostly macos clang) default to C++98,
|
||||||
|
// where aggregate initialization can't be used
|
||||||
|
// So, give a more clear error stating how to fix this
|
||||||
|
#if !defined(_MSC_VER) && (defined(__cplusplus) && __cplusplus < 201103L)
|
||||||
|
#error "C++11 or later is required. Add -std=c++11"
|
||||||
|
#endif
|
||||||
|
|
||||||
// NOTE: We set some defines with some data types declared by raylib
|
// NOTE: We set some defines with some data types declared by raylib
|
||||||
// Other modules (raymath, rlgl) also require some of those types, so,
|
// Other modules (raymath, rlgl) also require some of those types, so,
|
||||||
// to be able to use those other modules as standalone (not depending on raylib)
|
// to be able to use those other modules as standalone (not depending on raylib)
|
||||||
|
@ -402,6 +410,7 @@ typedef struct ModelAnimation {
|
||||||
int frameCount; // Number of animation frames
|
int frameCount; // Number of animation frames
|
||||||
BoneInfo *bones; // Bones information (skeleton)
|
BoneInfo *bones; // Bones information (skeleton)
|
||||||
Transform **framePoses; // Poses array by frame
|
Transform **framePoses; // Poses array by frame
|
||||||
|
char name[32]; // Animation name
|
||||||
} ModelAnimation;
|
} ModelAnimation;
|
||||||
|
|
||||||
// Ray, ray for raycasting
|
// Ray, ray for raycasting
|
||||||
|
@ -497,6 +506,20 @@ typedef struct FilePathList {
|
||||||
char **paths; // Filepaths entries
|
char **paths; // Filepaths entries
|
||||||
} FilePathList;
|
} FilePathList;
|
||||||
|
|
||||||
|
// Automation event
|
||||||
|
typedef struct AutomationEvent {
|
||||||
|
unsigned int frame; // Event frame
|
||||||
|
unsigned int type; // Event type (AutomationEventType)
|
||||||
|
int params[4]; // Event parameters (if required)
|
||||||
|
} AutomationEvent;
|
||||||
|
|
||||||
|
// Automation event list
|
||||||
|
typedef struct AutomationEventList {
|
||||||
|
unsigned int capacity; // Events max entries (MAX_AUTOMATION_EVENTS)
|
||||||
|
unsigned int count; // Events entries count
|
||||||
|
AutomationEvent *events; // Events entries
|
||||||
|
} AutomationEventList;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Enumerators Definition
|
// Enumerators Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
@ -517,6 +540,7 @@ typedef enum {
|
||||||
FLAG_WINDOW_TRANSPARENT = 0x00000010, // Set to allow transparent framebuffer
|
FLAG_WINDOW_TRANSPARENT = 0x00000010, // Set to allow transparent framebuffer
|
||||||
FLAG_WINDOW_HIGHDPI = 0x00002000, // Set to support HighDPI
|
FLAG_WINDOW_HIGHDPI = 0x00002000, // Set to support HighDPI
|
||||||
FLAG_WINDOW_MOUSE_PASSTHROUGH = 0x00004000, // Set to support mouse passthrough, only supported when FLAG_WINDOW_UNDECORATED
|
FLAG_WINDOW_MOUSE_PASSTHROUGH = 0x00004000, // Set to support mouse passthrough, only supported when FLAG_WINDOW_UNDECORATED
|
||||||
|
FLAG_BORDERLESS_WINDOWED_MODE = 0x00008000, // Set to run program in borderless windowed mode
|
||||||
FLAG_MSAA_4X_HINT = 0x00000020, // Set to try enabling MSAA 4X
|
FLAG_MSAA_4X_HINT = 0x00000020, // Set to try enabling MSAA 4X
|
||||||
FLAG_INTERLACED_HINT = 0x00010000 // Set to try enabling interlaced video format (for V3D)
|
FLAG_INTERLACED_HINT = 0x00010000 // Set to try enabling interlaced video format (for V3D)
|
||||||
} ConfigFlags;
|
} ConfigFlags;
|
||||||
|
@ -802,6 +826,9 @@ typedef enum {
|
||||||
PIXELFORMAT_UNCOMPRESSED_R32, // 32 bpp (1 channel - float)
|
PIXELFORMAT_UNCOMPRESSED_R32, // 32 bpp (1 channel - float)
|
||||||
PIXELFORMAT_UNCOMPRESSED_R32G32B32, // 32*3 bpp (3 channels - float)
|
PIXELFORMAT_UNCOMPRESSED_R32G32B32, // 32*3 bpp (3 channels - float)
|
||||||
PIXELFORMAT_UNCOMPRESSED_R32G32B32A32, // 32*4 bpp (4 channels - float)
|
PIXELFORMAT_UNCOMPRESSED_R32G32B32A32, // 32*4 bpp (4 channels - float)
|
||||||
|
PIXELFORMAT_UNCOMPRESSED_R16, // 16 bpp (1 channel - half float)
|
||||||
|
PIXELFORMAT_UNCOMPRESSED_R16G16B16, // 16*3 bpp (3 channels - half float)
|
||||||
|
PIXELFORMAT_UNCOMPRESSED_R16G16B16A16, // 16*4 bpp (4 channels - half float)
|
||||||
PIXELFORMAT_COMPRESSED_DXT1_RGB, // 4 bpp (no alpha)
|
PIXELFORMAT_COMPRESSED_DXT1_RGB, // 4 bpp (no alpha)
|
||||||
PIXELFORMAT_COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha)
|
PIXELFORMAT_COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha)
|
||||||
PIXELFORMAT_COMPRESSED_DXT3_RGBA, // 8 bpp
|
PIXELFORMAT_COMPRESSED_DXT3_RGBA, // 8 bpp
|
||||||
|
@ -905,8 +932,8 @@ typedef enum {
|
||||||
// Callbacks to hook some internal functions
|
// Callbacks to hook some internal functions
|
||||||
// WARNING: These callbacks are intended for advance users
|
// WARNING: These callbacks are intended for advance users
|
||||||
typedef void (*TraceLogCallback)(int logLevel, const char *text, va_list args); // Logging: Redirect trace log messages
|
typedef void (*TraceLogCallback)(int logLevel, const char *text, va_list args); // Logging: Redirect trace log messages
|
||||||
typedef unsigned char *(*LoadFileDataCallback)(const char *fileName, unsigned int *bytesRead); // FileIO: Load binary data
|
typedef unsigned char *(*LoadFileDataCallback)(const char *fileName, int *dataSize); // FileIO: Load binary data
|
||||||
typedef bool (*SaveFileDataCallback)(const char *fileName, void *data, unsigned int bytesToWrite); // FileIO: Save binary data
|
typedef bool (*SaveFileDataCallback)(const char *fileName, void *data, int dataSize); // FileIO: Save binary data
|
||||||
typedef char *(*LoadFileTextCallback)(const char *fileName); // FileIO: Load text data
|
typedef char *(*LoadFileTextCallback)(const char *fileName); // FileIO: Load text data
|
||||||
typedef bool (*SaveFileTextCallback)(const char *fileName, char *text); // FileIO: Save text data
|
typedef bool (*SaveFileTextCallback)(const char *fileName, char *text); // FileIO: Save text data
|
||||||
|
|
||||||
|
@ -925,8 +952,8 @@ extern "C" { // Prevents name mangling of functions
|
||||||
|
|
||||||
// Window-related functions
|
// Window-related functions
|
||||||
RLAPI void InitWindow(int width, int height, const char *title); // Initialize window and OpenGL context
|
RLAPI void InitWindow(int width, int height, const char *title); // Initialize window and OpenGL context
|
||||||
RLAPI bool WindowShouldClose(void); // Check if KEY_ESCAPE pressed or Close icon pressed
|
|
||||||
RLAPI void CloseWindow(void); // Close window and unload OpenGL context
|
RLAPI void CloseWindow(void); // Close window and unload OpenGL context
|
||||||
|
RLAPI bool WindowShouldClose(void); // Check if application should close (KEY_ESCAPE pressed or windows close icon clicked)
|
||||||
RLAPI bool IsWindowReady(void); // Check if window has been initialized successfully
|
RLAPI bool IsWindowReady(void); // Check if window has been initialized successfully
|
||||||
RLAPI bool IsWindowFullscreen(void); // Check if window is currently fullscreen
|
RLAPI bool IsWindowFullscreen(void); // Check if window is currently fullscreen
|
||||||
RLAPI bool IsWindowHidden(void); // Check if window is currently hidden (only PLATFORM_DESKTOP)
|
RLAPI bool IsWindowHidden(void); // Check if window is currently hidden (only PLATFORM_DESKTOP)
|
||||||
|
@ -938,17 +965,20 @@ RLAPI bool IsWindowState(unsigned int flag); // Check if on
|
||||||
RLAPI void SetWindowState(unsigned int flags); // Set window configuration state using flags (only PLATFORM_DESKTOP)
|
RLAPI void SetWindowState(unsigned int flags); // Set window configuration state using flags (only PLATFORM_DESKTOP)
|
||||||
RLAPI void ClearWindowState(unsigned int flags); // Clear window configuration state flags
|
RLAPI void ClearWindowState(unsigned int flags); // Clear window configuration state flags
|
||||||
RLAPI void ToggleFullscreen(void); // Toggle window state: fullscreen/windowed (only PLATFORM_DESKTOP)
|
RLAPI void ToggleFullscreen(void); // Toggle window state: fullscreen/windowed (only PLATFORM_DESKTOP)
|
||||||
|
RLAPI void ToggleBorderlessWindowed(void); // Toggle window state: borderless windowed (only PLATFORM_DESKTOP)
|
||||||
RLAPI void MaximizeWindow(void); // Set window state: maximized, if resizable (only PLATFORM_DESKTOP)
|
RLAPI void MaximizeWindow(void); // Set window state: maximized, if resizable (only PLATFORM_DESKTOP)
|
||||||
RLAPI void MinimizeWindow(void); // Set window state: minimized, if resizable (only PLATFORM_DESKTOP)
|
RLAPI void MinimizeWindow(void); // Set window state: minimized, if resizable (only PLATFORM_DESKTOP)
|
||||||
RLAPI void RestoreWindow(void); // Set window state: not minimized/maximized (only PLATFORM_DESKTOP)
|
RLAPI void RestoreWindow(void); // Set window state: not minimized/maximized (only PLATFORM_DESKTOP)
|
||||||
RLAPI void SetWindowIcon(Image image); // Set icon for window (single image, RGBA 32bit, only PLATFORM_DESKTOP)
|
RLAPI void SetWindowIcon(Image image); // Set icon for window (single image, RGBA 32bit, only PLATFORM_DESKTOP)
|
||||||
RLAPI void SetWindowIcons(Image *images, int count); // Set icon for window (multiple images, RGBA 32bit, only PLATFORM_DESKTOP)
|
RLAPI void SetWindowIcons(Image *images, int count); // Set icon for window (multiple images, RGBA 32bit, only PLATFORM_DESKTOP)
|
||||||
RLAPI void SetWindowTitle(const char *title); // Set title for window (only PLATFORM_DESKTOP)
|
RLAPI void SetWindowTitle(const char *title); // Set title for window (only PLATFORM_DESKTOP and PLATFORM_WEB)
|
||||||
RLAPI void SetWindowPosition(int x, int y); // Set window position on screen (only PLATFORM_DESKTOP)
|
RLAPI void SetWindowPosition(int x, int y); // Set window position on screen (only PLATFORM_DESKTOP)
|
||||||
RLAPI void SetWindowMonitor(int monitor); // Set monitor for the current window (fullscreen mode)
|
RLAPI void SetWindowMonitor(int monitor); // Set monitor for the current window
|
||||||
RLAPI void SetWindowMinSize(int width, int height); // Set window minimum dimensions (for FLAG_WINDOW_RESIZABLE)
|
RLAPI void SetWindowMinSize(int width, int height); // Set window minimum dimensions (for FLAG_WINDOW_RESIZABLE)
|
||||||
|
RLAPI void SetWindowMaxSize(int width, int height); // Set window maximum dimensions (for FLAG_WINDOW_RESIZABLE)
|
||||||
RLAPI void SetWindowSize(int width, int height); // Set window dimensions
|
RLAPI void SetWindowSize(int width, int height); // Set window dimensions
|
||||||
RLAPI void SetWindowOpacity(float opacity); // Set window opacity [0.0f..1.0f] (only PLATFORM_DESKTOP)
|
RLAPI void SetWindowOpacity(float opacity); // Set window opacity [0.0f..1.0f] (only PLATFORM_DESKTOP)
|
||||||
|
RLAPI void SetWindowFocused(void); // Set window focused (only PLATFORM_DESKTOP)
|
||||||
RLAPI void *GetWindowHandle(void); // Get native window handle
|
RLAPI void *GetWindowHandle(void); // Get native window handle
|
||||||
RLAPI int GetScreenWidth(void); // Get current screen width
|
RLAPI int GetScreenWidth(void); // Get current screen width
|
||||||
RLAPI int GetScreenHeight(void); // Get current screen height
|
RLAPI int GetScreenHeight(void); // Get current screen height
|
||||||
|
@ -964,20 +994,12 @@ RLAPI int GetMonitorPhysicalHeight(int monitor); // Get specifi
|
||||||
RLAPI int GetMonitorRefreshRate(int monitor); // Get specified monitor refresh rate
|
RLAPI int GetMonitorRefreshRate(int monitor); // Get specified monitor refresh rate
|
||||||
RLAPI Vector2 GetWindowPosition(void); // Get window position XY on monitor
|
RLAPI Vector2 GetWindowPosition(void); // Get window position XY on monitor
|
||||||
RLAPI Vector2 GetWindowScaleDPI(void); // Get window scale DPI factor
|
RLAPI Vector2 GetWindowScaleDPI(void); // Get window scale DPI factor
|
||||||
RLAPI const char *GetMonitorName(int monitor); // Get the human-readable, UTF-8 encoded name of the primary monitor
|
RLAPI const char *GetMonitorName(int monitor); // Get the human-readable, UTF-8 encoded name of the specified monitor
|
||||||
RLAPI void SetClipboardText(const char *text); // Set clipboard text content
|
RLAPI void SetClipboardText(const char *text); // Set clipboard text content
|
||||||
RLAPI const char *GetClipboardText(void); // Get clipboard text content
|
RLAPI const char *GetClipboardText(void); // Get clipboard text content
|
||||||
RLAPI void EnableEventWaiting(void); // Enable waiting for events on EndDrawing(), no automatic event polling
|
RLAPI void EnableEventWaiting(void); // Enable waiting for events on EndDrawing(), no automatic event polling
|
||||||
RLAPI void DisableEventWaiting(void); // Disable waiting for events on EndDrawing(), automatic events polling
|
RLAPI void DisableEventWaiting(void); // Disable waiting for events on EndDrawing(), automatic events polling
|
||||||
|
|
||||||
// Custom frame control functions
|
|
||||||
// NOTE: Those functions are intended for advance users that want full control over the frame processing
|
|
||||||
// By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timing + PollInputEvents()
|
|
||||||
// To avoid that behaviour and control frame processes manually, enable in config.h: SUPPORT_CUSTOM_FRAME_CONTROL
|
|
||||||
RLAPI void SwapScreenBuffer(void); // Swap back buffer with front buffer (screen drawing)
|
|
||||||
RLAPI void PollInputEvents(void); // Register all input events
|
|
||||||
RLAPI void WaitTime(double seconds); // Wait for some time (halt program execution)
|
|
||||||
|
|
||||||
// Cursor-related functions
|
// Cursor-related functions
|
||||||
RLAPI void ShowCursor(void); // Shows cursor
|
RLAPI void ShowCursor(void); // Shows cursor
|
||||||
RLAPI void HideCursor(void); // Hides cursor
|
RLAPI void HideCursor(void); // Hides cursor
|
||||||
|
@ -1033,24 +1055,37 @@ RLAPI Vector2 GetWorldToScreen2D(Vector2 position, Camera2D camera); // Get the
|
||||||
|
|
||||||
// Timing-related functions
|
// Timing-related functions
|
||||||
RLAPI void SetTargetFPS(int fps); // Set target FPS (maximum)
|
RLAPI void SetTargetFPS(int fps); // Set target FPS (maximum)
|
||||||
RLAPI int GetFPS(void); // Get current FPS
|
|
||||||
RLAPI float GetFrameTime(void); // Get time in seconds for last frame drawn (delta time)
|
RLAPI float GetFrameTime(void); // Get time in seconds for last frame drawn (delta time)
|
||||||
RLAPI double GetTime(void); // Get elapsed time in seconds since InitWindow()
|
RLAPI double GetTime(void); // Get elapsed time in seconds since InitWindow()
|
||||||
|
RLAPI int GetFPS(void); // Get current FPS
|
||||||
|
|
||||||
|
// Custom frame control functions
|
||||||
|
// NOTE: Those functions are intended for advance users that want full control over the frame processing
|
||||||
|
// By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timing + PollInputEvents()
|
||||||
|
// To avoid that behaviour and control frame processes manually, enable in config.h: SUPPORT_CUSTOM_FRAME_CONTROL
|
||||||
|
RLAPI void SwapScreenBuffer(void); // Swap back buffer with front buffer (screen drawing)
|
||||||
|
RLAPI void PollInputEvents(void); // Register all input events
|
||||||
|
RLAPI void WaitTime(double seconds); // Wait for some time (halt program execution)
|
||||||
|
|
||||||
|
// Random values generation functions
|
||||||
|
RLAPI void SetRandomSeed(unsigned int seed); // Set the seed for the random number generator
|
||||||
|
RLAPI int GetRandomValue(int min, int max); // Get a random value between min and max (both included)
|
||||||
|
RLAPI int *LoadRandomSequence(unsigned int count, int min, int max); // Load random values sequence, no values repeated
|
||||||
|
RLAPI void UnloadRandomSequence(int *sequence); // Unload random values sequence
|
||||||
|
|
||||||
// Misc. functions
|
// Misc. functions
|
||||||
RLAPI int GetRandomValue(int min, int max); // Get a random value between min and max (both included)
|
|
||||||
RLAPI void SetRandomSeed(unsigned int seed); // Set the seed for the random number generator
|
|
||||||
RLAPI void TakeScreenshot(const char *fileName); // Takes a screenshot of current screen (filename extension defines format)
|
RLAPI void TakeScreenshot(const char *fileName); // Takes a screenshot of current screen (filename extension defines format)
|
||||||
RLAPI void SetConfigFlags(unsigned int flags); // Setup init configuration flags (view FLAGS)
|
RLAPI void SetConfigFlags(unsigned int flags); // Setup init configuration flags (view FLAGS)
|
||||||
|
RLAPI void OpenURL(const char *url); // Open URL with default system browser (if available)
|
||||||
|
|
||||||
|
// NOTE: Following functions implemented in module [utils]
|
||||||
|
//------------------------------------------------------------------
|
||||||
RLAPI void TraceLog(int logLevel, const char *text, ...); // Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...)
|
RLAPI void TraceLog(int logLevel, const char *text, ...); // Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...)
|
||||||
RLAPI void SetTraceLogLevel(int logLevel); // Set the current threshold (minimum) log level
|
RLAPI void SetTraceLogLevel(int logLevel); // Set the current threshold (minimum) log level
|
||||||
RLAPI void *MemAlloc(unsigned int size); // Internal memory allocator
|
RLAPI void *MemAlloc(unsigned int size); // Internal memory allocator
|
||||||
RLAPI void *MemRealloc(void *ptr, unsigned int size); // Internal memory reallocator
|
RLAPI void *MemRealloc(void *ptr, unsigned int size); // Internal memory reallocator
|
||||||
RLAPI void MemFree(void *ptr); // Internal memory free
|
RLAPI void MemFree(void *ptr); // Internal memory free
|
||||||
|
|
||||||
RLAPI void OpenURL(const char *url); // Open URL with default system browser (if available)
|
|
||||||
|
|
||||||
// Set custom callbacks
|
// Set custom callbacks
|
||||||
// WARNING: Callbacks setup is intended for advance users
|
// WARNING: Callbacks setup is intended for advance users
|
||||||
RLAPI void SetTraceLogCallback(TraceLogCallback callback); // Set custom trace log
|
RLAPI void SetTraceLogCallback(TraceLogCallback callback); // Set custom trace log
|
||||||
|
@ -1060,13 +1095,16 @@ RLAPI void SetLoadFileTextCallback(LoadFileTextCallback callback); // Set custom
|
||||||
RLAPI void SetSaveFileTextCallback(SaveFileTextCallback callback); // Set custom file text data saver
|
RLAPI void SetSaveFileTextCallback(SaveFileTextCallback callback); // Set custom file text data saver
|
||||||
|
|
||||||
// Files management functions
|
// Files management functions
|
||||||
RLAPI unsigned char *LoadFileData(const char *fileName, unsigned int *bytesRead); // Load file data as byte array (read)
|
RLAPI unsigned char *LoadFileData(const char *fileName, int *dataSize); // Load file data as byte array (read)
|
||||||
RLAPI void UnloadFileData(unsigned char *data); // Unload file data allocated by LoadFileData()
|
RLAPI void UnloadFileData(unsigned char *data); // Unload file data allocated by LoadFileData()
|
||||||
RLAPI bool SaveFileData(const char *fileName, void *data, unsigned int bytesToWrite); // Save data to file from byte array (write), returns true on success
|
RLAPI bool SaveFileData(const char *fileName, void *data, int dataSize); // Save data to file from byte array (write), returns true on success
|
||||||
RLAPI bool ExportDataAsCode(const unsigned char *data, unsigned int size, const char *fileName); // Export data to code (.h), returns true on success
|
RLAPI bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileName); // Export data to code (.h), returns true on success
|
||||||
RLAPI char *LoadFileText(const char *fileName); // Load text data from file (read), returns a '\0' terminated string
|
RLAPI char *LoadFileText(const char *fileName); // Load text data from file (read), returns a '\0' terminated string
|
||||||
RLAPI void UnloadFileText(char *text); // Unload file text data allocated by LoadFileText()
|
RLAPI void UnloadFileText(char *text); // Unload file text data allocated by LoadFileText()
|
||||||
RLAPI bool SaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated, returns true on success
|
RLAPI bool SaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated, returns true on success
|
||||||
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
|
// File system functions
|
||||||
RLAPI bool FileExists(const char *fileName); // Check if file exists
|
RLAPI bool FileExists(const char *fileName); // Check if file exists
|
||||||
RLAPI bool DirectoryExists(const char *dirPath); // Check if a directory path exists
|
RLAPI bool DirectoryExists(const char *dirPath); // Check if a directory path exists
|
||||||
RLAPI bool IsFileExtension(const char *fileName, const char *ext); // Check file extension (including point: .png, .wav)
|
RLAPI bool IsFileExtension(const char *fileName, const char *ext); // Check file extension (including point: .png, .wav)
|
||||||
|
@ -1077,7 +1115,7 @@ RLAPI const char *GetFileNameWithoutExt(const char *filePath); // Get filenam
|
||||||
RLAPI const char *GetDirectoryPath(const char *filePath); // Get full path for a given fileName with path (uses static string)
|
RLAPI const char *GetDirectoryPath(const char *filePath); // Get full path for a given fileName with path (uses static string)
|
||||||
RLAPI const char *GetPrevDirectoryPath(const char *dirPath); // Get previous directory path for a given path (uses static string)
|
RLAPI const char *GetPrevDirectoryPath(const char *dirPath); // Get previous directory path for a given path (uses static string)
|
||||||
RLAPI const char *GetWorkingDirectory(void); // Get current working directory (uses static string)
|
RLAPI const char *GetWorkingDirectory(void); // Get current working directory (uses static string)
|
||||||
RLAPI const char *GetApplicationDirectory(void); // Get the directory if the running application (uses static string)
|
RLAPI const char *GetApplicationDirectory(void); // Get the directory of the running application (uses static string)
|
||||||
RLAPI bool ChangeDirectory(const char *dir); // Change working directory, return true on success
|
RLAPI bool ChangeDirectory(const char *dir); // Change working directory, return true on success
|
||||||
RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory
|
RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory
|
||||||
RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths
|
RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths
|
||||||
|
@ -1094,18 +1132,29 @@ RLAPI unsigned char *DecompressData(const unsigned char *compData, int compDataS
|
||||||
RLAPI char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize); // Encode data to Base64 string, memory must be MemFree()
|
RLAPI char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize); // Encode data to Base64 string, memory must be MemFree()
|
||||||
RLAPI unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize); // Decode Base64 string data, memory must be MemFree()
|
RLAPI unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize); // Decode Base64 string data, memory must be MemFree()
|
||||||
|
|
||||||
|
// Automation events functionality
|
||||||
|
RLAPI AutomationEventList LoadAutomationEventList(const char *fileName); // Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS
|
||||||
|
RLAPI void UnloadAutomationEventList(AutomationEventList *list); // Unload automation events list from file
|
||||||
|
RLAPI bool ExportAutomationEventList(AutomationEventList list, const char *fileName); // Export automation events list as text file
|
||||||
|
RLAPI void SetAutomationEventList(AutomationEventList *list); // Set automation event list to record to
|
||||||
|
RLAPI void SetAutomationEventBaseFrame(int frame); // Set automation event internal base frame to start recording
|
||||||
|
RLAPI void StartAutomationEventRecording(void); // Start recording automation events (AutomationEventList must be set)
|
||||||
|
RLAPI void StopAutomationEventRecording(void); // Stop recording automation events
|
||||||
|
RLAPI void PlayAutomationEvent(AutomationEvent event); // Play a recorded automation event
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Input Handling Functions (Module: core)
|
// Input Handling Functions (Module: core)
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Input-related functions: keyboard
|
// Input-related functions: keyboard
|
||||||
RLAPI bool IsKeyPressed(int key); // Check if a key has been pressed once
|
RLAPI bool IsKeyPressed(int key); // Check if a key has been pressed once
|
||||||
|
RLAPI bool IsKeyPressedRepeat(int key); // Check if a key has been pressed again (Only PLATFORM_DESKTOP)
|
||||||
RLAPI bool IsKeyDown(int key); // Check if a key is being pressed
|
RLAPI bool IsKeyDown(int key); // Check if a key is being pressed
|
||||||
RLAPI bool IsKeyReleased(int key); // Check if a key has been released once
|
RLAPI bool IsKeyReleased(int key); // Check if a key has been released once
|
||||||
RLAPI bool IsKeyUp(int key); // Check if a key is NOT being pressed
|
RLAPI bool IsKeyUp(int key); // Check if a key is NOT being pressed
|
||||||
RLAPI void SetExitKey(int key); // Set a custom key to exit program (default is ESC)
|
|
||||||
RLAPI int GetKeyPressed(void); // Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty
|
RLAPI int GetKeyPressed(void); // Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty
|
||||||
RLAPI int GetCharPressed(void); // Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty
|
RLAPI int GetCharPressed(void); // Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty
|
||||||
|
RLAPI void SetExitKey(int key); // Set a custom key to exit program (default is ESC)
|
||||||
|
|
||||||
// Input-related functions: gamepads
|
// Input-related functions: gamepads
|
||||||
RLAPI bool IsGamepadAvailable(int gamepad); // Check if a gamepad is available
|
RLAPI bool IsGamepadAvailable(int gamepad); // Check if a gamepad is available
|
||||||
|
@ -1146,7 +1195,7 @@ RLAPI int GetTouchPointCount(void); // Get number of t
|
||||||
// Gestures and Touch Handling Functions (Module: rgestures)
|
// Gestures and Touch Handling Functions (Module: rgestures)
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
RLAPI void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
|
RLAPI void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
|
||||||
RLAPI bool IsGestureDetected(int gesture); // Check if a gesture have been detected
|
RLAPI bool IsGestureDetected(unsigned int gesture); // Check if a gesture have been detected
|
||||||
RLAPI int GetGestureDetected(void); // Get latest detected gesture
|
RLAPI int GetGestureDetected(void); // Get latest detected gesture
|
||||||
RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds
|
RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds
|
||||||
RLAPI Vector2 GetGestureDragVector(void); // Get gesture drag vector
|
RLAPI Vector2 GetGestureDragVector(void); // Get gesture drag vector
|
||||||
|
@ -1177,6 +1226,8 @@ RLAPI void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color
|
||||||
RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line using cubic-bezier curves in-out
|
RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line using cubic-bezier curves in-out
|
||||||
RLAPI void DrawLineBezierQuad(Vector2 startPos, Vector2 endPos, Vector2 controlPos, float thick, Color color); // Draw line using quadratic bezier curves with a control point
|
RLAPI void DrawLineBezierQuad(Vector2 startPos, Vector2 endPos, Vector2 controlPos, float thick, Color color); // Draw line using quadratic bezier curves with a control point
|
||||||
RLAPI void DrawLineBezierCubic(Vector2 startPos, Vector2 endPos, Vector2 startControlPos, Vector2 endControlPos, float thick, Color color); // Draw line using cubic bezier curves with 2 control points
|
RLAPI void DrawLineBezierCubic(Vector2 startPos, Vector2 endPos, Vector2 startControlPos, Vector2 endControlPos, float thick, Color color); // Draw line using cubic bezier curves with 2 control points
|
||||||
|
RLAPI void DrawLineBSpline(Vector2 *points, int pointCount, float thick, Color color); // Draw a B-Spline line, minimum 4 points
|
||||||
|
RLAPI void DrawLineCatmullRom(Vector2 *points, int pointCount, float thick, Color color); // Draw a Catmull Rom spline line, minimum 4 points
|
||||||
RLAPI void DrawLineStrip(Vector2 *points, int pointCount, Color color); // Draw lines sequence
|
RLAPI void DrawLineStrip(Vector2 *points, int pointCount, Color color); // Draw lines sequence
|
||||||
RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle
|
RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle
|
||||||
RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle
|
RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle
|
||||||
|
@ -1184,6 +1235,7 @@ RLAPI void DrawCircleSectorLines(Vector2 center, float radius, float startAngle,
|
||||||
RLAPI void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2); // Draw a gradient-filled circle
|
RLAPI void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2); // Draw a gradient-filled circle
|
||||||
RLAPI void DrawCircleV(Vector2 center, float radius, Color color); // Draw a color-filled circle (Vector version)
|
RLAPI void DrawCircleV(Vector2 center, float radius, Color color); // Draw a color-filled circle (Vector version)
|
||||||
RLAPI void DrawCircleLines(int centerX, int centerY, float radius, Color color); // Draw circle outline
|
RLAPI void DrawCircleLines(int centerX, int centerY, float radius, Color color); // Draw circle outline
|
||||||
|
RLAPI void DrawCircleLinesV(Vector2 center, float radius, Color color); // Draw circle outline (Vector version)
|
||||||
RLAPI void DrawEllipse(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse
|
RLAPI void DrawEllipse(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse
|
||||||
RLAPI void DrawEllipseLines(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse outline
|
RLAPI void DrawEllipseLines(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse outline
|
||||||
RLAPI void DrawRing(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color); // Draw ring
|
RLAPI void DrawRing(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color); // Draw ring
|
||||||
|
@ -1227,6 +1279,7 @@ RLAPI Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2);
|
||||||
// NOTE: These functions do not require GPU access
|
// NOTE: These functions do not require GPU access
|
||||||
RLAPI Image LoadImage(const char *fileName); // Load image from file into CPU memory (RAM)
|
RLAPI Image LoadImage(const char *fileName); // Load image from file into CPU memory (RAM)
|
||||||
RLAPI Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize); // Load image from RAW file data
|
RLAPI Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize); // Load image from RAW file data
|
||||||
|
RLAPI Image LoadImageSvg(const char *fileNameOrString, int width, int height); // Load image from SVG file data or string with specified size
|
||||||
RLAPI Image LoadImageAnim(const char *fileName, int *frames); // Load image sequence from file (frames appended to image.data)
|
RLAPI Image LoadImageAnim(const char *fileName, int *frames); // Load image sequence from file (frames appended to image.data)
|
||||||
RLAPI Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load image from memory buffer, fileType refers to extension: i.e. '.png'
|
RLAPI Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load image from memory buffer, fileType refers to extension: i.e. '.png'
|
||||||
RLAPI Image LoadImageFromTexture(Texture2D texture); // Load image from GPU texture data
|
RLAPI Image LoadImageFromTexture(Texture2D texture); // Load image from GPU texture data
|
||||||
|
@ -1234,13 +1287,14 @@ RLAPI Image LoadImageFromScreen(void);
|
||||||
RLAPI bool IsImageReady(Image image); // Check if an image is ready
|
RLAPI bool IsImageReady(Image image); // Check if an image is ready
|
||||||
RLAPI void UnloadImage(Image image); // Unload image from CPU memory (RAM)
|
RLAPI void UnloadImage(Image image); // Unload image from CPU memory (RAM)
|
||||||
RLAPI bool ExportImage(Image image, const char *fileName); // Export image data to file, returns true on success
|
RLAPI bool ExportImage(Image image, const char *fileName); // Export image data to file, returns true on success
|
||||||
|
RLAPI unsigned char *ExportImageToMemory(Image image, const char *fileType, int *fileSize); // Export image to memory buffer
|
||||||
RLAPI bool ExportImageAsCode(Image image, const char *fileName); // Export image as code file defining an array of bytes, returns true on success
|
RLAPI bool ExportImageAsCode(Image image, const char *fileName); // Export image as code file defining an array of bytes, returns true on success
|
||||||
|
|
||||||
// Image generation functions
|
// Image generation functions
|
||||||
RLAPI Image GenImageColor(int width, int height, Color color); // Generate image: plain color
|
RLAPI Image GenImageColor(int width, int height, Color color); // Generate image: plain color
|
||||||
RLAPI Image GenImageGradientV(int width, int height, Color top, Color bottom); // Generate image: vertical gradient
|
RLAPI Image GenImageGradientLinear(int width, int height, int direction, Color start, Color end); // Generate image: linear gradient, direction in degrees [0..360], 0=Vertical gradient
|
||||||
RLAPI Image GenImageGradientH(int width, int height, Color left, Color right); // Generate image: horizontal gradient
|
|
||||||
RLAPI Image GenImageGradientRadial(int width, int height, float density, Color inner, Color outer); // Generate image: radial gradient
|
RLAPI Image GenImageGradientRadial(int width, int height, float density, Color inner, Color outer); // Generate image: radial gradient
|
||||||
|
RLAPI Image GenImageGradientSquare(int width, int height, float density, Color inner, Color outer); // Generate image: square gradient
|
||||||
RLAPI Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2); // Generate image: checked
|
RLAPI Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2); // Generate image: checked
|
||||||
RLAPI Image GenImageWhiteNoise(int width, int height, float factor); // Generate image: white noise
|
RLAPI Image GenImageWhiteNoise(int width, int height, float factor); // Generate image: white noise
|
||||||
RLAPI Image GenImagePerlinNoise(int width, int height, int offsetX, int offsetY, float scale); // Generate image: perlin noise
|
RLAPI Image GenImagePerlinNoise(int width, int height, int offsetX, int offsetY, float scale); // Generate image: perlin noise
|
||||||
|
@ -1267,6 +1321,7 @@ RLAPI void ImageMipmaps(Image *image);
|
||||||
RLAPI void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp); // Dither image data to 16bpp or lower (Floyd-Steinberg dithering)
|
RLAPI void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp); // Dither image data to 16bpp or lower (Floyd-Steinberg dithering)
|
||||||
RLAPI void ImageFlipVertical(Image *image); // Flip image vertically
|
RLAPI void ImageFlipVertical(Image *image); // Flip image vertically
|
||||||
RLAPI void ImageFlipHorizontal(Image *image); // Flip image horizontally
|
RLAPI void ImageFlipHorizontal(Image *image); // Flip image horizontally
|
||||||
|
RLAPI void ImageRotate(Image *image, int degrees); // Rotate image by input angle in degrees (-359 to 359)
|
||||||
RLAPI void ImageRotateCW(Image *image); // Rotate image clockwise 90deg
|
RLAPI void ImageRotateCW(Image *image); // Rotate image clockwise 90deg
|
||||||
RLAPI void ImageRotateCCW(Image *image); // Rotate image counter-clockwise 90deg
|
RLAPI void ImageRotateCCW(Image *image); // Rotate image counter-clockwise 90deg
|
||||||
RLAPI void ImageColorTint(Image *image, Color color); // Modify image color: tint
|
RLAPI void ImageColorTint(Image *image, Color color); // Modify image color: tint
|
||||||
|
@ -1351,13 +1406,13 @@ RLAPI int GetPixelDataSize(int width, int height, int format); // G
|
||||||
// Font loading/unloading functions
|
// Font loading/unloading functions
|
||||||
RLAPI Font GetFontDefault(void); // Get the default Font
|
RLAPI Font GetFontDefault(void); // Get the default Font
|
||||||
RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM)
|
RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM)
|
||||||
RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int glyphCount); // Load font from file with extended parameters, use NULL for fontChars and 0 for glyphCount to load the default character set
|
RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set
|
||||||
RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style)
|
RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style)
|
||||||
RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int glyphCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf'
|
RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf'
|
||||||
RLAPI bool IsFontReady(Font font); // Check if a font is ready
|
RLAPI bool IsFontReady(Font font); // Check if a font is ready
|
||||||
RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int glyphCount, int type); // Load font data for further use
|
RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount, int type); // Load font data for further use
|
||||||
RLAPI Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **recs, int glyphCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info
|
RLAPI Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyphCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info
|
||||||
RLAPI void UnloadFontData(GlyphInfo *chars, int glyphCount); // Unload font chars info data (RAM)
|
RLAPI void UnloadFontData(GlyphInfo *glyphs, int glyphCount); // Unload font chars info data (RAM)
|
||||||
RLAPI void UnloadFont(Font font); // Unload font from GPU memory (VRAM)
|
RLAPI void UnloadFont(Font font); // Unload font from GPU memory (VRAM)
|
||||||
RLAPI bool ExportFontAsCode(Font font, const char *fileName); // Export font as code file, returns true on success
|
RLAPI bool ExportFontAsCode(Font font, const char *fileName); // Export font as code file, returns true on success
|
||||||
|
|
||||||
|
@ -1367,9 +1422,10 @@ RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color co
|
||||||
RLAPI void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters
|
RLAPI void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters
|
||||||
RLAPI void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint); // Draw text using Font and pro parameters (rotation)
|
RLAPI void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint); // Draw text using Font and pro parameters (rotation)
|
||||||
RLAPI void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSize, Color tint); // Draw one character (codepoint)
|
RLAPI void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSize, Color tint); // Draw one character (codepoint)
|
||||||
RLAPI void DrawTextCodepoints(Font font, const int *codepoints, int count, Vector2 position, float fontSize, float spacing, Color tint); // Draw multiple character (codepoint)
|
RLAPI void DrawTextCodepoints(Font font, const int *codepoints, int codepointCount, Vector2 position, float fontSize, float spacing, Color tint); // Draw multiple character (codepoint)
|
||||||
|
|
||||||
// Text font info functions
|
// Text font info functions
|
||||||
|
RLAPI void SetTextLineSpacing(int spacing); // Set vertical line spacing when drawing with line-breaks
|
||||||
RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font
|
RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font
|
||||||
RLAPI Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // Measure string size for Font
|
RLAPI Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // Measure string size for Font
|
||||||
RLAPI int GetGlyphIndex(Font font, int codepoint); // Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found
|
RLAPI int GetGlyphIndex(Font font, int codepoint); // Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found
|
||||||
|
@ -1485,10 +1541,10 @@ RLAPI void SetMaterialTexture(Material *material, int mapType, Texture2D texture
|
||||||
RLAPI void SetModelMeshMaterial(Model *model, int meshId, int materialId); // Set material for a mesh
|
RLAPI void SetModelMeshMaterial(Model *model, int meshId, int materialId); // Set material for a mesh
|
||||||
|
|
||||||
// Model animations loading/unloading functions
|
// Model animations loading/unloading functions
|
||||||
RLAPI ModelAnimation *LoadModelAnimations(const char *fileName, unsigned int *animCount); // Load model animations from file
|
RLAPI ModelAnimation *LoadModelAnimations(const char *fileName, int *animCount); // Load model animations from file
|
||||||
RLAPI void UpdateModelAnimation(Model model, ModelAnimation anim, int frame); // Update model animation pose
|
RLAPI void UpdateModelAnimation(Model model, ModelAnimation anim, int frame); // Update model animation pose
|
||||||
RLAPI void UnloadModelAnimation(ModelAnimation anim); // Unload animation data
|
RLAPI void UnloadModelAnimation(ModelAnimation anim); // Unload animation data
|
||||||
RLAPI void UnloadModelAnimations(ModelAnimation *animations, unsigned int count); // Unload animation array data
|
RLAPI void UnloadModelAnimations(ModelAnimation *animations, int animCount); // Unload animation array data
|
||||||
RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match
|
RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match
|
||||||
|
|
||||||
// Collision detection functions
|
// Collision detection functions
|
||||||
|
@ -1511,6 +1567,7 @@ RLAPI void InitAudioDevice(void); // Initial
|
||||||
RLAPI void CloseAudioDevice(void); // Close the audio device and context
|
RLAPI void CloseAudioDevice(void); // Close the audio device and context
|
||||||
RLAPI bool IsAudioDeviceReady(void); // Check if audio device has been initialized successfully
|
RLAPI bool IsAudioDeviceReady(void); // Check if audio device has been initialized successfully
|
||||||
RLAPI void SetMasterVolume(float volume); // Set master volume (listener)
|
RLAPI void SetMasterVolume(float volume); // Set master volume (listener)
|
||||||
|
RLAPI float GetMasterVolume(void); // Get master volume (listener)
|
||||||
|
|
||||||
// Wave/Sound loading/unloading functions
|
// Wave/Sound loading/unloading functions
|
||||||
RLAPI Wave LoadWave(const char *fileName); // Load wave data from file
|
RLAPI Wave LoadWave(const char *fileName); // Load wave data from file
|
||||||
|
@ -1518,10 +1575,12 @@ RLAPI Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileDat
|
||||||
RLAPI bool IsWaveReady(Wave wave); // Checks if wave data is ready
|
RLAPI bool IsWaveReady(Wave wave); // Checks if wave data is ready
|
||||||
RLAPI Sound LoadSound(const char *fileName); // Load sound from file
|
RLAPI Sound LoadSound(const char *fileName); // Load sound from file
|
||||||
RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound from wave data
|
RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound from wave data
|
||||||
|
RLAPI Sound LoadSoundAlias(Sound source); // Create a new sound that shares the same sample data as the source sound, does not own the sound data
|
||||||
RLAPI bool IsSoundReady(Sound sound); // Checks if a sound is ready
|
RLAPI bool IsSoundReady(Sound sound); // Checks if a sound is ready
|
||||||
RLAPI void UpdateSound(Sound sound, const void *data, int sampleCount); // Update sound buffer with new data
|
RLAPI void UpdateSound(Sound sound, const void *data, int sampleCount); // Update sound buffer with new data
|
||||||
RLAPI void UnloadWave(Wave wave); // Unload wave data
|
RLAPI void UnloadWave(Wave wave); // Unload wave data
|
||||||
RLAPI void UnloadSound(Sound sound); // Unload sound
|
RLAPI void UnloadSound(Sound sound); // Unload sound
|
||||||
|
RLAPI void UnloadSoundAlias(Sound alias); // Unload a sound alias (does not deallocate sample data)
|
||||||
RLAPI bool ExportWave(Wave wave, const char *fileName); // Export wave data to file, returns true on success
|
RLAPI bool ExportWave(Wave wave, const char *fileName); // Export wave data to file, returns true on success
|
||||||
RLAPI bool ExportWaveAsCode(Wave wave, const char *fileName); // Export wave sample data to code (.h), returns true on success
|
RLAPI bool ExportWaveAsCode(Wave wave, const char *fileName); // Export wave sample data to code (.h), returns true on success
|
||||||
|
|
||||||
|
@ -1575,10 +1634,10 @@ RLAPI void SetAudioStreamPan(AudioStream stream, float pan); // Set pan
|
||||||
RLAPI void SetAudioStreamBufferSizeDefault(int size); // Default size for new audio streams
|
RLAPI void SetAudioStreamBufferSizeDefault(int size); // Default size for new audio streams
|
||||||
RLAPI void SetAudioStreamCallback(AudioStream stream, AudioCallback callback); // Audio thread callback to request new data
|
RLAPI void SetAudioStreamCallback(AudioStream stream, AudioCallback callback); // Audio thread callback to request new data
|
||||||
|
|
||||||
RLAPI void AttachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Attach audio stream processor to stream
|
RLAPI void AttachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Attach audio stream processor to stream, receives the samples as <float>s
|
||||||
RLAPI void DetachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Detach audio stream processor from stream
|
RLAPI void DetachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Detach audio stream processor from stream
|
||||||
|
|
||||||
RLAPI void AttachAudioMixedProcessor(AudioCallback processor); // Attach audio stream processor to the entire audio pipeline
|
RLAPI void AttachAudioMixedProcessor(AudioCallback processor); // Attach audio stream processor to the entire audio pipeline, receives the samples as <float>s
|
||||||
RLAPI void DetachAudioMixedProcessor(AudioCallback processor); // Detach audio stream processor from the entire audio pipeline
|
RLAPI void DetachAudioMixedProcessor(AudioCallback processor); // Detach audio stream processor from the entire audio pipeline
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue