Update C sources
This commit is contained in:
parent
dd222de786
commit
b83dec57b5
14 changed files with 2900 additions and 1289 deletions
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2018-2021 Ahmad Fatoum & Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2018-2022 Ahmad Fatoum & 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.
|
||||
|
@ -26,7 +26,17 @@
|
|||
**********************************************************************************************/
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Module: core - Configuration Flags
|
||||
// Module selection - Some modules could be avoided
|
||||
// Mandatory modules: rcore, rlgl, utils
|
||||
//------------------------------------------------------------------------------------
|
||||
#define SUPPORT_MODULE_RSHAPES 1
|
||||
#define SUPPORT_MODULE_RTEXTURES 1
|
||||
#define SUPPORT_MODULE_RTEXT 1 // WARNING: It requires SUPPORT_MODULE_RTEXTURES to load sprite font textures
|
||||
#define SUPPORT_MODULE_RMODELS 1
|
||||
#define SUPPORT_MODULE_RAUDIO 1
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Module: rcore - Configuration Flags
|
||||
//------------------------------------------------------------------------------------
|
||||
// Camera module is included (rcamera.h) and multiple predefined cameras are available: free, 1st/3rd person, orbital
|
||||
#define SUPPORT_CAMERA_SYSTEM 1
|
||||
|
@ -36,8 +46,6 @@
|
|||
#define SUPPORT_MOUSE_GESTURES 1
|
||||
// Reconfigure standard input to receive key inputs, works with SSH connection.
|
||||
#define SUPPORT_SSH_KEYBOARD_RPI 1
|
||||
// Draw a mouse pointer on screen
|
||||
//#define SUPPORT_MOUSE_CURSOR_POINT 1
|
||||
// Setting a higher resolution can improve the accuracy of time-out intervals in wait functions.
|
||||
// However, it can also reduce overall system performance, because the thread scheduler switches tasks more often.
|
||||
#define SUPPORT_WINMM_HIGHRES_TIMER 1
|
||||
|
@ -53,8 +61,6 @@
|
|||
#define SUPPORT_GIF_RECORDING 1
|
||||
// Support CompressData() and DecompressData() functions
|
||||
#define SUPPORT_COMPRESSION_API 1
|
||||
// Support saving binary data automatically to a generated storage.data file. This file is managed internally.
|
||||
#define SUPPORT_DATA_STORAGE 1
|
||||
// Support automatic generated events, loading and recording of those events when required
|
||||
//#define SUPPORT_EVENTS_AUTOMATION 1
|
||||
// Support custom frame control, only for advance users
|
||||
|
@ -62,21 +68,19 @@
|
|||
// Enabling this flag allows manual control of the frame processes, use at your own risk
|
||||
//#define SUPPORT_CUSTOM_FRAME_CONTROL 1
|
||||
|
||||
// core: Configuration values
|
||||
// rcore: Configuration values
|
||||
//------------------------------------------------------------------------------------
|
||||
#if defined(__linux__)
|
||||
#define MAX_FILEPATH_LENGTH 4096 // Maximum length for filepaths (Linux PATH_MAX default value)
|
||||
#else
|
||||
#define MAX_FILEPATH_LENGTH 512 // Maximum length supported for filepaths
|
||||
#endif
|
||||
#define MAX_FILEPATH_CAPACITY 8192 // Maximum file paths capacity
|
||||
#define MAX_FILEPATH_LENGTH 4096 // Maximum length for filepaths (Linux PATH_MAX default value)
|
||||
|
||||
#define MAX_GAMEPADS 4 // Max number of gamepads supported
|
||||
#define MAX_GAMEPAD_AXIS 8 // Max number of axis supported (per gamepad)
|
||||
#define MAX_GAMEPAD_BUTTONS 32 // Max bumber of buttons supported (per gamepad)
|
||||
#define MAX_KEYBOARD_KEYS 512 // Maximum number of keyboard keys supported
|
||||
#define MAX_MOUSE_BUTTONS 8 // Maximum number of mouse buttons supported
|
||||
#define MAX_GAMEPADS 4 // Maximum number of gamepads supported
|
||||
#define MAX_GAMEPAD_AXIS 8 // Maximum number of axis supported (per gamepad)
|
||||
#define MAX_GAMEPAD_BUTTONS 32 // Maximum number of buttons supported (per gamepad)
|
||||
#define MAX_TOUCH_POINTS 8 // Maximum number of touch points supported
|
||||
#define MAX_KEY_PRESSED_QUEUE 16 // Max number of characters in the key input queue
|
||||
|
||||
#define STORAGE_DATA_FILE "storage.data" // Automatic storage filename
|
||||
#define MAX_KEY_PRESSED_QUEUE 16 // Maximum number of keys in the key input queue
|
||||
#define MAX_CHAR_PRESSED_QUEUE 16 // Maximum number of characters in the char input queue
|
||||
|
||||
#define MAX_DECOMPRESSION_SIZE 64 // Max size allocated for decompression in MB
|
||||
|
||||
|
@ -124,7 +128,7 @@
|
|||
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Module: shapes - Configuration Flags
|
||||
// Module: rshapes - Configuration Flags
|
||||
//------------------------------------------------------------------------------------
|
||||
// Use QUADS instead of TRIANGLES for drawing when possible
|
||||
// Some lines-based shapes could still use lines
|
||||
|
@ -132,7 +136,7 @@
|
|||
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Module: textures - Configuration Flags
|
||||
// Module: rtextures - Configuration Flags
|
||||
//------------------------------------------------------------------------------------
|
||||
// Selecte desired fileformats to be supported for image data loading
|
||||
#define SUPPORT_FILEFORMAT_PNG 1
|
||||
|
@ -140,6 +144,7 @@
|
|||
//#define SUPPORT_FILEFORMAT_TGA 1
|
||||
#define SUPPORT_FILEFORMAT_JPG 1
|
||||
#define SUPPORT_FILEFORMAT_GIF 1
|
||||
#define SUPPORT_FILEFORMAT_QOI 1
|
||||
//#define SUPPORT_FILEFORMAT_PSD 1
|
||||
#define SUPPORT_FILEFORMAT_DDS 1
|
||||
#define SUPPORT_FILEFORMAT_HDR 1
|
||||
|
@ -148,7 +153,7 @@
|
|||
//#define SUPPORT_FILEFORMAT_PKM 1
|
||||
//#define SUPPORT_FILEFORMAT_PVR 1
|
||||
|
||||
// Support image export functionality (.png, .bmp, .tga, .jpg)
|
||||
// Support image export functionality (.png, .bmp, .tga, .jpg, .qoi)
|
||||
#define SUPPORT_IMAGE_EXPORT 1
|
||||
// Support procedural image generation functionality (gradient, spot, perlin-noise, cellular)
|
||||
#define SUPPORT_IMAGE_GENERATION 1
|
||||
|
@ -158,7 +163,7 @@
|
|||
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Module: text - Configuration Flags
|
||||
// Module: rtext - Configuration Flags
|
||||
//------------------------------------------------------------------------------------
|
||||
// Default font is loaded on window initialization to be available for the user to render simple text
|
||||
// NOTE: If enabled, uses external module functions to load default raylib font
|
||||
|
@ -171,7 +176,7 @@
|
|||
// If not defined, still some functions are supported: TextLength(), TextFormat()
|
||||
#define SUPPORT_TEXT_MANIPULATION 1
|
||||
|
||||
// text: Configuration values
|
||||
// rtext: Configuration values
|
||||
//------------------------------------------------------------------------------------
|
||||
#define MAX_TEXT_BUFFER_LENGTH 1024 // Size of internal static buffers used on some functions:
|
||||
// TextFormat(), TextSubtext(), TextToUpper(), TextToLower(), TextToPascal(), TextSplit()
|
||||
|
@ -179,7 +184,7 @@
|
|||
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Module: models - Configuration Flags
|
||||
// Module: rmodels - Configuration Flags
|
||||
//------------------------------------------------------------------------------------
|
||||
// Selected desired model fileformats to be supported for loading
|
||||
#define SUPPORT_FILEFORMAT_OBJ 1
|
||||
|
@ -187,17 +192,18 @@
|
|||
#define SUPPORT_FILEFORMAT_IQM 1
|
||||
#define SUPPORT_FILEFORMAT_GLTF 1
|
||||
#define SUPPORT_FILEFORMAT_VOX 1
|
||||
#define SUPPORT_FILEFORMAT_M3D 1
|
||||
// Support procedural mesh generation functions, uses external par_shapes.h library
|
||||
// NOTE: Some generated meshes DO NOT include generated texture coordinates
|
||||
#define SUPPORT_MESH_GENERATION 1
|
||||
|
||||
// models: Configuration values
|
||||
// rmodels: Configuration values
|
||||
//------------------------------------------------------------------------------------
|
||||
#define MAX_MATERIAL_MAPS 12 // Maximum number of shader maps supported
|
||||
#define MAX_MESH_VERTEX_BUFFERS 7 // Maximum vertex buffers (VBO) per mesh
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Module: audio - Configuration Flags
|
||||
// Module: raudio - Configuration Flags
|
||||
//------------------------------------------------------------------------------------
|
||||
// Desired audio fileformats to be supported for loading
|
||||
#define SUPPORT_FILEFORMAT_WAV 1
|
||||
|
@ -207,7 +213,7 @@
|
|||
#define SUPPORT_FILEFORMAT_MP3 1
|
||||
//#define SUPPORT_FILEFORMAT_FLAC 1
|
||||
|
||||
// audio: Configuration values
|
||||
// raudio: Configuration values
|
||||
//------------------------------------------------------------------------------------
|
||||
#define AUDIO_DEVICE_FORMAT ma_format_f32 // Device output format (miniaudio: float-32bit)
|
||||
#define AUDIO_DEVICE_CHANNELS 2 // Device output channels: stereo
|
||||
|
|
559
raylib/raudio.c
559
raylib/raudio.c
File diff suppressed because it is too large
Load diff
159
raylib/raylib.h
159
raylib/raylib.h
|
@ -1,6 +1,6 @@
|
|||
/**********************************************************************************************
|
||||
*
|
||||
* raylib v4.0 - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com)
|
||||
* raylib v4.2 - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com)
|
||||
*
|
||||
* FEATURES:
|
||||
* - NO external dependencies, all required libraries included with raylib
|
||||
|
@ -33,8 +33,8 @@
|
|||
*
|
||||
* OPTIONAL DEPENDENCIES (included):
|
||||
* [rcore] msf_gif (Miles Fogle) for GIF recording
|
||||
* [rcore] sinfl (Micha Mettke) for DEFLATE decompression algorythm
|
||||
* [rcore] sdefl (Micha Mettke) for DEFLATE compression algorythm
|
||||
* [rcore] sinfl (Micha Mettke) for DEFLATE decompression algorithm
|
||||
* [rcore] sdefl (Micha Mettke) for DEFLATE compression algorithm
|
||||
* [rtextures] stb_image (Sean Barret) for images loading (BMP, TGA, PNG, JPEG, HDR...)
|
||||
* [rtextures] stb_image_write (Sean Barret) for image writing (BMP, TGA, PNG, JPG)
|
||||
* [rtextures] stb_image_resize (Sean Barret) for image resizing algorithms
|
||||
|
@ -43,6 +43,7 @@
|
|||
* [rmodels] par_shapes (Philip Rideout) for parametric 3d shapes generation
|
||||
* [rmodels] tinyobj_loader_c (Syoyo Fujita) for models loading (OBJ, MTL)
|
||||
* [rmodels] cgltf (Johannes Kuhlmann) for models loading (glTF)
|
||||
* [rmodels] Model3D (bzt) for models loading (M3D, https://bztsrc.gitlab.io/model3d)
|
||||
* [raudio] dr_wav (David Reid) for WAV audio file loading
|
||||
* [raudio] dr_flac (David Reid) for FLAC audio file loading
|
||||
* [raudio] dr_mp3 (David Reid) for MP3 audio file loading
|
||||
|
@ -56,7 +57,7 @@
|
|||
* raylib is licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software:
|
||||
*
|
||||
* Copyright (c) 2013-2021 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2013-2022 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.
|
||||
|
@ -80,12 +81,15 @@
|
|||
|
||||
#include <stdarg.h> // Required for: va_list - Only used by TraceLogCallback
|
||||
|
||||
#define RAYLIB_VERSION "4.0"
|
||||
#define RAYLIB_VERSION "4.2"
|
||||
|
||||
// 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)
|
||||
|
@ -110,6 +114,7 @@
|
|||
#endif
|
||||
|
||||
// Allow custom memory allocators
|
||||
// NOTE: Require recompiling raylib sources
|
||||
#ifndef RL_MALLOC
|
||||
#define RL_MALLOC(sz) malloc(sz)
|
||||
#endif
|
||||
|
@ -177,10 +182,10 @@
|
|||
// Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
// Boolean type
|
||||
#if defined(__STDC__) && __STDC_VERSION__ >= 199901L
|
||||
#if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
|
||||
#include <stdbool.h>
|
||||
#elif !defined(__cplusplus) && !defined(bool)
|
||||
typedef enum bool { false, true } bool;
|
||||
typedef enum bool { false = 0, true = !false } bool;
|
||||
#define RL_BOOL_TYPE
|
||||
#endif
|
||||
|
||||
|
@ -322,7 +327,7 @@ typedef struct Mesh {
|
|||
// Vertex attributes data
|
||||
float *vertices; // Vertex position (XYZ - 3 components per vertex) (shader-location = 0)
|
||||
float *texcoords; // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)
|
||||
float *texcoords2; // Vertex second texture coordinates (useful for lightmaps) (shader-location = 5)
|
||||
float *texcoords2; // Vertex texture second coordinates (UV - 2 components per vertex) (shader-location = 5)
|
||||
float *normals; // Vertex normals (XYZ - 3 components per vertex) (shader-location = 2)
|
||||
float *tangents; // Vertex tangents (XYZW - 4 components per vertex) (shader-location = 4)
|
||||
unsigned char *colors; // Vertex colors (RGBA - 4 components per vertex) (shader-location = 3)
|
||||
|
@ -425,11 +430,15 @@ typedef struct Wave {
|
|||
void *data; // Buffer data pointer
|
||||
} Wave;
|
||||
|
||||
// Opaque structs declaration
|
||||
// NOTE: Actual structs are defined internally in raudio module
|
||||
typedef struct rAudioBuffer rAudioBuffer;
|
||||
typedef struct rAudioProcessor rAudioProcessor;
|
||||
|
||||
// AudioStream, custom audio stream
|
||||
typedef struct AudioStream {
|
||||
rAudioBuffer *buffer; // Pointer to internal data used by the audio system
|
||||
rAudioProcessor *processor; // Pointer to internal data processor, useful for audio effects
|
||||
|
||||
unsigned int sampleRate; // Frequency (samples per second)
|
||||
unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported)
|
||||
|
@ -478,6 +487,13 @@ typedef struct VrStereoConfig {
|
|||
float scaleIn[2]; // VR distortion scale in
|
||||
} VrStereoConfig;
|
||||
|
||||
// File path list
|
||||
typedef struct FilePathList {
|
||||
unsigned int capacity; // Filepaths max entries
|
||||
unsigned int count; // Filepaths entries count
|
||||
char **paths; // Filepaths entries
|
||||
} FilePathList;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Enumerators Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -497,6 +513,7 @@ typedef enum {
|
|||
FLAG_WINDOW_ALWAYS_RUN = 0x00000100, // Set to allow windows running while minimized
|
||||
FLAG_WINDOW_TRANSPARENT = 0x00000010, // Set to allow transparent framebuffer
|
||||
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_MSAA_4X_HINT = 0x00000020, // Set to try enabling MSAA 4X
|
||||
FLAG_INTERLACED_HINT = 0x00010000 // Set to try enabling interlaced video format (for V3D)
|
||||
} ConfigFlags;
|
||||
|
@ -799,7 +816,7 @@ typedef enum {
|
|||
// NOTE 1: Filtering considers mipmaps if available in the texture
|
||||
// NOTE 2: Filter is accordingly set for minification and magnification
|
||||
typedef enum {
|
||||
TEXTURE_FILTER_POINT = 0, // No filter, just pixel aproximation
|
||||
TEXTURE_FILTER_POINT = 0, // No filter, just pixel approximation
|
||||
TEXTURE_FILTER_BILINEAR, // Linear filtering
|
||||
TEXTURE_FILTER_TRILINEAR, // Trilinear filtering (linear with mipmaps)
|
||||
TEXTURE_FILTER_ANISOTROPIC_4X, // Anisotropic filtering 4x
|
||||
|
@ -839,7 +856,8 @@ typedef enum {
|
|||
BLEND_MULTIPLIED, // Blend textures multiplying colors
|
||||
BLEND_ADD_COLORS, // Blend textures adding colors (alternative)
|
||||
BLEND_SUBTRACT_COLORS, // Blend textures subtracting colors (alternative)
|
||||
BLEND_CUSTOM // Belnd textures using custom src/dst factors (use rlSetBlendMode())
|
||||
BLEND_ALPHA_PREMULTIPLY, // Blend premultiplied textures considering alpha
|
||||
BLEND_CUSTOM // Blend textures using custom src/dst factors (use rlSetBlendMode())
|
||||
} BlendMode;
|
||||
|
||||
// Gesture
|
||||
|
@ -885,8 +903,8 @@ typedef enum {
|
|||
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 bool (*SaveFileDataCallback)(const char *fileName, void *data, unsigned int bytesToWrite); // FileIO: Save binary data
|
||||
typedef char *(*LoadFileTextCallback)(const char *fileName); // FileIO: Load text data
|
||||
typedef bool (*SaveFileTextCallback)(const char *fileName, char *text); // FileIO: Save text data
|
||||
typedef char *(*LoadFileTextCallback)(const char *fileName); // FileIO: Load text data
|
||||
typedef bool (*SaveFileTextCallback)(const char *fileName, char *text); // FileIO: Save text data
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Global Variables Definition
|
||||
|
@ -913,7 +931,7 @@ RLAPI bool IsWindowMaximized(void); // Check if wi
|
|||
RLAPI bool IsWindowFocused(void); // Check if window is currently focused (only PLATFORM_DESKTOP)
|
||||
RLAPI bool IsWindowResized(void); // Check if window has been resized last frame
|
||||
RLAPI bool IsWindowState(unsigned int flag); // Check if one specific window flag is enabled
|
||||
RLAPI void SetWindowState(unsigned int flags); // Set window configuration state using flags
|
||||
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 ToggleFullscreen(void); // Toggle window state: fullscreen/windowed (only PLATFORM_DESKTOP)
|
||||
RLAPI void MaximizeWindow(void); // Set window state: maximized, if resizable (only PLATFORM_DESKTOP)
|
||||
|
@ -925,14 +943,17 @@ RLAPI void SetWindowPosition(int x, int y); // Set window
|
|||
RLAPI void SetWindowMonitor(int monitor); // Set monitor for the current window (fullscreen mode)
|
||||
RLAPI void SetWindowMinSize(int width, int height); // Set window minimum dimensions (for FLAG_WINDOW_RESIZABLE)
|
||||
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 *GetWindowHandle(void); // Get native window handle
|
||||
RLAPI int GetScreenWidth(void); // Get current screen width
|
||||
RLAPI int GetScreenHeight(void); // Get current screen height
|
||||
RLAPI int GetRenderWidth(void); // Get current render width (it considers HiDPI)
|
||||
RLAPI int GetRenderHeight(void); // Get current render height (it considers HiDPI)
|
||||
RLAPI int GetMonitorCount(void); // Get number of connected monitors
|
||||
RLAPI int GetCurrentMonitor(void); // Get current connected monitor
|
||||
RLAPI Vector2 GetMonitorPosition(int monitor); // Get specified monitor position
|
||||
RLAPI int GetMonitorWidth(int monitor); // Get specified monitor width (max available by monitor)
|
||||
RLAPI int GetMonitorHeight(int monitor); // Get specified monitor height (max available by monitor)
|
||||
RLAPI int GetMonitorWidth(int monitor); // Get specified monitor width (current video mode used by monitor)
|
||||
RLAPI int GetMonitorHeight(int monitor); // Get specified monitor height (current video mode used by monitor)
|
||||
RLAPI int GetMonitorPhysicalWidth(int monitor); // Get specified monitor physical width in millimetres
|
||||
RLAPI int GetMonitorPhysicalHeight(int monitor); // Get specified monitor physical height in millimetres
|
||||
RLAPI int GetMonitorRefreshRate(int monitor); // Get specified monitor refresh rate
|
||||
|
@ -941,6 +962,8 @@ RLAPI Vector2 GetWindowScaleDPI(void); // Get window
|
|||
RLAPI const char *GetMonitorName(int monitor); // Get the human-readable, UTF-8 encoded name of the primary monitor
|
||||
RLAPI void SetClipboardText(const char *text); // Set 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 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
|
||||
|
@ -948,7 +971,7 @@ RLAPI const char *GetClipboardText(void); // Get clipboa
|
|||
// 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(float ms); // Wait for some milliseconds (halt program execution)
|
||||
RLAPI void WaitTime(double seconds); // Wait for some time (halt program execution)
|
||||
|
||||
// Cursor-related functions
|
||||
RLAPI void ShowCursor(void); // Shows cursor
|
||||
|
@ -998,9 +1021,9 @@ RLAPI Ray GetMouseRay(Vector2 mousePosition, Camera camera); // Get a ray t
|
|||
RLAPI Matrix GetCameraMatrix(Camera camera); // Get camera transform matrix (view matrix)
|
||||
RLAPI Matrix GetCameraMatrix2D(Camera2D camera); // Get camera 2d transform matrix
|
||||
RLAPI Vector2 GetWorldToScreen(Vector3 position, Camera camera); // Get the screen space position for a 3d world space position
|
||||
RLAPI Vector2 GetScreenToWorld2D(Vector2 position, Camera2D camera); // Get the world space position for a 2d camera screen space position
|
||||
RLAPI Vector2 GetWorldToScreenEx(Vector3 position, Camera camera, int width, int height); // Get size position for a 3d world space position
|
||||
RLAPI Vector2 GetWorldToScreen2D(Vector2 position, Camera2D camera); // Get the screen space position for a 2d camera world space position
|
||||
RLAPI Vector2 GetScreenToWorld2D(Vector2 position, Camera2D camera); // Get the world space position for a 2d camera screen space position
|
||||
|
||||
// Timing-related functions
|
||||
RLAPI void SetTargetFPS(int fps); // Set target FPS (maximum)
|
||||
|
@ -1020,6 +1043,8 @@ RLAPI void *MemAlloc(int size); // Internal me
|
|||
RLAPI void *MemRealloc(void *ptr, int size); // Internal memory reallocator
|
||||
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
|
||||
// WARNING: Callbacks setup is intended for advance users
|
||||
RLAPI void SetTraceLogCallback(TraceLogCallback callback); // Set custom trace log
|
||||
|
@ -1029,40 +1054,39 @@ RLAPI void SetLoadFileTextCallback(LoadFileTextCallback callback); // Set custom
|
|||
RLAPI void SetSaveFileTextCallback(SaveFileTextCallback callback); // Set custom file text data saver
|
||||
|
||||
// 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, unsigned int *bytesRead); // Load file data as byte array (read)
|
||||
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, unsigned int bytesToWrite); // Save data to file from byte array (write), returns true on success
|
||||
RLAPI bool ExportDataAsCode(const char *data, unsigned int size, 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 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 FileExists(const char *fileName); // Check if file 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)
|
||||
RLAPI int GetFileLength(const char *fileName); // Get file length in bytes (NOTE: GetFileSize() conflicts with windows.h)
|
||||
RLAPI const char *GetFileExtension(const char *fileName); // Get pointer to extension for a filename string (includes dot: '.png')
|
||||
RLAPI const char *GetFileName(const char *filePath); // Get pointer to filename for a path string
|
||||
RLAPI const char *GetFileNameWithoutExt(const char *filePath); // Get filename string without extension (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 *GetWorkingDirectory(void); // Get current working directory (uses static string)
|
||||
RLAPI char **GetDirectoryFiles(const char *dirPath, int *count); // Get filenames in a directory path (memory should be freed)
|
||||
RLAPI void ClearDirectoryFiles(void); // Clear directory files paths buffers (free memory)
|
||||
RLAPI const char *GetApplicationDirectory(void); // Get the directory if the running application (uses static string)
|
||||
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 FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths
|
||||
RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and recursive directory scan
|
||||
RLAPI void UnloadDirectoryFiles(FilePathList files); // Unload filepaths
|
||||
RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window
|
||||
RLAPI char **GetDroppedFiles(int *count); // Get dropped files names (memory should be freed)
|
||||
RLAPI void ClearDroppedFiles(void); // Clear dropped files paths buffer (free memory)
|
||||
RLAPI FilePathList LoadDroppedFiles(void); // Load dropped filepaths
|
||||
RLAPI void UnloadDroppedFiles(FilePathList files); // Unload dropped filepaths
|
||||
RLAPI long GetFileModTime(const char *fileName); // Get file modification time (last write time)
|
||||
|
||||
// Compression/Encoding functionality
|
||||
RLAPI unsigned char *CompressData(unsigned char *data, int dataLength, int *compDataLength); // Compress data (DEFLATE algorithm)
|
||||
RLAPI unsigned char *DecompressData(unsigned char *compData, int compDataLength, int *dataLength); // Decompress data (DEFLATE algorithm)
|
||||
RLAPI char *EncodeDataBase64(const unsigned char *data, int dataLength, int *outputLength); // Encode data to Base64 string
|
||||
RLAPI unsigned char *DecodeDataBase64(unsigned char *data, int *outputLength); // Decode Base64 string data
|
||||
|
||||
// Persistent storage management
|
||||
RLAPI bool SaveStorageValue(unsigned int position, int value); // Save integer value to storage file (to defined position), returns true on success
|
||||
RLAPI int LoadStorageValue(unsigned int position); // Load integer value from storage file (from defined position)
|
||||
|
||||
RLAPI void OpenURL(const char *url); // Open URL with default system browser (if available)
|
||||
RLAPI unsigned char *CompressData(const unsigned char *data, int dataSize, int *compDataSize); // Compress data (DEFLATE algorithm), memory must be MemFree()
|
||||
RLAPI unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // Decompress data (DEFLATE algorithm), 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()
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Input Handling Functions (Module: core)
|
||||
|
@ -1101,7 +1125,8 @@ RLAPI Vector2 GetMouseDelta(void); // Get mouse delta
|
|||
RLAPI void SetMousePosition(int x, int y); // Set mouse position XY
|
||||
RLAPI void SetMouseOffset(int offsetX, int offsetY); // Set mouse offset
|
||||
RLAPI void SetMouseScale(float scaleX, float scaleY); // Set mouse scaling
|
||||
RLAPI float GetMouseWheelMove(void); // Get mouse wheel movement Y
|
||||
RLAPI float GetMouseWheelMove(void); // Get mouse wheel movement for X or Y, whichever is larger
|
||||
RLAPI Vector2 GetMouseWheelMoveV(void); // Get mouse wheel movement for both X and Y
|
||||
RLAPI void SetMouseCursor(int cursor); // Set mouse cursor
|
||||
|
||||
// Input-related functions: touch
|
||||
|
@ -1290,10 +1315,10 @@ RLAPI void DrawTextureV(Texture2D texture, Vector2 position, Color tint);
|
|||
RLAPI void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint); // Draw a Texture2D with extended parameters
|
||||
RLAPI void DrawTextureRec(Texture2D texture, Rectangle source, Vector2 position, Color tint); // Draw a part of a texture defined by a rectangle
|
||||
RLAPI void DrawTextureQuad(Texture2D texture, Vector2 tiling, Vector2 offset, Rectangle quad, Color tint); // Draw texture quad with tiling and offset parameters
|
||||
RLAPI void DrawTextureTiled(Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, float scale, Color tint); // Draw part of a texture (defined by a rectangle) with rotation and scale tiled into dest.
|
||||
RLAPI void DrawTextureTiled(Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, float scale, Color tint); // Draw part of a texture (defined by a rectangle) with rotation and scale tiled into dest.
|
||||
RLAPI void DrawTexturePro(Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, Color tint); // Draw a part of a texture defined by a rectangle with 'pro' parameters
|
||||
RLAPI void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle dest, Vector2 origin, float rotation, Color tint); // Draws a texture (or part of it) that stretches or shrinks nicely
|
||||
RLAPI void DrawTexturePoly(Texture2D texture, Vector2 center, Vector2 *points, Vector2 *texcoords, int pointCount, Color tint); // Draw a textured polygon
|
||||
RLAPI void DrawTexturePoly(Texture2D texture, Vector2 center, Vector2 *points, Vector2 *texcoords, int pointCount, Color tint); // Draw a textured polygon
|
||||
|
||||
// Color/pixel related functions
|
||||
RLAPI Color Fade(Color color, float alpha); // Get color with alpha applied, alpha goes from 0.0f to 1.0f
|
||||
|
@ -1316,20 +1341,22 @@ RLAPI int GetPixelDataSize(int width, int height, int format); // G
|
|||
// Font loading/unloading functions
|
||||
RLAPI Font GetFontDefault(void); // Get the default Font
|
||||
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
|
||||
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 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 GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int glyphCount, int type); // Load font data for further use
|
||||
RLAPI Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **recs, int 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 UnloadFont(Font font); // Unload Font from GPU memory (VRAM)
|
||||
RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int glyphCount, int type); // Load font data for further use
|
||||
RLAPI Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **recs, int 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 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
|
||||
|
||||
// Text drawing functions
|
||||
RLAPI void DrawFPS(int posX, int posY); // Draw current FPS
|
||||
RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font)
|
||||
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 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)
|
||||
|
||||
// Text font info functions
|
||||
RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font
|
||||
|
@ -1344,7 +1371,7 @@ RLAPI void UnloadCodepoints(int *codepoints); // Unload
|
|||
RLAPI int GetCodepointCount(const char *text); // Get total number of codepoints in a UTF-8 encoded string
|
||||
RLAPI int GetCodepoint(const char *text, int *bytesProcessed); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
|
||||
RLAPI const char *CodepointToUTF8(int codepoint, int *byteSize); // Encode one codepoint into UTF-8 byte array (array length returned as parameter)
|
||||
RLAPI char *TextCodepointsToUTF8(int *codepoints, int length); // Encode text as codepoints array into UTF-8 text string (WARNING: memory must be freed!)
|
||||
RLAPI char *TextCodepointsToUTF8(const int *codepoints, int length); // Encode text as codepoints array into UTF-8 text string (WARNING: memory must be freed!)
|
||||
|
||||
// Text strings management functions (no UTF-8 strings, only byte chars)
|
||||
// NOTE: Some strings allocate memory internally for returned strings, just be careful!
|
||||
|
@ -1373,7 +1400,7 @@ RLAPI void DrawLine3D(Vector3 startPos, Vector3 endPos, Color color);
|
|||
RLAPI void DrawPoint3D(Vector3 position, Color color); // Draw a point in 3D space, actually a small line
|
||||
RLAPI void DrawCircle3D(Vector3 center, float radius, Vector3 rotationAxis, float rotationAngle, Color color); // Draw a circle in 3D world space
|
||||
RLAPI void DrawTriangle3D(Vector3 v1, Vector3 v2, Vector3 v3, Color color); // Draw a color-filled triangle (vertex in counter-clockwise order!)
|
||||
RLAPI void DrawTriangleStrip3D(Vector3 *points, int pointCount, Color color); // Draw a triangle strip defined by points
|
||||
RLAPI void DrawTriangleStrip3D(Vector3 *points, int pointCount, Color color); // Draw a triangle strip defined by points
|
||||
RLAPI void DrawCube(Vector3 position, float width, float height, float length, Color color); // Draw cube
|
||||
RLAPI void DrawCubeV(Vector3 position, Vector3 size, Color color); // Draw cube (Vector version)
|
||||
RLAPI void DrawCubeWires(Vector3 position, float width, float height, float length, Color color); // Draw cube wires
|
||||
|
@ -1414,14 +1441,13 @@ RLAPI void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source,
|
|||
|
||||
// Mesh management functions
|
||||
RLAPI void UploadMesh(Mesh *mesh, bool dynamic); // Upload mesh vertex data in GPU and provide VAO/VBO ids
|
||||
RLAPI void UpdateMeshBuffer(Mesh mesh, int index, void *data, int dataSize, int offset); // Update mesh vertex data in GPU for a specific buffer index
|
||||
RLAPI void UpdateMeshBuffer(Mesh mesh, int index, const void *data, int dataSize, int offset); // Update mesh vertex data in GPU for a specific buffer index
|
||||
RLAPI void UnloadMesh(Mesh mesh); // Unload mesh data from CPU and GPU
|
||||
RLAPI void DrawMesh(Mesh mesh, Material material, Matrix transform); // Draw a 3d mesh with material and transform
|
||||
RLAPI void DrawMeshInstanced(Mesh mesh, Material material, Matrix *transforms, int instances); // Draw multiple mesh instances with material and different transforms
|
||||
RLAPI void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, int instances); // Draw multiple mesh instances with material and different transforms
|
||||
RLAPI bool ExportMesh(Mesh mesh, const char *fileName); // Export mesh data to file, returns true on success
|
||||
RLAPI BoundingBox GetMeshBoundingBox(Mesh mesh); // Compute mesh bounding box limits
|
||||
RLAPI void GenMeshTangents(Mesh *mesh); // Compute mesh tangents
|
||||
RLAPI void GenMeshBinormals(Mesh *mesh); // Compute mesh binormals
|
||||
|
||||
// Mesh generation functions
|
||||
RLAPI Mesh GenMeshPoly(int sides, float radius); // Generate polygonal mesh
|
||||
|
@ -1447,23 +1473,23 @@ RLAPI void SetModelMeshMaterial(Model *model, int meshId, int materialId);
|
|||
RLAPI ModelAnimation *LoadModelAnimations(const char *fileName, unsigned int *animCount); // Load model animations from file
|
||||
RLAPI void UpdateModelAnimation(Model model, ModelAnimation anim, int frame); // Update model animation pose
|
||||
RLAPI void UnloadModelAnimation(ModelAnimation anim); // Unload animation data
|
||||
RLAPI void UnloadModelAnimations(ModelAnimation* animations, unsigned int count); // Unload animation array data
|
||||
RLAPI void UnloadModelAnimations(ModelAnimation *animations, unsigned int count); // Unload animation array data
|
||||
RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match
|
||||
|
||||
// Collision detection functions
|
||||
RLAPI bool CheckCollisionSpheres(Vector3 center1, float radius1, Vector3 center2, float radius2); // Check collision between two spheres
|
||||
RLAPI bool CheckCollisionBoxes(BoundingBox box1, BoundingBox box2); // Check collision between two bounding boxes
|
||||
RLAPI bool CheckCollisionBoxSphere(BoundingBox box, Vector3 center, float radius); // Check collision between box and sphere
|
||||
RLAPI RayCollision GetRayCollisionSphere(Ray ray, Vector3 center, float radius); // Get collision info between ray and sphere
|
||||
RLAPI RayCollision GetRayCollisionBox(Ray ray, BoundingBox box); // Get collision info between ray and box
|
||||
RLAPI RayCollision GetRayCollisionModel(Ray ray, Model model); // Get collision info between ray and model
|
||||
RLAPI RayCollision GetRayCollisionMesh(Ray ray, Mesh mesh, Matrix transform); // Get collision info between ray and mesh
|
||||
RLAPI RayCollision GetRayCollisionTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3); // Get collision info between ray and triangle
|
||||
RLAPI RayCollision GetRayCollisionQuad(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4); // Get collision info between ray and quad
|
||||
RLAPI bool CheckCollisionSpheres(Vector3 center1, float radius1, Vector3 center2, float radius2); // Check collision between two spheres
|
||||
RLAPI bool CheckCollisionBoxes(BoundingBox box1, BoundingBox box2); // Check collision between two bounding boxes
|
||||
RLAPI bool CheckCollisionBoxSphere(BoundingBox box, Vector3 center, float radius); // Check collision between box and sphere
|
||||
RLAPI RayCollision GetRayCollisionSphere(Ray ray, Vector3 center, float radius); // Get collision info between ray and sphere
|
||||
RLAPI RayCollision GetRayCollisionBox(Ray ray, BoundingBox box); // Get collision info between ray and box
|
||||
RLAPI RayCollision GetRayCollisionMesh(Ray ray, Mesh mesh, Matrix transform); // Get collision info between ray and mesh
|
||||
RLAPI RayCollision GetRayCollisionTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3); // Get collision info between ray and triangle
|
||||
RLAPI RayCollision GetRayCollisionQuad(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4); // Get collision info between ray and quad
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Audio Loading and Playing Functions (Module: audio)
|
||||
//------------------------------------------------------------------------------------
|
||||
typedef void (*AudioCallback)(void *bufferData, unsigned int frames);
|
||||
|
||||
// Audio device management functions
|
||||
RLAPI void InitAudioDevice(void); // Initialize audio device and context
|
||||
|
@ -1493,15 +1519,16 @@ RLAPI int GetSoundsPlaying(void); // Get num
|
|||
RLAPI bool IsSoundPlaying(Sound sound); // Check if a sound is currently playing
|
||||
RLAPI void SetSoundVolume(Sound sound, float volume); // Set volume for a sound (1.0 is max level)
|
||||
RLAPI void SetSoundPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level)
|
||||
RLAPI void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels); // Convert wave data to desired format
|
||||
RLAPI void SetSoundPan(Sound sound, float pan); // Set pan for a sound (0.5 is center)
|
||||
RLAPI Wave WaveCopy(Wave wave); // Copy a wave to a new wave
|
||||
RLAPI void WaveCrop(Wave *wave, int initSample, int finalSample); // Crop a wave to defined samples range
|
||||
RLAPI float *LoadWaveSamples(Wave wave); // Load samples data from wave as a floats array
|
||||
RLAPI void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels); // Convert wave data to desired format
|
||||
RLAPI float *LoadWaveSamples(Wave wave); // Load samples data from wave as a 32bit float data array
|
||||
RLAPI void UnloadWaveSamples(float *samples); // Unload samples data loaded with LoadWaveSamples()
|
||||
|
||||
// Music management functions
|
||||
RLAPI Music LoadMusicStream(const char *fileName); // Load music stream from file
|
||||
RLAPI Music LoadMusicStreamFromMemory(const char *fileType, unsigned char *data, int dataSize); // Load music stream from data
|
||||
RLAPI Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data, int dataSize); // Load music stream from data
|
||||
RLAPI void UnloadMusicStream(Music music); // Unload music stream
|
||||
RLAPI void PlayMusicStream(Music music); // Start music playing
|
||||
RLAPI bool IsMusicStreamPlaying(Music music); // Check if music is playing
|
||||
|
@ -1512,12 +1539,13 @@ RLAPI void ResumeMusicStream(Music music); // Resume
|
|||
RLAPI void SeekMusicStream(Music music, float position); // Seek music to a position (in seconds)
|
||||
RLAPI void SetMusicVolume(Music music, float volume); // Set volume for music (1.0 is max level)
|
||||
RLAPI void SetMusicPitch(Music music, float pitch); // Set pitch for a music (1.0 is base level)
|
||||
RLAPI void SetMusicPan(Music music, float pan); // Set pan for a music (0.5 is center)
|
||||
RLAPI float GetMusicTimeLength(Music music); // Get music time length (in seconds)
|
||||
RLAPI float GetMusicTimePlayed(Music music); // Get current music time played (in seconds)
|
||||
|
||||
// AudioStream management functions
|
||||
RLAPI AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, unsigned int channels); // Load audio stream (to stream raw audio pcm data)
|
||||
RLAPI void UnloadAudioStream(AudioStream stream); // Unload audio stream and free memory
|
||||
RLAPI void UnloadAudioStream(AudioStream stream); // Unload audio stream and free memory
|
||||
RLAPI void UpdateAudioStream(AudioStream stream, const void *data, int frameCount); // Update audio stream buffers with data
|
||||
RLAPI bool IsAudioStreamProcessed(AudioStream stream); // Check if any audio stream buffers requires refill
|
||||
RLAPI void PlayAudioStream(AudioStream stream); // Play audio stream
|
||||
|
@ -1527,7 +1555,12 @@ RLAPI bool IsAudioStreamPlaying(AudioStream stream); // Check i
|
|||
RLAPI void StopAudioStream(AudioStream stream); // Stop audio stream
|
||||
RLAPI void SetAudioStreamVolume(AudioStream stream, float volume); // Set volume for audio stream (1.0 is max level)
|
||||
RLAPI void SetAudioStreamPitch(AudioStream stream, float pitch); // Set pitch for audio stream (1.0 is base level)
|
||||
RLAPI void SetAudioStreamPan(AudioStream stream, float pan); // Set pan for audio stream (0.5 is centered)
|
||||
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 AttachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Attach audio stream processor to stream
|
||||
RLAPI void DetachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Detach audio stream processor from stream
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
|
|
532
raylib/raymath.h
532
raylib/raymath.h
|
@ -18,14 +18,14 @@
|
|||
* - 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" anmed variable for return
|
||||
* - 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
|
||||
*
|
||||
* Copyright (c) 2015-2021 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2015-2022 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.
|
||||
|
@ -77,6 +77,10 @@
|
|||
#define PI 3.14159265358979323846f
|
||||
#endif
|
||||
|
||||
#ifndef EPSILON
|
||||
#define EPSILON 0.000001f
|
||||
#endif
|
||||
|
||||
#ifndef DEG2RAD
|
||||
#define DEG2RAD (PI/180.0f)
|
||||
#endif
|
||||
|
@ -154,7 +158,7 @@ typedef struct float16 {
|
|||
float v[16];
|
||||
} float16;
|
||||
|
||||
#include <math.h> // Required for: sinf(), cosf(), tan(), atan2f(), sqrtf(), fminf(), fmaxf(), fabs()
|
||||
#include <math.h> // Required for: sinf(), cosf(), tan(), atan2f(), sqrtf(), floor(), fminf(), fmaxf(), fabs()
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition - Utils math
|
||||
|
@ -189,7 +193,23 @@ RMAPI float Normalize(float value, float start, float end)
|
|||
// Remap input value within input range to output range
|
||||
RMAPI float Remap(float value, float inputStart, float inputEnd, float outputStart, float outputEnd)
|
||||
{
|
||||
float result =(value - inputStart)/(inputEnd - inputStart)*(outputEnd - outputStart) + outputStart;
|
||||
float result = (value - inputStart)/(inputEnd - inputStart)*(outputEnd - outputStart) + outputStart;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Wrap input value from min to max
|
||||
RMAPI float Wrap(float value, float min, float max)
|
||||
{
|
||||
float result = value - (max - min)*floorf((value - min)/(max - min));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Check whether two given floats are almost equal
|
||||
RMAPI int FloatEquals(float x, float y)
|
||||
{
|
||||
int result = (fabsf(x - y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(x), fabsf(y))));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -278,12 +298,18 @@ RMAPI float Vector2Distance(Vector2 v1, Vector2 v2)
|
|||
return result;
|
||||
}
|
||||
|
||||
// Calculate angle from two vectors in X-axis
|
||||
// Calculate square distance between two vectors
|
||||
RMAPI float Vector2DistanceSqr(Vector2 v1, Vector2 v2)
|
||||
{
|
||||
float result = ((v1.x - v2.x)*(v1.x - v2.x) + (v1.y - v2.y)*(v1.y - v2.y));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Calculate angle from two vectors
|
||||
RMAPI float Vector2Angle(Vector2 v1, Vector2 v2)
|
||||
{
|
||||
float result = atan2f(v2.y - v1.y, v2.x - v1.x)*(180.0f/PI);
|
||||
|
||||
if (result < 0) result += 360.0f;
|
||||
float result = atan2f(v2.y, v2.x) - atan2f(v1.y, v1.x);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -328,13 +354,29 @@ RMAPI Vector2 Vector2Normalize(Vector2 v)
|
|||
|
||||
if (length > 0)
|
||||
{
|
||||
result.x = v.x*1.0f/length;
|
||||
result.y = v.y*1.0f/length;
|
||||
float ilength = 1.0f/length;
|
||||
result.x = v.x*ilength;
|
||||
result.y = v.y*ilength;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Transforms a Vector2 by a given Matrix
|
||||
RMAPI Vector2 Vector2Transform(Vector2 v, Matrix mat)
|
||||
{
|
||||
Vector2 result = { 0 };
|
||||
|
||||
float x = v.x;
|
||||
float y = v.y;
|
||||
float z = 0;
|
||||
|
||||
result.x = mat.m0*x + mat.m4*y + mat.m8*z + mat.m12;
|
||||
result.y = mat.m1*x + mat.m5*y + mat.m9*z + mat.m13;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Calculate linear interpolation between two vectors
|
||||
RMAPI Vector2 Vector2Lerp(Vector2 v1, Vector2 v2, float amount)
|
||||
{
|
||||
|
@ -364,8 +406,11 @@ RMAPI Vector2 Vector2Rotate(Vector2 v, float angle)
|
|||
{
|
||||
Vector2 result = { 0 };
|
||||
|
||||
result.x = v.x*cosf(angle) - v.y*sinf(angle);
|
||||
result.y = v.x*sinf(angle) + v.y*cosf(angle);
|
||||
float cosres = cosf(angle);
|
||||
float sinres = sinf(angle);
|
||||
|
||||
result.x = v.x*cosres - v.y*sinres;
|
||||
result.y = v.x*sinres + v.y*cosres;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -389,6 +434,62 @@ RMAPI Vector2 Vector2MoveTowards(Vector2 v, Vector2 target, float maxDistance)
|
|||
return result;
|
||||
}
|
||||
|
||||
// Invert the given vector
|
||||
RMAPI Vector2 Vector2Invert(Vector2 v)
|
||||
{
|
||||
Vector2 result = { 1.0f/v.x, 1.0f/v.y };
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Clamp the components of the vector between
|
||||
// min and max values specified by the given vectors
|
||||
RMAPI Vector2 Vector2Clamp(Vector2 v, Vector2 min, Vector2 max)
|
||||
{
|
||||
Vector2 result = { 0 };
|
||||
|
||||
result.x = fminf(max.x, fmaxf(min.x, v.x));
|
||||
result.y = fminf(max.y, fmaxf(min.y, v.y));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Clamp the magnitude of the vector between two min and max values
|
||||
RMAPI Vector2 Vector2ClampValue(Vector2 v, float min, float max)
|
||||
{
|
||||
Vector2 result = v;
|
||||
|
||||
float length = (v.x*v.x) + (v.y*v.y);
|
||||
if (length > 0.0f)
|
||||
{
|
||||
length = sqrtf(length);
|
||||
|
||||
if (length < min)
|
||||
{
|
||||
float scale = min/length;
|
||||
result.x = v.x*scale;
|
||||
result.y = v.y*scale;
|
||||
}
|
||||
else if (length > max)
|
||||
{
|
||||
float scale = max/length;
|
||||
result.x = v.x*scale;
|
||||
result.y = v.y*scale;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Check whether two given vectors are almost equal
|
||||
RMAPI int Vector2Equals(Vector2 p, Vector2 q)
|
||||
{
|
||||
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)))));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition - Vector3 math
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -473,14 +574,14 @@ RMAPI Vector3 Vector3Perpendicular(Vector3 v)
|
|||
float min = (float) fabs(v.x);
|
||||
Vector3 cardinalAxis = {1.0f, 0.0f, 0.0f};
|
||||
|
||||
if (fabs(v.y) < min)
|
||||
if (fabsf(v.y) < min)
|
||||
{
|
||||
min = (float) fabs(v.y);
|
||||
Vector3 tmp = {0.0f, 1.0f, 0.0f};
|
||||
cardinalAxis = tmp;
|
||||
}
|
||||
|
||||
if (fabs(v.z) < min)
|
||||
if (fabsf(v.z) < min)
|
||||
{
|
||||
Vector3 tmp = {0.0f, 0.0f, 1.0f};
|
||||
cardinalAxis = tmp;
|
||||
|
@ -531,17 +632,28 @@ RMAPI float Vector3Distance(Vector3 v1, Vector3 v2)
|
|||
return result;
|
||||
}
|
||||
|
||||
// Calculate angle between two vectors in XY and XZ
|
||||
RMAPI Vector2 Vector3Angle(Vector3 v1, Vector3 v2)
|
||||
// Calculate square distance between two vectors
|
||||
RMAPI float Vector3DistanceSqr(Vector3 v1, Vector3 v2)
|
||||
{
|
||||
Vector2 result = { 0 };
|
||||
float result = 0.0f;
|
||||
|
||||
float dx = v2.x - v1.x;
|
||||
float dy = v2.y - v1.y;
|
||||
float dz = v2.z - v1.z;
|
||||
result = dx*dx + dy*dy + dz*dz;
|
||||
|
||||
result.x = atan2f(dx, dz); // Angle in XZ
|
||||
result.y = atan2f(dy, sqrtf(dx*dx + dz*dz)); // Angle in XY
|
||||
return result;
|
||||
}
|
||||
|
||||
// Calculate angle between two vectors
|
||||
RMAPI float Vector3Angle(Vector3 v1, Vector3 v2)
|
||||
{
|
||||
float result = 0.0f;
|
||||
|
||||
Vector3 cross = { v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x };
|
||||
float len = sqrtf(cross.x*cross.x + cross.y*cross.y + cross.z*cross.z);
|
||||
float dot = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z);
|
||||
result = atan2f(len, dot);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -641,6 +753,58 @@ RMAPI Vector3 Vector3RotateByQuaternion(Vector3 v, Quaternion q)
|
|||
return result;
|
||||
}
|
||||
|
||||
// Rotates a vector around an axis
|
||||
RMAPI Vector3 Vector3RotateByAxisAngle(Vector3 v, Vector3 axis, float angle)
|
||||
{
|
||||
// Using Euler-Rodrigues Formula
|
||||
// Ref.: https://en.wikipedia.org/w/index.php?title=Euler%E2%80%93Rodrigues_formula
|
||||
|
||||
Vector3 result = v;
|
||||
|
||||
// Vector3Normalize(axis);
|
||||
float length = sqrtf(axis.x * axis.x + axis.y * axis.y + axis.z * axis.z);
|
||||
if (length == 0.0f) length = 1.0f;
|
||||
float ilength = 1.0f / length;
|
||||
axis.x *= ilength;
|
||||
axis.y *= ilength;
|
||||
axis.z *= ilength;
|
||||
|
||||
angle /= 2.0f;
|
||||
float a = sinf(angle);
|
||||
float b = axis.x * a;
|
||||
float c = axis.y * a;
|
||||
float d = axis.z * a;
|
||||
a = cosf(angle);
|
||||
Vector3 w = { b, c, d };
|
||||
|
||||
// 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 };
|
||||
|
||||
// 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 };
|
||||
|
||||
// Vector3Scale(wv, 2 * a)
|
||||
a *= 2;
|
||||
wv.x *= a;
|
||||
wv.y *= a;
|
||||
wv.z *= a;
|
||||
|
||||
// Vector3Scale(wwv, 2)
|
||||
wwv.x *= 2;
|
||||
wwv.y *= 2;
|
||||
wwv.z *= 2;
|
||||
|
||||
result.x += wv.x;
|
||||
result.y += wv.y;
|
||||
result.z += wv.z;
|
||||
|
||||
result.x += wwv.x;
|
||||
result.y += wwv.y;
|
||||
result.z += wwv.z;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Calculate linear interpolation between two vectors
|
||||
RMAPI Vector3 Vector3Lerp(Vector3 v1, Vector3 v2, float amount)
|
||||
{
|
||||
|
@ -815,6 +979,92 @@ RMAPI float3 Vector3ToFloatV(Vector3 v)
|
|||
return buffer;
|
||||
}
|
||||
|
||||
// Invert the given vector
|
||||
RMAPI Vector3 Vector3Invert(Vector3 v)
|
||||
{
|
||||
Vector3 result = { 1.0f/v.x, 1.0f/v.y, 1.0f/v.z };
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Clamp the components of the vector between
|
||||
// min and max values specified by the given vectors
|
||||
RMAPI Vector3 Vector3Clamp(Vector3 v, Vector3 min, Vector3 max)
|
||||
{
|
||||
Vector3 result = { 0 };
|
||||
|
||||
result.x = fminf(max.x, fmaxf(min.x, v.x));
|
||||
result.y = fminf(max.y, fmaxf(min.y, v.y));
|
||||
result.z = fminf(max.z, fmaxf(min.z, v.z));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Clamp the magnitude of the vector between two values
|
||||
RMAPI Vector3 Vector3ClampValue(Vector3 v, float min, float max)
|
||||
{
|
||||
Vector3 result = v;
|
||||
|
||||
float length = (v.x*v.x) + (v.y*v.y) + (v.z*v.z);
|
||||
if (length > 0.0f)
|
||||
{
|
||||
length = sqrtf(length);
|
||||
|
||||
if (length < min)
|
||||
{
|
||||
float scale = min/length;
|
||||
result.x = v.x*scale;
|
||||
result.y = v.y*scale;
|
||||
result.z = v.z*scale;
|
||||
}
|
||||
else if (length > max)
|
||||
{
|
||||
float scale = max/length;
|
||||
result.x = v.x*scale;
|
||||
result.y = v.y*scale;
|
||||
result.z = v.z*scale;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Check whether two given vectors are almost equal
|
||||
RMAPI int Vector3Equals(Vector3 p, Vector3 q)
|
||||
{
|
||||
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.z - q.z)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z)))));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Compute the direction of a refracted ray where v specifies the
|
||||
// normalized direction of the incoming ray, n specifies the
|
||||
// normalized normal vector of the interface of two optical media,
|
||||
// and r specifies the ratio of the refractive index of the medium
|
||||
// from where the ray comes to the refractive index of the medium
|
||||
// on the other side of the surface
|
||||
RMAPI Vector3 Vector3Refract(Vector3 v, Vector3 n, float r)
|
||||
{
|
||||
Vector3 result = { 0 };
|
||||
|
||||
float dot = v.x*n.x + v.y*n.y + v.z*n.z;
|
||||
float d = 1.0f - r*r*(1.0f - dot*dot);
|
||||
|
||||
if (d >= 0.0f)
|
||||
{
|
||||
d = sqrtf(d);
|
||||
v.x = r*v.x - (r*dot + d)*n.x;
|
||||
v.y = r*v.y - (r*dot + d)*n.y;
|
||||
v.z = r*v.z - (r*dot + d)*n.z;
|
||||
|
||||
result = v;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition - Matrix math
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -920,45 +1170,6 @@ RMAPI Matrix MatrixInvert(Matrix mat)
|
|||
return result;
|
||||
}
|
||||
|
||||
// Normalize provided matrix
|
||||
RMAPI Matrix MatrixNormalize(Matrix mat)
|
||||
{
|
||||
Matrix result = { 0 };
|
||||
|
||||
// Cache the matrix values (speed optimization)
|
||||
float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3;
|
||||
float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7;
|
||||
float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11;
|
||||
float a30 = mat.m12, a31 = mat.m13, a32 = mat.m14, a33 = mat.m15;
|
||||
|
||||
// MatrixDeterminant(mat)
|
||||
float det = a30*a21*a12*a03 - a20*a31*a12*a03 - a30*a11*a22*a03 + a10*a31*a22*a03 +
|
||||
a20*a11*a32*a03 - a10*a21*a32*a03 - a30*a21*a02*a13 + a20*a31*a02*a13 +
|
||||
a30*a01*a22*a13 - a00*a31*a22*a13 - a20*a01*a32*a13 + a00*a21*a32*a13 +
|
||||
a30*a11*a02*a23 - a10*a31*a02*a23 - a30*a01*a12*a23 + a00*a31*a12*a23 +
|
||||
a10*a01*a32*a23 - a00*a11*a32*a23 - a20*a11*a02*a33 + a10*a21*a02*a33 +
|
||||
a20*a01*a12*a33 - a00*a21*a12*a33 - a10*a01*a22*a33 + a00*a11*a22*a33;
|
||||
|
||||
result.m0 = mat.m0/det;
|
||||
result.m1 = mat.m1/det;
|
||||
result.m2 = mat.m2/det;
|
||||
result.m3 = mat.m3/det;
|
||||
result.m4 = mat.m4/det;
|
||||
result.m5 = mat.m5/det;
|
||||
result.m6 = mat.m6/det;
|
||||
result.m7 = mat.m7/det;
|
||||
result.m8 = mat.m8/det;
|
||||
result.m9 = mat.m9/det;
|
||||
result.m10 = mat.m10/det;
|
||||
result.m11 = mat.m11/det;
|
||||
result.m12 = mat.m12/det;
|
||||
result.m13 = mat.m13/det;
|
||||
result.m14 = mat.m14/det;
|
||||
result.m15 = mat.m15/det;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Get identity matrix
|
||||
RMAPI Matrix MatrixIdentity(void)
|
||||
{
|
||||
|
@ -1102,7 +1313,8 @@ RMAPI Matrix MatrixRotate(Vector3 axis, float angle)
|
|||
return result;
|
||||
}
|
||||
|
||||
// Get x-rotation matrix (angle in radians)
|
||||
// Get x-rotation matrix
|
||||
// NOTE: Angle must be provided in radians
|
||||
RMAPI Matrix MatrixRotateX(float angle)
|
||||
{
|
||||
Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f,
|
||||
|
@ -1114,14 +1326,15 @@ RMAPI Matrix MatrixRotateX(float angle)
|
|||
float sinres = sinf(angle);
|
||||
|
||||
result.m5 = cosres;
|
||||
result.m6 = -sinres;
|
||||
result.m9 = sinres;
|
||||
result.m6 = sinres;
|
||||
result.m9 = -sinres;
|
||||
result.m10 = cosres;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Get y-rotation matrix (angle in radians)
|
||||
// Get y-rotation matrix
|
||||
// NOTE: Angle must be provided in radians
|
||||
RMAPI Matrix MatrixRotateY(float angle)
|
||||
{
|
||||
Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f,
|
||||
|
@ -1133,14 +1346,15 @@ RMAPI Matrix MatrixRotateY(float angle)
|
|||
float sinres = sinf(angle);
|
||||
|
||||
result.m0 = cosres;
|
||||
result.m2 = sinres;
|
||||
result.m8 = -sinres;
|
||||
result.m2 = -sinres;
|
||||
result.m8 = sinres;
|
||||
result.m10 = cosres;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Get z-rotation matrix (angle in radians)
|
||||
// Get z-rotation matrix
|
||||
// NOTE: Angle must be provided in radians
|
||||
RMAPI Matrix MatrixRotateZ(float angle)
|
||||
{
|
||||
Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f,
|
||||
|
@ -1152,74 +1366,76 @@ RMAPI Matrix MatrixRotateZ(float angle)
|
|||
float sinres = sinf(angle);
|
||||
|
||||
result.m0 = cosres;
|
||||
result.m1 = -sinres;
|
||||
result.m4 = sinres;
|
||||
result.m1 = sinres;
|
||||
result.m4 = -sinres;
|
||||
result.m5 = cosres;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// Get xyz-rotation matrix (angles in radians)
|
||||
RMAPI Matrix MatrixRotateXYZ(Vector3 ang)
|
||||
// Get xyz-rotation matrix
|
||||
// NOTE: Angle must be provided in radians
|
||||
RMAPI Matrix MatrixRotateXYZ(Vector3 angle)
|
||||
{
|
||||
Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f }; // MatrixIdentity()
|
||||
|
||||
float cosz = cosf(-ang.z);
|
||||
float sinz = sinf(-ang.z);
|
||||
float cosy = cosf(-ang.y);
|
||||
float siny = sinf(-ang.y);
|
||||
float cosx = cosf(-ang.x);
|
||||
float sinx = sinf(-ang.x);
|
||||
float cosz = cosf(-angle.z);
|
||||
float sinz = sinf(-angle.z);
|
||||
float cosy = cosf(-angle.y);
|
||||
float siny = sinf(-angle.y);
|
||||
float cosx = cosf(-angle.x);
|
||||
float sinx = sinf(-angle.x);
|
||||
|
||||
result.m0 = cosz*cosy;
|
||||
result.m4 = (cosz*siny*sinx) - (sinz*cosx);
|
||||
result.m8 = (cosz*siny*cosx) + (sinz*sinx);
|
||||
result.m1 = (cosz*siny*sinx) - (sinz*cosx);
|
||||
result.m2 = (cosz*siny*cosx) + (sinz*sinx);
|
||||
|
||||
result.m1 = sinz*cosy;
|
||||
result.m4 = sinz*cosy;
|
||||
result.m5 = (sinz*siny*sinx) + (cosz*cosx);
|
||||
result.m9 = (sinz*siny*cosx) - (cosz*sinx);
|
||||
result.m6 = (sinz*siny*cosx) - (cosz*sinx);
|
||||
|
||||
result.m2 = -siny;
|
||||
result.m6 = cosy*sinx;
|
||||
result.m8 = -siny;
|
||||
result.m9 = cosy*sinx;
|
||||
result.m10= cosy*cosx;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Get zyx-rotation matrix (angles in radians)
|
||||
RMAPI Matrix MatrixRotateZYX(Vector3 ang)
|
||||
// Get zyx-rotation matrix
|
||||
// NOTE: Angle must be provided in radians
|
||||
RMAPI Matrix MatrixRotateZYX(Vector3 angle)
|
||||
{
|
||||
Matrix result = { 0 };
|
||||
|
||||
float cz = cosf(ang.z);
|
||||
float sz = sinf(ang.z);
|
||||
float cy = cosf(ang.y);
|
||||
float sy = sinf(ang.y);
|
||||
float cx = cosf(ang.x);
|
||||
float sx = sinf(ang.x);
|
||||
float cz = cosf(angle.z);
|
||||
float sz = sinf(angle.z);
|
||||
float cy = cosf(angle.y);
|
||||
float sy = sinf(angle.y);
|
||||
float cx = cosf(angle.x);
|
||||
float sx = sinf(angle.x);
|
||||
|
||||
result.m0 = cz*cy;
|
||||
result.m1 = cz*sy*sx - cx*sz;
|
||||
result.m2 = sz*sx + cz*cx*sy;
|
||||
result.m3 = 0;
|
||||
|
||||
result.m4 = cy*sz;
|
||||
result.m5 = cz*cx + sz*sy*sx;
|
||||
result.m6 = cx*sz*sy - cz*sx;
|
||||
result.m7 = 0;
|
||||
|
||||
result.m8 = -sy;
|
||||
result.m9 = cy*sx;
|
||||
result.m10 = cy*cx;
|
||||
result.m11 = 0;
|
||||
|
||||
result.m4 = cz*sy*sx - cx*sz;
|
||||
result.m8 = sz*sx + cz*cx*sy;
|
||||
result.m12 = 0;
|
||||
|
||||
result.m1 = cy*sz;
|
||||
result.m5 = cz*cx + sz*sy*sx;
|
||||
result.m9 = cx*sz*sy - cz*sx;
|
||||
result.m13 = 0;
|
||||
|
||||
result.m2 = -sy;
|
||||
result.m6 = cy*sx;
|
||||
result.m10 = cy*cx;
|
||||
result.m14 = 0;
|
||||
|
||||
result.m3 = 0;
|
||||
result.m7 = 0;
|
||||
result.m11 = 0;
|
||||
result.m15 = 1;
|
||||
|
||||
return result;
|
||||
|
@ -1269,7 +1485,7 @@ RMAPI Matrix MatrixFrustum(double left, double right, double bottom, double top,
|
|||
}
|
||||
|
||||
// Get perspective projection matrix
|
||||
// NOTE: Angle should be provided in radians
|
||||
// NOTE: Fovy angle must be provided in radians
|
||||
RMAPI Matrix MatrixPerspective(double fovy, double aspect, double near, double far)
|
||||
{
|
||||
Matrix result = { 0 };
|
||||
|
@ -1478,10 +1694,9 @@ RMAPI Quaternion QuaternionInvert(Quaternion q)
|
|||
{
|
||||
Quaternion result = q;
|
||||
|
||||
float length = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w);
|
||||
float lengthSq = length*length;
|
||||
float lengthSq = q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w;
|
||||
|
||||
if (lengthSq != 0.0)
|
||||
if (lengthSq != 0.0f)
|
||||
{
|
||||
float invLength = 1.0f/lengthSq;
|
||||
|
||||
|
@ -1515,12 +1730,10 @@ RMAPI Quaternion QuaternionScale(Quaternion q, float mul)
|
|||
{
|
||||
Quaternion result = { 0 };
|
||||
|
||||
float qax = q.x, qay = q.y, qaz = q.z, qaw = q.w;
|
||||
|
||||
result.x = qax*mul + qaw*mul + qay*mul - qaz*mul;
|
||||
result.y = qay*mul + qaw*mul + qaz*mul - qax*mul;
|
||||
result.z = qaz*mul + qaw*mul + qax*mul - qay*mul;
|
||||
result.w = qaw*mul - qax*mul - qay*mul - qaz*mul;
|
||||
result.x = q.x*mul;
|
||||
result.y = q.y*mul;
|
||||
result.z = q.z*mul;
|
||||
result.w = q.w*mul;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -1584,14 +1797,14 @@ RMAPI Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount)
|
|||
cosHalfTheta = -cosHalfTheta;
|
||||
}
|
||||
|
||||
if (fabs(cosHalfTheta) >= 1.0f) result = q1;
|
||||
if (fabsf(cosHalfTheta) >= 1.0f) result = q1;
|
||||
else if (cosHalfTheta > 0.95f) result = QuaternionNlerp(q1, q2, amount);
|
||||
else
|
||||
{
|
||||
float halfTheta = acosf(cosHalfTheta);
|
||||
float sinHalfTheta = sqrtf(1.0f - cosHalfTheta*cosHalfTheta);
|
||||
|
||||
if (fabs(sinHalfTheta) < 0.001f)
|
||||
if (fabsf(sinHalfTheta) < 0.001f)
|
||||
{
|
||||
result.x = (q1.x*0.5f + q2.x*0.5f);
|
||||
result.y = (q1.y*0.5f + q2.y*0.5f);
|
||||
|
@ -1646,30 +1859,60 @@ RMAPI Quaternion QuaternionFromMatrix(Matrix mat)
|
|||
{
|
||||
Quaternion result = { 0 };
|
||||
|
||||
if ((mat.m0 > mat.m5) && (mat.m0 > mat.m10))
|
||||
{
|
||||
float s = sqrtf(1.0f + mat.m0 - mat.m5 - mat.m10)*2;
|
||||
float fourWSquaredMinus1 = mat.m0 + mat.m5 + mat.m10;
|
||||
float fourXSquaredMinus1 = mat.m0 - mat.m5 - mat.m10;
|
||||
float fourYSquaredMinus1 = mat.m5 - mat.m0 - mat.m10;
|
||||
float fourZSquaredMinus1 = mat.m10 - mat.m0 - mat.m5;
|
||||
|
||||
result.x = 0.25f*s;
|
||||
result.y = (mat.m4 + mat.m1)/s;
|
||||
result.z = (mat.m2 + mat.m8)/s;
|
||||
result.w = (mat.m9 - mat.m6)/s;
|
||||
}
|
||||
else if (mat.m5 > mat.m10)
|
||||
int biggestIndex = 0;
|
||||
float fourBiggestSquaredMinus1 = fourWSquaredMinus1;
|
||||
if (fourXSquaredMinus1 > fourBiggestSquaredMinus1)
|
||||
{
|
||||
float s = sqrtf(1.0f + mat.m5 - mat.m0 - mat.m10)*2;
|
||||
result.x = (mat.m4 + mat.m1)/s;
|
||||
result.y = 0.25f*s;
|
||||
result.z = (mat.m9 + mat.m6)/s;
|
||||
result.w = (mat.m2 - mat.m8)/s;
|
||||
fourBiggestSquaredMinus1 = fourXSquaredMinus1;
|
||||
biggestIndex = 1;
|
||||
}
|
||||
else
|
||||
|
||||
if (fourYSquaredMinus1 > fourBiggestSquaredMinus1)
|
||||
{
|
||||
float s = sqrtf(1.0f + mat.m10 - mat.m0 - mat.m5)*2;
|
||||
result.x = (mat.m2 + mat.m8)/s;
|
||||
result.y = (mat.m9 + mat.m6)/s;
|
||||
result.z = 0.25f*s;
|
||||
result.w = (mat.m4 - mat.m1)/s;
|
||||
fourBiggestSquaredMinus1 = fourYSquaredMinus1;
|
||||
biggestIndex = 2;
|
||||
}
|
||||
|
||||
if (fourZSquaredMinus1 > fourBiggestSquaredMinus1)
|
||||
{
|
||||
fourBiggestSquaredMinus1 = fourZSquaredMinus1;
|
||||
biggestIndex = 3;
|
||||
}
|
||||
|
||||
float biggestVal = sqrtf(fourBiggestSquaredMinus1 + 1.0f) * 0.5f;
|
||||
float mult = 0.25f / biggestVal;
|
||||
|
||||
switch (biggestIndex)
|
||||
{
|
||||
case 0:
|
||||
result.w = biggestVal;
|
||||
result.x = (mat.m6 - mat.m9) * mult;
|
||||
result.y = (mat.m8 - mat.m2) * mult;
|
||||
result.z = (mat.m1 - mat.m4) * mult;
|
||||
break;
|
||||
case 1:
|
||||
result.x = biggestVal;
|
||||
result.w = (mat.m6 - mat.m9) * mult;
|
||||
result.y = (mat.m1 + mat.m4) * mult;
|
||||
result.z = (mat.m8 + mat.m2) * mult;
|
||||
break;
|
||||
case 2:
|
||||
result.y = biggestVal;
|
||||
result.w = (mat.m8 - mat.m2) * mult;
|
||||
result.x = (mat.m1 + mat.m4) * mult;
|
||||
result.z = (mat.m6 + mat.m9) * mult;
|
||||
break;
|
||||
case 3:
|
||||
result.z = biggestVal;
|
||||
result.w = (mat.m1 - mat.m4) * mult;
|
||||
result.x = (mat.m8 + mat.m2) * mult;
|
||||
result.y = (mat.m6 + mat.m9) * mult;
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -1709,7 +1952,7 @@ RMAPI Matrix QuaternionToMatrix(Quaternion q)
|
|||
}
|
||||
|
||||
// Get rotation quaternion for an angle and axis
|
||||
// NOTE: angle must be provided in radians
|
||||
// NOTE: Angle must be provided in radians
|
||||
RMAPI Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle)
|
||||
{
|
||||
Quaternion result = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
|
@ -1757,7 +2000,7 @@ RMAPI Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle)
|
|||
// Get the rotation angle and axis for a given quaternion
|
||||
RMAPI void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle)
|
||||
{
|
||||
if (fabs(q.w) > 1.0f)
|
||||
if (fabsf(q.w) > 1.0f)
|
||||
{
|
||||
// QuaternionNormalize(q);
|
||||
float length = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w);
|
||||
|
@ -1850,4 +2093,19 @@ RMAPI Quaternion QuaternionTransform(Quaternion q, Matrix mat)
|
|||
return result;
|
||||
}
|
||||
|
||||
// Check whether two given quaternions are almost equal
|
||||
RMAPI int QuaternionEquals(Quaternion p, Quaternion q)
|
||||
{
|
||||
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.z - q.z)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z))))) &&
|
||||
((fabsf(p.w - q.w)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.w), fabsf(q.w)))))) ||
|
||||
(((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.z + q.z)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z))))) &&
|
||||
((fabsf(p.w + q.w)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.w), fabsf(q.w))))));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // RAYMATH_H
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2015-2021 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2015-2022 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.
|
||||
|
@ -103,7 +103,7 @@
|
|||
// Module Functions Declaration
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if defined(__cplusplus)
|
||||
extern "C" { // Prevents name mangling of functions
|
||||
#endif
|
||||
|
||||
|
@ -119,7 +119,7 @@ void SetCameraMoveControls(int keyFront, int keyBack,
|
|||
int keyUp, int keyDown); // Set camera move controls (1st person and 3rd person cameras)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -150,7 +150,7 @@ void SetCameraMoveControls(int keyFront, int keyBack,
|
|||
#endif
|
||||
|
||||
// Camera mouse movement sensitivity
|
||||
#define CAMERA_MOUSE_MOVE_SENSITIVITY 0.003f
|
||||
#define CAMERA_MOUSE_MOVE_SENSITIVITY 0.5f // TODO: it should be independant of framerate
|
||||
#define CAMERA_MOUSE_SCROLL_SENSITIVITY 1.5f
|
||||
|
||||
// FREE_CAMERA
|
||||
|
@ -163,7 +163,7 @@ void SetCameraMoveControls(int keyFront, int keyBack,
|
|||
#define CAMERA_FREE_PANNING_DIVIDER 5.1f
|
||||
|
||||
// ORBITAL_CAMERA
|
||||
#define CAMERA_ORBITAL_SPEED 0.01f // Radians per frame
|
||||
#define CAMERA_ORBITAL_SPEED 0.5f // Radians per second
|
||||
|
||||
// FIRST_PERSON
|
||||
//#define CAMERA_FIRST_PERSON_MOUSE_SENSITIVITY 0.003f
|
||||
|
@ -171,9 +171,11 @@ void SetCameraMoveControls(int keyFront, int keyBack,
|
|||
#define CAMERA_FIRST_PERSON_MIN_CLAMP 89.0f
|
||||
#define CAMERA_FIRST_PERSON_MAX_CLAMP -89.0f
|
||||
|
||||
#define CAMERA_FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER 8.0f
|
||||
#define CAMERA_FIRST_PERSON_STEP_DIVIDER 30.0f
|
||||
#define CAMERA_FIRST_PERSON_WAVING_DIVIDER 200.0f
|
||||
// When walking, y-position of the player moves up-down at step frequency (swinging) but
|
||||
// also the body slightly tilts left-right on every step, when all the body weight is left over one foot (tilting)
|
||||
#define CAMERA_FIRST_PERSON_STEP_FREQUENCY 1.8f // Step frequency when walking (steps per second)
|
||||
#define CAMERA_FIRST_PERSON_SWINGING_DELTA 0.03f // Maximum up-down swinging distance when walking
|
||||
#define CAMERA_FIRST_PERSON_TILTING_DELTA 0.005f // Maximum left-right tilting distance when walking
|
||||
|
||||
// THIRD_PERSON
|
||||
//#define CAMERA_THIRD_PERSON_MOUSE_SENSITIVITY 0.003f
|
||||
|
@ -183,7 +185,7 @@ void SetCameraMoveControls(int keyFront, int keyBack,
|
|||
#define CAMERA_THIRD_PERSON_OFFSET (Vector3){ 0.4f, 0.0f, 0.0f }
|
||||
|
||||
// PLAYER (used by camera)
|
||||
#define PLAYER_MOVEMENT_SENSITIVITY 20.0f
|
||||
#define PLAYER_MOVEMENT_SENSITIVITY 2.0f
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
|
@ -204,7 +206,6 @@ typedef struct {
|
|||
float targetDistance; // Camera distance from position to target
|
||||
float playerEyesPosition; // Player eyes position from ground (in meters)
|
||||
Vector2 angle; // Camera angle in plane XZ
|
||||
Vector2 previousMousePosition; // Previous mouse position
|
||||
|
||||
// Camera movement control keys
|
||||
int moveControl[6]; // Move controls (CAMERA_FIRST_PERSON)
|
||||
|
@ -221,7 +222,6 @@ static CameraData CAMERA = { // Global CAMERA state context
|
|||
.targetDistance = 0,
|
||||
.playerEyesPosition = 1.85f,
|
||||
.angle = { 0 },
|
||||
.previousMousePosition = { 0 },
|
||||
.moveControl = { 'W', 'S', 'D', 'A', 'E', 'Q' },
|
||||
.smoothZoomControl = 341, // raylib: KEY_LEFT_CONTROL
|
||||
.altControl = 342, // raylib: KEY_LEFT_ALT
|
||||
|
@ -265,8 +265,6 @@ void SetCameraMode(Camera camera, int mode)
|
|||
|
||||
CAMERA.playerEyesPosition = camera.position.y; // Init player eyes position to camera Y position
|
||||
|
||||
CAMERA.previousMousePosition = GetMousePosition(); // Init mouse position
|
||||
|
||||
// Lock cursor for first person and third person cameras
|
||||
if ((mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON)) DisableCursor();
|
||||
else EnableCursor();
|
||||
|
@ -281,13 +279,12 @@ void SetCameraMode(Camera camera, int mode)
|
|||
// Keys: IsKeyDown()
|
||||
void UpdateCamera(Camera *camera)
|
||||
{
|
||||
static int swingCounter = 0; // Used for 1st person swinging movement
|
||||
static float swingCounter = 0.0f; // Used for 1st person swinging movement
|
||||
|
||||
// TODO: Compute CAMERA.targetDistance and CAMERA.angle here (?)
|
||||
|
||||
// Mouse movement detection
|
||||
Vector2 mousePositionDelta = { 0.0f, 0.0f };
|
||||
Vector2 mousePosition = GetMousePosition();
|
||||
Vector2 mousePositionDelta = GetMouseDelta();
|
||||
float mouseWheelMove = GetMouseWheelMove();
|
||||
|
||||
// Keys input detection
|
||||
|
@ -302,14 +299,6 @@ void UpdateCamera(Camera *camera)
|
|||
IsKeyDown(CAMERA.moveControl[MOVE_UP]),
|
||||
IsKeyDown(CAMERA.moveControl[MOVE_DOWN]) };
|
||||
|
||||
if (CAMERA.mode != CAMERA_CUSTOM)
|
||||
{
|
||||
mousePositionDelta.x = mousePosition.x - CAMERA.previousMousePosition.x;
|
||||
mousePositionDelta.y = mousePosition.y - CAMERA.previousMousePosition.y;
|
||||
|
||||
CAMERA.previousMousePosition = mousePosition;
|
||||
}
|
||||
|
||||
// Support for multiple automatic camera modes
|
||||
// NOTE: In case of CAMERA_CUSTOM nothing happens here, user must update it manually
|
||||
switch (CAMERA.mode)
|
||||
|
@ -388,9 +377,9 @@ void UpdateCamera(Camera *camera)
|
|||
else
|
||||
{
|
||||
// Camera panning
|
||||
camera->target.x += ((mousePositionDelta.x*CAMERA_FREE_MOUSE_SENSITIVITY)*cosf(CAMERA.angle.x) + (mousePositionDelta.y*CAMERA_FREE_MOUSE_SENSITIVITY)*sinf(CAMERA.angle.x)*sinf(CAMERA.angle.y))*(CAMERA.targetDistance/CAMERA_FREE_PANNING_DIVIDER);
|
||||
camera->target.x += ((mousePositionDelta.x*CAMERA_FREE_MOUSE_SENSITIVITY)*cosf(CAMERA.angle.x) + (mousePositionDelta.y*-CAMERA_FREE_MOUSE_SENSITIVITY)*sinf(CAMERA.angle.x)*sinf(CAMERA.angle.y))*(CAMERA.targetDistance/CAMERA_FREE_PANNING_DIVIDER);
|
||||
camera->target.y += ((mousePositionDelta.y*CAMERA_FREE_MOUSE_SENSITIVITY)*cosf(CAMERA.angle.y))*(CAMERA.targetDistance/CAMERA_FREE_PANNING_DIVIDER);
|
||||
camera->target.z += ((mousePositionDelta.x*-CAMERA_FREE_MOUSE_SENSITIVITY)*sinf(CAMERA.angle.x) + (mousePositionDelta.y*CAMERA_FREE_MOUSE_SENSITIVITY)*cosf(CAMERA.angle.x)*sinf(CAMERA.angle.y))*(CAMERA.targetDistance/CAMERA_FREE_PANNING_DIVIDER);
|
||||
camera->target.z += ((mousePositionDelta.x*-CAMERA_FREE_MOUSE_SENSITIVITY)*sinf(CAMERA.angle.x) + (mousePositionDelta.y*-CAMERA_FREE_MOUSE_SENSITIVITY)*cosf(CAMERA.angle.x)*sinf(CAMERA.angle.y))*(CAMERA.targetDistance/CAMERA_FREE_PANNING_DIVIDER);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -402,7 +391,7 @@ void UpdateCamera(Camera *camera)
|
|||
} break;
|
||||
case CAMERA_ORBITAL: // Camera just orbits around target, only zoom allowed
|
||||
{
|
||||
CAMERA.angle.x += CAMERA_ORBITAL_SPEED; // Camera orbit angle
|
||||
CAMERA.angle.x += CAMERA_ORBITAL_SPEED*GetFrameTime(); // Camera orbit angle
|
||||
CAMERA.targetDistance -= (mouseWheelMove*CAMERA_MOUSE_SCROLL_SENSITIVITY); // Camera zoom
|
||||
|
||||
// Camera distance clamp
|
||||
|
@ -419,20 +408,20 @@ void UpdateCamera(Camera *camera)
|
|||
camera->position.x += (sinf(CAMERA.angle.x)*direction[MOVE_BACK] -
|
||||
sinf(CAMERA.angle.x)*direction[MOVE_FRONT] -
|
||||
cosf(CAMERA.angle.x)*direction[MOVE_LEFT] +
|
||||
cosf(CAMERA.angle.x)*direction[MOVE_RIGHT])/PLAYER_MOVEMENT_SENSITIVITY;
|
||||
cosf(CAMERA.angle.x)*direction[MOVE_RIGHT])*PLAYER_MOVEMENT_SENSITIVITY*GetFrameTime();
|
||||
|
||||
camera->position.y += (sinf(CAMERA.angle.y)*direction[MOVE_FRONT] -
|
||||
sinf(CAMERA.angle.y)*direction[MOVE_BACK] +
|
||||
1.0f*direction[MOVE_UP] - 1.0f*direction[MOVE_DOWN])/PLAYER_MOVEMENT_SENSITIVITY;
|
||||
1.0f*direction[MOVE_UP] - 1.0f*direction[MOVE_DOWN])*PLAYER_MOVEMENT_SENSITIVITY*GetFrameTime();
|
||||
|
||||
camera->position.z += (cosf(CAMERA.angle.x)*direction[MOVE_BACK] -
|
||||
cosf(CAMERA.angle.x)*direction[MOVE_FRONT] +
|
||||
sinf(CAMERA.angle.x)*direction[MOVE_LEFT] -
|
||||
sinf(CAMERA.angle.x)*direction[MOVE_RIGHT])/PLAYER_MOVEMENT_SENSITIVITY;
|
||||
sinf(CAMERA.angle.x)*direction[MOVE_RIGHT])*PLAYER_MOVEMENT_SENSITIVITY*GetFrameTime();
|
||||
|
||||
// Camera orientation calculation
|
||||
CAMERA.angle.x += (mousePositionDelta.x*-CAMERA_MOUSE_MOVE_SENSITIVITY);
|
||||
CAMERA.angle.y += (mousePositionDelta.y*-CAMERA_MOUSE_MOVE_SENSITIVITY);
|
||||
CAMERA.angle.x -= mousePositionDelta.x*CAMERA_MOUSE_MOVE_SENSITIVITY*GetFrameTime();
|
||||
CAMERA.angle.y -= mousePositionDelta.y*CAMERA_MOUSE_MOVE_SENSITIVITY*GetFrameTime();
|
||||
|
||||
// Angle clamp
|
||||
if (CAMERA.angle.y > CAMERA_FIRST_PERSON_MIN_CLAMP*DEG2RAD) CAMERA.angle.y = CAMERA_FIRST_PERSON_MIN_CLAMP*DEG2RAD;
|
||||
|
@ -490,15 +479,17 @@ void UpdateCamera(Camera *camera)
|
|||
camera->target.y = camera->position.y - matTransform.m13;
|
||||
camera->target.z = camera->position.z - matTransform.m14;
|
||||
|
||||
// If movement detected (some key pressed), increase swinging
|
||||
for (int i = 0; i < 6; i++) if (direction[i]) { swingCounter++; break; }
|
||||
|
||||
// Camera position update
|
||||
// NOTE: On CAMERA_FIRST_PERSON player Y-movement is limited to player 'eyes position'
|
||||
camera->position.y = CAMERA.playerEyesPosition - sinf(swingCounter/CAMERA_FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER)/CAMERA_FIRST_PERSON_STEP_DIVIDER;
|
||||
camera->position.y = CAMERA.playerEyesPosition;
|
||||
|
||||
camera->up.x = sinf(swingCounter/(CAMERA_FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER*2))/CAMERA_FIRST_PERSON_WAVING_DIVIDER;
|
||||
camera->up.z = -sinf(swingCounter/(CAMERA_FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER*2))/CAMERA_FIRST_PERSON_WAVING_DIVIDER;
|
||||
// Camera swinging (y-movement), only when walking (some key pressed)
|
||||
for (int i = 0; i < 6; i++) if (direction[i]) { swingCounter += GetFrameTime(); break; }
|
||||
camera->position.y -= sinf(2*PI*CAMERA_FIRST_PERSON_STEP_FREQUENCY*swingCounter)*CAMERA_FIRST_PERSON_SWINGING_DELTA;
|
||||
|
||||
// Camera waiving (xz-movement), only when walking (some key pressed)
|
||||
camera->up.x = sinf(2*PI*CAMERA_FIRST_PERSON_STEP_FREQUENCY*swingCounter)*CAMERA_FIRST_PERSON_TILTING_DELTA;
|
||||
camera->up.z = -sinf(2*PI*CAMERA_FIRST_PERSON_STEP_FREQUENCY*swingCounter)*CAMERA_FIRST_PERSON_TILTING_DELTA;
|
||||
|
||||
} break;
|
||||
case CAMERA_THIRD_PERSON: // Camera moves as in a third-person game, following target at a distance, controls are configurable
|
||||
|
@ -506,16 +497,16 @@ void UpdateCamera(Camera *camera)
|
|||
camera->position.x += (sinf(CAMERA.angle.x)*direction[MOVE_BACK] -
|
||||
sinf(CAMERA.angle.x)*direction[MOVE_FRONT] -
|
||||
cosf(CAMERA.angle.x)*direction[MOVE_LEFT] +
|
||||
cosf(CAMERA.angle.x)*direction[MOVE_RIGHT])/PLAYER_MOVEMENT_SENSITIVITY;
|
||||
cosf(CAMERA.angle.x)*direction[MOVE_RIGHT])*PLAYER_MOVEMENT_SENSITIVITY*GetFrameTime();
|
||||
|
||||
camera->position.y += (sinf(CAMERA.angle.y)*direction[MOVE_FRONT] -
|
||||
sinf(CAMERA.angle.y)*direction[MOVE_BACK] +
|
||||
1.0f*direction[MOVE_UP] - 1.0f*direction[MOVE_DOWN])/PLAYER_MOVEMENT_SENSITIVITY;
|
||||
1.0f*direction[MOVE_UP] - 1.0f*direction[MOVE_DOWN])*PLAYER_MOVEMENT_SENSITIVITY*GetFrameTime();
|
||||
|
||||
camera->position.z += (cosf(CAMERA.angle.x)*direction[MOVE_BACK] -
|
||||
cosf(CAMERA.angle.x)*direction[MOVE_FRONT] +
|
||||
sinf(CAMERA.angle.x)*direction[MOVE_LEFT] -
|
||||
sinf(CAMERA.angle.x)*direction[MOVE_RIGHT])/PLAYER_MOVEMENT_SENSITIVITY;
|
||||
sinf(CAMERA.angle.x)*direction[MOVE_RIGHT])*PLAYER_MOVEMENT_SENSITIVITY*GetFrameTime();
|
||||
|
||||
// Camera orientation calculation
|
||||
CAMERA.angle.x += (mousePositionDelta.x*-CAMERA_MOUSE_MOVE_SENSITIVITY);
|
||||
|
|
1275
raylib/rcore.c
1275
raylib/rcore.c
File diff suppressed because it is too large
Load diff
|
@ -24,7 +24,7 @@
|
|||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2014-2021 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2014-2022 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.
|
||||
|
@ -62,10 +62,10 @@
|
|||
// NOTE: Below types are required for GESTURES_STANDALONE usage
|
||||
//----------------------------------------------------------------------------------
|
||||
// Boolean type
|
||||
#if defined(__STDC__) && __STDC_VERSION__ >= 199901L
|
||||
#if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
|
||||
#include <stdbool.h>
|
||||
#elif !defined(__cplusplus) && !defined(bool) && !defined(RL_BOOL_TYPE)
|
||||
typedef enum bool { false, true } bool;
|
||||
typedef enum bool { false = 0, true = !false } bool;
|
||||
#endif
|
||||
|
||||
#if !defined(RL_VECTOR2_TYPE)
|
||||
|
@ -118,7 +118,7 @@ typedef struct {
|
|||
// Module Functions Declaration
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if defined(__cplusplus)
|
||||
extern "C" { // Prevents name mangling of functions
|
||||
#endif
|
||||
|
||||
|
@ -137,7 +137,7 @@ Vector2 GetGesturePinchVector(void); // Get gesture pinch del
|
|||
float GetGesturePinchAngle(void); // Get gesture pinch angle
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
204
raylib/rlgl.h
204
raylib/rlgl.h
|
@ -85,7 +85,7 @@
|
|||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2014-2021 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2014-2022 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.
|
||||
|
@ -358,11 +358,11 @@ typedef struct rlRenderBatch {
|
|||
float currentDepth; // Current depth value for next draw
|
||||
} rlRenderBatch;
|
||||
|
||||
#if defined(__STDC__) && __STDC_VERSION__ >= 199901L
|
||||
#if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
|
||||
#include <stdbool.h>
|
||||
#elif !defined(__cplusplus) && !defined(bool) && !defined(RL_BOOL_TYPE)
|
||||
// Boolean type
|
||||
typedef enum bool { false, true } bool;
|
||||
typedef enum bool { false = 0, true = !false } bool;
|
||||
#endif
|
||||
|
||||
#if !defined(RL_MATRIX_TYPE)
|
||||
|
@ -418,7 +418,7 @@ typedef enum {
|
|||
// NOTE 1: Filtering considers mipmaps if available in the texture
|
||||
// NOTE 2: Filter is accordingly set for minification and magnification
|
||||
typedef enum {
|
||||
RL_TEXTURE_FILTER_POINT = 0, // No filter, just pixel aproximation
|
||||
RL_TEXTURE_FILTER_POINT = 0, // No filter, just pixel approximation
|
||||
RL_TEXTURE_FILTER_BILINEAR, // Linear filtering
|
||||
RL_TEXTURE_FILTER_TRILINEAR, // Trilinear filtering (linear with mipmaps)
|
||||
RL_TEXTURE_FILTER_ANISOTROPIC_4X, // Anisotropic filtering 4x
|
||||
|
@ -433,7 +433,8 @@ typedef enum {
|
|||
RL_BLEND_MULTIPLIED, // Blend textures multiplying colors
|
||||
RL_BLEND_ADD_COLORS, // Blend textures adding colors (alternative)
|
||||
RL_BLEND_SUBTRACT_COLORS, // Blend textures subtracting colors (alternative)
|
||||
RL_BLEND_CUSTOM // Belnd textures using custom src/dst factors (use SetBlendModeCustom())
|
||||
RL_BLEND_ALPHA_PREMULTIPLY, // Blend premultiplied textures considering alpha
|
||||
RL_BLEND_CUSTOM // Blend textures using custom src/dst factors (use rlSetBlendFactors())
|
||||
} rlBlendMode;
|
||||
|
||||
// Shader location point type
|
||||
|
@ -597,7 +598,9 @@ RLAPI void rlglInit(int width, int height); // Initialize rlgl (buffer
|
|||
RLAPI void rlglClose(void); // De-inititialize rlgl (buffers, shaders, textures)
|
||||
RLAPI void rlLoadExtensions(void *loader); // Load OpenGL extensions (loader function required)
|
||||
RLAPI int rlGetVersion(void); // Get current OpenGL version
|
||||
RLAPI void rlSetFramebufferWidth(int width); // Set current framebuffer width
|
||||
RLAPI int rlGetFramebufferWidth(void); // Get default framebuffer width
|
||||
RLAPI void rlSetFramebufferHeight(int height); // Set current framebuffer height
|
||||
RLAPI int rlGetFramebufferHeight(void); // Get default framebuffer height
|
||||
|
||||
RLAPI unsigned int rlGetTextureIdDefault(void); // Get default texture id
|
||||
|
@ -619,25 +622,26 @@ RLAPI void rlSetTexture(unsigned int id); // Set current texture for r
|
|||
|
||||
// Vertex buffers management
|
||||
RLAPI unsigned int rlLoadVertexArray(void); // Load vertex array (vao) if supported
|
||||
RLAPI unsigned int rlLoadVertexBuffer(void *buffer, int size, bool dynamic); // Load a vertex buffer attribute
|
||||
RLAPI unsigned int rlLoadVertexBufferElement(void *buffer, int size, bool dynamic); // Load a new attributes element buffer
|
||||
RLAPI void rlUpdateVertexBuffer(unsigned int bufferId, void *data, int dataSize, int offset); // Update GPU buffer with new data
|
||||
RLAPI unsigned int rlLoadVertexBuffer(const void *buffer, int size, bool dynamic); // Load a vertex buffer attribute
|
||||
RLAPI unsigned int rlLoadVertexBufferElement(const void *buffer, int size, bool dynamic); // Load a new attributes element buffer
|
||||
RLAPI void rlUpdateVertexBuffer(unsigned int bufferId, const void *data, int dataSize, int offset); // Update GPU buffer with new data
|
||||
RLAPI void rlUpdateVertexBufferElements(unsigned int id, const void *data, int dataSize, int offset); // Update vertex buffer elements with new data
|
||||
RLAPI void rlUnloadVertexArray(unsigned int vaoId);
|
||||
RLAPI void rlUnloadVertexBuffer(unsigned int vboId);
|
||||
RLAPI void rlSetVertexAttribute(unsigned int index, int compSize, int type, bool normalized, int stride, void *pointer);
|
||||
RLAPI void rlSetVertexAttribute(unsigned int index, int compSize, int type, bool normalized, int stride, const void *pointer);
|
||||
RLAPI void rlSetVertexAttributeDivisor(unsigned int index, int divisor);
|
||||
RLAPI void rlSetVertexAttributeDefault(int locIndex, const void *value, int attribType, int count); // Set vertex attribute default value
|
||||
RLAPI void rlDrawVertexArray(int offset, int count);
|
||||
RLAPI void rlDrawVertexArrayElements(int offset, int count, void *buffer);
|
||||
RLAPI void rlDrawVertexArrayElements(int offset, int count, const void *buffer);
|
||||
RLAPI void rlDrawVertexArrayInstanced(int offset, int count, int instances);
|
||||
RLAPI void rlDrawVertexArrayElementsInstanced(int offset, int count, void *buffer, int instances);
|
||||
RLAPI void rlDrawVertexArrayElementsInstanced(int offset, int count, const void *buffer, int instances);
|
||||
|
||||
// Textures management
|
||||
RLAPI unsigned int rlLoadTexture(void *data, int width, int height, int format, int mipmapCount); // Load texture in GPU
|
||||
RLAPI unsigned int rlLoadTexture(const void *data, int width, int height, int format, int mipmapCount); // Load texture in GPU
|
||||
RLAPI unsigned int rlLoadTextureDepth(int width, int height, bool useRenderBuffer); // Load depth texture/renderbuffer (to be attached to fbo)
|
||||
RLAPI unsigned int rlLoadTextureCubemap(void *data, int size, int format); // Load texture cubemap
|
||||
RLAPI unsigned int rlLoadTextureCubemap(const void *data, int size, int format); // Load texture cubemap
|
||||
RLAPI void rlUpdateTexture(unsigned int id, int offsetX, int offsetY, int width, int height, int format, const void *data); // Update GPU texture with new data
|
||||
RLAPI void rlGetGlTextureFormats(int format, int *glInternalFormat, int *glFormat, int *glType); // Get OpenGL internal formats
|
||||
RLAPI void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned int *glFormat, unsigned int *glType); // Get OpenGL internal formats
|
||||
RLAPI const char *rlGetPixelFormatName(unsigned int format); // Get name string for pixel format
|
||||
RLAPI void rlUnloadTexture(unsigned int id); // Unload texture from GPU memory
|
||||
RLAPI void rlGenTextureMipmaps(unsigned int id, int width, int height, int format, int *mipmaps); // Generate mipmap data for selected texture
|
||||
|
@ -713,7 +717,7 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
|
|||
#include <OpenGL/glext.h> // OpenGL extensions library
|
||||
#else
|
||||
// APIENTRY for OpenGL function pointer declarations is required
|
||||
#ifndef APIENTRY
|
||||
#if !defined(APIENTRY)
|
||||
#if defined(_WIN32)
|
||||
#define APIENTRY __stdcall
|
||||
#else
|
||||
|
@ -925,8 +929,8 @@ typedef struct rlglData {
|
|||
int glBlendDstFactor; // Blending destination factor
|
||||
int glBlendEquation; // Blending equation
|
||||
|
||||
int framebufferWidth; // Default framebuffer width
|
||||
int framebufferHeight; // Default framebuffer height
|
||||
int framebufferWidth; // Current framebuffer width
|
||||
int framebufferHeight; // Current framebuffer height
|
||||
|
||||
} State; // Renderer state
|
||||
struct {
|
||||
|
@ -1228,6 +1232,7 @@ void rlOrtho(double left, double right, double bottom, double top, double znear,
|
|||
#endif
|
||||
|
||||
// Set the viewport area (transformation from normalized device coordinates to window coordinates)
|
||||
// NOTE: We store current viewport dimensions
|
||||
void rlViewport(int x, int y, int width, int height)
|
||||
{
|
||||
glViewport(x, y, width, height);
|
||||
|
@ -1512,6 +1517,11 @@ void rlTextureParameters(unsigned int id, int param, int value)
|
|||
{
|
||||
glBindTexture(GL_TEXTURE_2D, id);
|
||||
|
||||
#if !defined(GRAPHICS_API_OPENGL_11)
|
||||
// Reset anisotropy filter, in case it was set
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
|
||||
#endif
|
||||
|
||||
switch (param)
|
||||
{
|
||||
case RL_TEXTURE_WRAP_S:
|
||||
|
@ -1535,7 +1545,7 @@ void rlTextureParameters(unsigned int id, int param, int value)
|
|||
if (value <= RLGL.ExtSupported.maxAnisotropyLevel) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value);
|
||||
else if (RLGL.ExtSupported.maxAnisotropyLevel > 0.0f)
|
||||
{
|
||||
TRACELOG(RL_LOG_WARNING, "GL: Maximum anisotropic filter level supported is %iX", id, RLGL.ExtSupported.maxAnisotropyLevel);
|
||||
TRACELOG(RL_LOG_WARNING, "GL: Maximum anisotropic filter level supported is %iX", id, (int)RLGL.ExtSupported.maxAnisotropyLevel);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value);
|
||||
}
|
||||
else TRACELOG(RL_LOG_WARNING, "GL: Anisotropic filtering not supported");
|
||||
|
@ -1778,7 +1788,12 @@ void rlSetBlendMode(int mode)
|
|||
case RL_BLEND_MULTIPLIED: glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); break;
|
||||
case RL_BLEND_ADD_COLORS: glBlendFunc(GL_ONE, GL_ONE); glBlendEquation(GL_FUNC_ADD); break;
|
||||
case RL_BLEND_SUBTRACT_COLORS: glBlendFunc(GL_ONE, GL_ONE); glBlendEquation(GL_FUNC_SUBTRACT); break;
|
||||
case RL_BLEND_CUSTOM: glBlendFunc(RLGL.State.glBlendSrcFactor, RLGL.State.glBlendDstFactor); glBlendEquation(RLGL.State.glBlendEquation); break;
|
||||
case RL_BLEND_ALPHA_PREMULTIPLY: glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); break;
|
||||
case RL_BLEND_CUSTOM:
|
||||
{
|
||||
// NOTE: Using GL blend src/dst factors and GL equation configured with rlSetBlendFactors()
|
||||
glBlendFunc(RLGL.State.glBlendSrcFactor, RLGL.State.glBlendDstFactor); glBlendEquation(RLGL.State.glBlendEquation);
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
|
@ -2212,6 +2227,22 @@ int rlGetVersion(void)
|
|||
return glVersion;
|
||||
}
|
||||
|
||||
// Set current framebuffer width
|
||||
void rlSetFramebufferWidth(int width)
|
||||
{
|
||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
RLGL.State.framebufferWidth = width;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Set current framebuffer height
|
||||
void rlSetFramebufferHeight(int height)
|
||||
{
|
||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
RLGL.State.framebufferHeight = height;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Get default framebuffer width
|
||||
int rlGetFramebufferWidth(void)
|
||||
{
|
||||
|
@ -2594,6 +2625,9 @@ void rlDrawRenderBatch(rlRenderBatch *batch)
|
|||
|
||||
glUseProgram(0); // Unbind shader program
|
||||
}
|
||||
|
||||
// Restore viewport to default measures
|
||||
if (eyeCount == 2) rlViewport(0, 0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight);
|
||||
//------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// Reset batch buffers
|
||||
|
@ -2676,12 +2710,12 @@ bool rlCheckRenderBatchLimit(int vCount)
|
|||
// Textures data management
|
||||
//-----------------------------------------------------------------------------------------
|
||||
// Convert image data to OpenGL texture (returns OpenGL valid Id)
|
||||
unsigned int rlLoadTexture(void *data, int width, int height, int format, int mipmapCount)
|
||||
unsigned int rlLoadTexture(const void *data, int width, int height, int format, int mipmapCount)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, 0); // Free any old binding
|
||||
|
||||
unsigned int id = 0;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0); // Free any old binding
|
||||
|
||||
// Check texture format support by OpenGL 1.1 (compressed textures not supported)
|
||||
#if defined(GRAPHICS_API_OPENGL_11)
|
||||
if (format >= RL_PIXELFORMAT_COMPRESSED_DXT1_RGB)
|
||||
|
@ -2738,7 +2772,7 @@ unsigned int rlLoadTexture(void *data, int width, int height, int format, int mi
|
|||
{
|
||||
unsigned int mipSize = rlGetPixelDataSize(mipWidth, mipHeight, format);
|
||||
|
||||
int glInternalFormat, glFormat, glType;
|
||||
unsigned int glInternalFormat, glFormat, glType;
|
||||
rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType);
|
||||
|
||||
TRACELOGD("TEXTURE: Load mipmap level %i (%i x %i), size: %i, offset: %i", i, mipWidth, mipHeight, mipSize, mipOffset);
|
||||
|
@ -2878,7 +2912,7 @@ unsigned int rlLoadTextureDepth(int width, int height, bool useRenderBuffer)
|
|||
// Load texture cubemap
|
||||
// NOTE: Cubemap data is expected to be 6 images in a single data array (one after the other),
|
||||
// expected the following convention: +X, -X, +Y, -Y, +Z, -Z
|
||||
unsigned int rlLoadTextureCubemap(void *data, int size, int format)
|
||||
unsigned int rlLoadTextureCubemap(const void *data, int size, int format)
|
||||
{
|
||||
unsigned int id = 0;
|
||||
|
||||
|
@ -2888,7 +2922,7 @@ unsigned int rlLoadTextureCubemap(void *data, int size, int format)
|
|||
glGenTextures(1, &id);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, id);
|
||||
|
||||
int glInternalFormat, glFormat, glType;
|
||||
unsigned int glInternalFormat, glFormat, glType;
|
||||
rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType);
|
||||
|
||||
if (glInternalFormat != -1)
|
||||
|
@ -2960,22 +2994,22 @@ void rlUpdateTexture(unsigned int id, int offsetX, int offsetY, int width, int h
|
|||
{
|
||||
glBindTexture(GL_TEXTURE_2D, id);
|
||||
|
||||
int glInternalFormat, glFormat, glType;
|
||||
unsigned int glInternalFormat, glFormat, glType;
|
||||
rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType);
|
||||
|
||||
if ((glInternalFormat != -1) && (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB))
|
||||
{
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, offsetX, offsetY, width, height, glFormat, glType, (unsigned char *)data);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, offsetX, offsetY, width, height, glFormat, glType, data);
|
||||
}
|
||||
else TRACELOG(RL_LOG_WARNING, "TEXTURE: [ID %i] Failed to update for current texture format (%i)", id, format);
|
||||
}
|
||||
|
||||
// Get OpenGL internal formats and data type from raylib PixelFormat
|
||||
void rlGetGlTextureFormats(int format, int *glInternalFormat, int *glFormat, int *glType)
|
||||
void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned int *glFormat, unsigned int *glType)
|
||||
{
|
||||
*glInternalFormat = -1;
|
||||
*glFormat = -1;
|
||||
*glType = -1;
|
||||
*glInternalFormat = 0;
|
||||
*glFormat = 0;
|
||||
*glType = 0;
|
||||
|
||||
switch (format)
|
||||
{
|
||||
|
@ -3081,14 +3115,11 @@ void rlGenTextureMipmaps(unsigned int id, int width, int height, int format, int
|
|||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
if ((texIsPOT) || (RLGL.ExtSupported.texNPOT))
|
||||
{
|
||||
//glHint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE); // Hint for mipmaps generation algorythm: GL_FASTEST, GL_NICEST, GL_DONT_CARE
|
||||
//glHint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE); // Hint for mipmaps generation algorithm: GL_FASTEST, GL_NICEST, GL_DONT_CARE
|
||||
glGenerateMipmap(GL_TEXTURE_2D); // Generate mipmaps automatically
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // Activate Trilinear filtering for mipmaps
|
||||
|
||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||
#define MAX(a,b) (((a)>(b))?(a):(b))
|
||||
#define MIN(a,b) (((a)<(b))? (a):(b))
|
||||
#define MAX(a,b) (((a)>(b))? (a):(b))
|
||||
|
||||
*mipmaps = 1 + (int)floor(log(MAX(width, height))/log(2));
|
||||
TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Mipmaps generated automatically, total: %i", id, *mipmaps);
|
||||
|
@ -3121,7 +3152,7 @@ void *rlReadTexturePixels(unsigned int id, int width, int height, int format)
|
|||
// GL_UNPACK_ALIGNMENT affects operations that write to OpenGL memory (glTexImage, etc.)
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
|
||||
int glInternalFormat, glFormat, glType;
|
||||
unsigned int glInternalFormat, glFormat, glType;
|
||||
rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType);
|
||||
unsigned int size = rlGetPixelDataSize(width, height, format);
|
||||
|
||||
|
@ -3164,7 +3195,6 @@ void *rlReadTexturePixels(unsigned int id, int width, int height, int format)
|
|||
return pixels;
|
||||
}
|
||||
|
||||
|
||||
// Read screen pixel data (color buffer)
|
||||
unsigned char *rlReadScreenPixels(int width, int height)
|
||||
{
|
||||
|
@ -3313,7 +3343,7 @@ void rlUnloadFramebuffer(unsigned int id)
|
|||
// Vertex data management
|
||||
//-----------------------------------------------------------------------------------------
|
||||
// Load a new attributes buffer
|
||||
unsigned int rlLoadVertexBuffer(void *buffer, int size, bool dynamic)
|
||||
unsigned int rlLoadVertexBuffer(const void *buffer, int size, bool dynamic)
|
||||
{
|
||||
unsigned int id = 0;
|
||||
|
||||
|
@ -3327,7 +3357,7 @@ unsigned int rlLoadVertexBuffer(void *buffer, int size, bool dynamic)
|
|||
}
|
||||
|
||||
// Load a new attributes element buffer
|
||||
unsigned int rlLoadVertexBufferElement(void *buffer, int size, bool dynamic)
|
||||
unsigned int rlLoadVertexBufferElement(const void *buffer, int size, bool dynamic)
|
||||
{
|
||||
unsigned int id = 0;
|
||||
|
||||
|
@ -3374,7 +3404,7 @@ void rlDisableVertexBufferElement(void)
|
|||
|
||||
// Update vertex buffer with new data
|
||||
// NOTE: dataSize and offset must be provided in bytes
|
||||
void rlUpdateVertexBuffer(unsigned int id, void *data, int dataSize, int offset)
|
||||
void rlUpdateVertexBuffer(unsigned int id, const void *data, int dataSize, int offset)
|
||||
{
|
||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
glBindBuffer(GL_ARRAY_BUFFER, id);
|
||||
|
@ -3384,7 +3414,7 @@ void rlUpdateVertexBuffer(unsigned int id, void *data, int dataSize, int offset)
|
|||
|
||||
// Update vertex buffer elements with new data
|
||||
// NOTE: dataSize and offset must be provided in bytes
|
||||
void rlUpdateVertexBufferElements(unsigned int id, void *data, int dataSize, int offset)
|
||||
void rlUpdateVertexBufferElements(unsigned int id, const void *data, int dataSize, int offset)
|
||||
{
|
||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id);
|
||||
|
@ -3437,9 +3467,9 @@ void rlDrawVertexArray(int offset, int count)
|
|||
}
|
||||
|
||||
// Draw vertex array elements
|
||||
void rlDrawVertexArrayElements(int offset, int count, void *buffer)
|
||||
void rlDrawVertexArrayElements(int offset, int count, const void *buffer)
|
||||
{
|
||||
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (unsigned short *)buffer + offset);
|
||||
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (const unsigned short *)buffer + offset);
|
||||
}
|
||||
|
||||
// Draw vertex array instanced
|
||||
|
@ -3451,10 +3481,10 @@ void rlDrawVertexArrayInstanced(int offset, int count, int instances)
|
|||
}
|
||||
|
||||
// Draw vertex array elements instanced
|
||||
void rlDrawVertexArrayElementsInstanced(int offset, int count, 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)
|
||||
glDrawElementsInstanced(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (unsigned short *)buffer + offset, instances);
|
||||
glDrawElementsInstanced(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (const unsigned short *)buffer + offset, instances);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -3495,7 +3525,7 @@ unsigned int rlLoadVertexArray(void)
|
|||
}
|
||||
|
||||
// Set vertex attribute
|
||||
void rlSetVertexAttribute(unsigned int index, int compSize, int type, bool normalized, int stride, void *pointer)
|
||||
void rlSetVertexAttribute(unsigned int index, int compSize, int type, bool normalized, int stride, const void *pointer)
|
||||
{
|
||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
glVertexAttribPointer(index, compSize, type, normalized, stride, pointer);
|
||||
|
@ -3541,56 +3571,69 @@ unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode)
|
|||
unsigned int id = 0;
|
||||
|
||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
unsigned int vertexShaderId = RLGL.State.defaultVShaderId;
|
||||
unsigned int fragmentShaderId = RLGL.State.defaultFShaderId;
|
||||
unsigned int vertexShaderId = 0;
|
||||
unsigned int fragmentShaderId = 0;
|
||||
|
||||
// Compile vertex shader (if provided)
|
||||
if (vsCode != NULL) vertexShaderId = rlCompileShader(vsCode, GL_VERTEX_SHADER);
|
||||
if (fsCode != NULL) fragmentShaderId = rlCompileShader(fsCode, GL_FRAGMENT_SHADER);
|
||||
// In case no vertex shader was provided or compilation failed, we use default vertex shader
|
||||
if (vertexShaderId == 0) vertexShaderId = RLGL.State.defaultVShaderId;
|
||||
|
||||
// Compile fragment shader (if provided)
|
||||
if (fsCode != NULL) fragmentShaderId = rlCompileShader(fsCode, GL_FRAGMENT_SHADER);
|
||||
// In case no fragment shader was provided or compilation failed, we use default fragment shader
|
||||
if (fragmentShaderId == 0) fragmentShaderId = RLGL.State.defaultFShaderId;
|
||||
|
||||
// In case vertex and fragment shader are the default ones, no need to recompile, we can just assign the default shader program id
|
||||
if ((vertexShaderId == RLGL.State.defaultVShaderId) && (fragmentShaderId == RLGL.State.defaultFShaderId)) id = RLGL.State.defaultShaderId;
|
||||
else
|
||||
{
|
||||
// One of or both shader are new, we need to compile a new shader program
|
||||
id = rlLoadShaderProgram(vertexShaderId, fragmentShaderId);
|
||||
|
||||
// We can detach and delete vertex/fragment shaders (if not default ones)
|
||||
// NOTE: We detach shader before deletion to make sure memory is freed
|
||||
if (vertexShaderId != RLGL.State.defaultVShaderId)
|
||||
{
|
||||
// Detach shader before deletion to make sure memory is freed
|
||||
glDetachShader(id, vertexShaderId);
|
||||
glDeleteShader(vertexShaderId);
|
||||
}
|
||||
if (fragmentShaderId != RLGL.State.defaultFShaderId)
|
||||
{
|
||||
// Detach shader before deletion to make sure memory is freed
|
||||
glDetachShader(id, fragmentShaderId);
|
||||
glDeleteShader(fragmentShaderId);
|
||||
}
|
||||
|
||||
// In case shader program loading failed, we assign default shader
|
||||
if (id == 0)
|
||||
{
|
||||
TRACELOG(RL_LOG_WARNING, "SHADER: Failed to load custom shader code");
|
||||
// In case shader loading fails, we return the default shader
|
||||
TRACELOG(RL_LOG_WARNING, "SHADER: Failed to load custom shader code, using default shader");
|
||||
id = RLGL.State.defaultShaderId;
|
||||
}
|
||||
}
|
||||
/*
|
||||
else
|
||||
{
|
||||
// Get available shader uniforms
|
||||
// NOTE: This information is useful for debug...
|
||||
int uniformCount = -1;
|
||||
glGetProgramiv(id, GL_ACTIVE_UNIFORMS, &uniformCount);
|
||||
|
||||
// Get available shader uniforms
|
||||
// NOTE: This information is useful for debug...
|
||||
int uniformCount = -1;
|
||||
for (int i = 0; i < uniformCount; i++)
|
||||
{
|
||||
int namelen = -1;
|
||||
int num = -1;
|
||||
char name[256] = { 0 }; // Assume no variable names longer than 256
|
||||
GLenum type = GL_ZERO;
|
||||
|
||||
glGetProgramiv(id, GL_ACTIVE_UNIFORMS, &uniformCount);
|
||||
// Get the name of the uniforms
|
||||
glGetActiveUniform(id, i, sizeof(name) - 1, &namelen, &num, &type, name);
|
||||
|
||||
for (int i = 0; i < uniformCount; i++)
|
||||
{
|
||||
int namelen = -1;
|
||||
int num = -1;
|
||||
char name[256] = { 0 }; // Assume no variable names longer than 256
|
||||
GLenum type = GL_ZERO;
|
||||
|
||||
// Get the name of the uniforms
|
||||
glGetActiveUniform(id, i, sizeof(name) - 1, &namelen, &num, &type, name);
|
||||
|
||||
name[namelen] = 0;
|
||||
|
||||
TRACELOGD("SHADER: [ID %i] Active uniform (%s) set at location: %i", id, name, glGetUniformLocation(id, name));
|
||||
name[namelen] = 0;
|
||||
TRACELOGD("SHADER: [ID %i] Active uniform (%s) set at location: %i", id, name, glGetUniformLocation(id, name));
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -3629,7 +3672,7 @@ unsigned int rlCompileShader(const char *shaderCode, int type)
|
|||
if (maxLength > 0)
|
||||
{
|
||||
int length = 0;
|
||||
char *log = RL_CALLOC(maxLength, sizeof(char));
|
||||
char *log = (char *)RL_CALLOC(maxLength, sizeof(char));
|
||||
glGetShaderInfoLog(shader, maxLength, &length, log);
|
||||
TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Compile error: %s", shader, log);
|
||||
RL_FREE(log);
|
||||
|
@ -3691,7 +3734,7 @@ unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId)
|
|||
if (maxLength > 0)
|
||||
{
|
||||
int length = 0;
|
||||
char *log = RL_CALLOC(maxLength, sizeof(char));
|
||||
char *log = (char *)RL_CALLOC(maxLength, sizeof(char));
|
||||
glGetProgramInfoLog(program, maxLength, &length, log);
|
||||
TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Link error: %s", program, log);
|
||||
RL_FREE(log);
|
||||
|
@ -3858,7 +3901,7 @@ unsigned int rlLoadComputeShaderProgram(unsigned int shaderId)
|
|||
if (maxLength > 0)
|
||||
{
|
||||
int length = 0;
|
||||
char *log = RL_CALLOC(maxLength, sizeof(char));
|
||||
char *log = (char *)RL_CALLOC(maxLength, sizeof(char));
|
||||
glGetProgramInfoLog(program, maxLength, &length, log);
|
||||
TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Link error: %s", program, log);
|
||||
RL_FREE(log);
|
||||
|
@ -3894,11 +3937,13 @@ void rlComputeShaderDispatch(unsigned int groupX, unsigned int groupY, unsigned
|
|||
unsigned int rlLoadShaderBuffer(unsigned long long size, const void *data, int usageHint)
|
||||
{
|
||||
unsigned int ssbo = 0;
|
||||
|
||||
|
||||
#if defined(GRAPHICS_API_OPENGL_43)
|
||||
glGenBuffers(1, &ssbo);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
|
||||
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);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
||||
#endif
|
||||
|
||||
return ssbo;
|
||||
|
@ -3925,7 +3970,7 @@ void rlUpdateShaderBufferElements(unsigned int id, const void *data, unsigned lo
|
|||
unsigned long long rlGetShaderBufferSize(unsigned int id)
|
||||
{
|
||||
long long size = 0;
|
||||
|
||||
|
||||
#if defined(GRAPHICS_API_OPENGL_43)
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, id);
|
||||
glGetInteger64v(GL_SHADER_STORAGE_BUFFER_SIZE, &size);
|
||||
|
@ -3965,7 +4010,7 @@ void rlCopyBuffersElements(unsigned int destId, unsigned int srcId, unsigned lon
|
|||
void rlBindImageTexture(unsigned int id, unsigned int index, unsigned int format, int readonly)
|
||||
{
|
||||
#if defined(GRAPHICS_API_OPENGL_43)
|
||||
int glInternalFormat = 0, glFormat = 0, glType = 0;
|
||||
unsigned int glInternalFormat = 0, glFormat = 0, glType = 0;
|
||||
|
||||
rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType);
|
||||
glBindImageTexture(index, id, 0, 0, 0, readonly ? GL_READ_ONLY : GL_READ_WRITE, glInternalFormat);
|
||||
|
@ -4336,7 +4381,8 @@ static void rlLoadShaderDefault(void)
|
|||
"} \n";
|
||||
#endif
|
||||
|
||||
// NOTE: Compiled vertex/fragment shaders are kept for re-use
|
||||
// NOTE: Compiled vertex/fragment shaders are not deleted,
|
||||
// they are kept for re-use as default shaders in case some shader loading fails
|
||||
RLGL.State.defaultVShaderId = rlCompileShader(defaultVShaderCode, GL_VERTEX_SHADER); // Compile default vertex shader
|
||||
RLGL.State.defaultFShaderId = rlCompileShader(defaultFShaderCode, GL_FRAGMENT_SHADER); // Compile default fragment shader
|
||||
|
||||
|
|
678
raylib/rmodels.c
678
raylib/rmodels.c
File diff suppressed because it is too large
Load diff
|
@ -6,24 +6,27 @@
|
|||
* 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
|
||||
* are used but QUADS implementation can be selected with SUPPORT_QUADS_DRAW_MODE define
|
||||
*
|
||||
* Some functions define texture coordinates (rlTexCoord2f()) for the shapes and use a
|
||||
*
|
||||
* Some functions define texture coordinates (rlTexCoord2f()) for the shapes and use a
|
||||
* user-provided texture with SetShapesTexture(), the pourpouse of this implementation
|
||||
* is allowing to reduce draw calls when combined with a texture-atlas.
|
||||
*
|
||||
* By default, raylib sets the default texture and rectangle at InitWindow()[rcore] to one
|
||||
* By default, raylib sets the default texture and rectangle at InitWindow()[rcore] to one
|
||||
* white character of default font [rtext], this way, raylib text and shapes can be draw with
|
||||
* a single draw call and it also allows users to configure it the same way with their own fonts.
|
||||
*
|
||||
* CONFIGURATION:
|
||||
*
|
||||
* #define SUPPORT_MODULE_RSHAPES
|
||||
* rshapes module is included in the build
|
||||
*
|
||||
* #define SUPPORT_QUADS_DRAW_MODE
|
||||
* Use QUADS instead of TRIANGLES for drawing when possible. Lines-based shapes still use LINES
|
||||
*
|
||||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2013-2021 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2013-2022 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.
|
||||
|
@ -49,6 +52,8 @@
|
|||
#include "config.h" // Defines module configuration flags
|
||||
#endif
|
||||
|
||||
#if defined(SUPPORT_MODULE_RSHAPES)
|
||||
|
||||
#include "rlgl.h" // OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2
|
||||
|
||||
#include <math.h> // Required for: sinf(), asinf(), cosf(), acosf(), sqrtf(), fabsf()
|
||||
|
@ -75,8 +80,8 @@
|
|||
//----------------------------------------------------------------------------------
|
||||
// Global Variables Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
Texture2D texShapes = { 1, 1, 1, 1, 7 }; // Texture used on shapes drawing (usually a white pixel)
|
||||
Rectangle texShapesRec = { 0, 0, 1, 1 }; // Texture source rectangle used on shapes drawing
|
||||
Texture2D texShapes = { 1, 1, 1, 1, 7 }; // Texture used on shapes drawing (usually a white pixel)
|
||||
Rectangle texShapesRec = { 0.0f, 0.0f, 1.0f, 1.0f }; // Texture source rectangle used on shapes drawing
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module specific Functions Declaration
|
||||
|
@ -718,7 +723,7 @@ void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color
|
|||
rlCheckRenderBatchLimit(4);
|
||||
|
||||
rlSetTexture(texShapes.id);
|
||||
|
||||
|
||||
rlBegin(RL_QUADS);
|
||||
|
||||
rlNormal3f(0.0f, 0.0f, 1.0f);
|
||||
|
@ -737,13 +742,13 @@ void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color
|
|||
rlVertex2f(topRight.x, topRight.y);
|
||||
|
||||
rlEnd();
|
||||
|
||||
|
||||
rlSetTexture(0);
|
||||
#else
|
||||
rlCheckRenderBatchLimit(6);
|
||||
|
||||
rlBegin(RL_TRIANGLES);
|
||||
|
||||
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
|
||||
rlVertex2f(topLeft.x, topLeft.y);
|
||||
|
@ -780,28 +785,26 @@ void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3,
|
|||
|
||||
rlSetTexture(texShapes.id);
|
||||
|
||||
rlPushMatrix();
|
||||
rlBegin(RL_QUADS);
|
||||
rlNormal3f(0.0f, 0.0f, 1.0f);
|
||||
rlBegin(RL_QUADS);
|
||||
rlNormal3f(0.0f, 0.0f, 1.0f);
|
||||
|
||||
// NOTE: Default raylib font character 95 is a white square
|
||||
rlColor4ub(col1.r, col1.g, col1.b, col1.a);
|
||||
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
||||
rlVertex2f(rec.x, rec.y);
|
||||
// NOTE: Default raylib font character 95 is a white square
|
||||
rlColor4ub(col1.r, col1.g, col1.b, col1.a);
|
||||
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
||||
rlVertex2f(rec.x, rec.y);
|
||||
|
||||
rlColor4ub(col2.r, col2.g, col2.b, col2.a);
|
||||
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||
rlVertex2f(rec.x, rec.y + rec.height);
|
||||
rlColor4ub(col2.r, col2.g, col2.b, col2.a);
|
||||
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||
rlVertex2f(rec.x, rec.y + rec.height);
|
||||
|
||||
rlColor4ub(col3.r, col3.g, col3.b, col3.a);
|
||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||
rlVertex2f(rec.x + rec.width, rec.y + rec.height);
|
||||
rlColor4ub(col3.r, col3.g, col3.b, col3.a);
|
||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||
rlVertex2f(rec.x + rec.width, rec.y + rec.height);
|
||||
|
||||
rlColor4ub(col4.r, col4.g, col4.b, col4.a);
|
||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
||||
rlVertex2f(rec.x + rec.width, rec.y);
|
||||
rlEnd();
|
||||
rlPopMatrix();
|
||||
rlColor4ub(col4.r, col4.g, col4.b, col4.a);
|
||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
||||
rlVertex2f(rec.x + rec.width, rec.y);
|
||||
rlEnd();
|
||||
|
||||
rlSetTexture(0);
|
||||
}
|
||||
|
@ -1604,7 +1607,7 @@ bool CheckCollisionPointRec(Vector2 point, Rectangle rec)
|
|||
bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius)
|
||||
{
|
||||
bool collision = false;
|
||||
|
||||
|
||||
collision = CheckCollisionCircles(point, 0, center, radius);
|
||||
|
||||
return collision;
|
||||
|
@ -1676,7 +1679,7 @@ bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec)
|
|||
(dy - rec.height/2.0f)*(dy - rec.height/2.0f);
|
||||
|
||||
collision = (cornerDistanceSq <= (radius*radius));
|
||||
|
||||
|
||||
return collision;
|
||||
}
|
||||
|
||||
|
@ -1690,10 +1693,10 @@ bool CheckCollisionLines(Vector2 startPos1, Vector2 endPos1, Vector2 startPos2,
|
|||
if (fabsf(div) >= FLT_EPSILON)
|
||||
{
|
||||
collision = true;
|
||||
|
||||
|
||||
float xi = ((startPos2.x - endPos2.x)*(startPos1.x*endPos1.y - startPos1.y*endPos1.x) - (startPos1.x - endPos1.x)*(startPos2.x*endPos2.y - startPos2.y*endPos2.x))/div;
|
||||
float yi = ((startPos2.y - endPos2.y)*(startPos1.x*endPos1.y - startPos1.y*endPos1.x) - (startPos1.y - endPos1.y)*(startPos2.x*endPos2.y - startPos2.y*endPos2.x))/div;
|
||||
|
||||
|
||||
if (((fabsf(startPos1.x - endPos1.x) > FLT_EPSILON) && (xi < fminf(startPos1.x, endPos1.x) || (xi > fmaxf(startPos1.x, endPos1.x)))) ||
|
||||
((fabsf(startPos2.x - endPos2.x) > FLT_EPSILON) && (xi < fminf(startPos2.x, endPos2.x) || (xi > fmaxf(startPos2.x, endPos2.x)))) ||
|
||||
((fabsf(startPos1.y - endPos1.y) > FLT_EPSILON) && (yi < fminf(startPos1.y, endPos1.y) || (yi > fmaxf(startPos1.y, endPos1.y)))) ||
|
||||
|
@ -1810,3 +1813,5 @@ static float EaseCubicInOut(float t, float b, float c, float d)
|
|||
|
||||
return 0.5f*c*(t*t*t + 2.0f) + b;
|
||||
}
|
||||
|
||||
#endif // SUPPORT_MODULE_RSHAPES
|
||||
|
|
278
raylib/rtext.c
278
raylib/rtext.c
|
@ -4,6 +4,9 @@
|
|||
*
|
||||
* CONFIGURATION:
|
||||
*
|
||||
* #define SUPPORT_MODULE_RTEXT
|
||||
* rtext module is included in the build
|
||||
*
|
||||
* #define SUPPORT_FILEFORMAT_FNT
|
||||
* #define SUPPORT_FILEFORMAT_TTF
|
||||
* Selected desired fileformats to be supported for loading. Some of those formats are
|
||||
|
@ -22,12 +25,12 @@
|
|||
*
|
||||
* DEPENDENCIES:
|
||||
* stb_truetype - Load TTF file and rasterize characters data
|
||||
* stb_rect_pack - Rectangles packing algorythms, required for font atlas generation
|
||||
* stb_rect_pack - Rectangles packing algorithms, required for font atlas generation
|
||||
*
|
||||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2013-2021 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2013-2022 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.
|
||||
|
@ -53,6 +56,8 @@
|
|||
#include "config.h" // Defines module configuration flags
|
||||
#endif
|
||||
|
||||
#if defined(SUPPORT_MODULE_RTEXT)
|
||||
|
||||
#include "utils.h" // Required for: LoadFileText()
|
||||
#include "rlgl.h" // OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2 -> Only DrawTextPro()
|
||||
|
||||
|
@ -224,7 +229,7 @@ extern void LoadFontDefault(void)
|
|||
//------------------------------------------------------------------------------
|
||||
|
||||
// Allocate space for our characters info data
|
||||
// NOTE: This memory should be freed at end! --> CloseWindow()
|
||||
// NOTE: This memory must be freed at end! --> Done by CloseWindow()
|
||||
defaultFont.glyphs = (GlyphInfo *)RL_MALLOC(defaultFont.glyphCount*sizeof(GlyphInfo));
|
||||
defaultFont.recs = (Rectangle *)RL_MALLOC(defaultFont.glyphCount*sizeof(Rectangle));
|
||||
|
||||
|
@ -311,7 +316,7 @@ Font LoadFont(const char *fileName)
|
|||
Font font = { 0 };
|
||||
|
||||
#if defined(SUPPORT_FILEFORMAT_TTF)
|
||||
if (IsFileExtension(fileName, ".ttf;.otf")) font = LoadFontEx(fileName, FONT_TTF_DEFAULT_SIZE, NULL, FONT_TTF_DEFAULT_NUMCHARS);
|
||||
if (IsFileExtension(fileName, ".ttf") || IsFileExtension(fileName, ".otf")) font = LoadFontEx(fileName, FONT_TTF_DEFAULT_SIZE, NULL, FONT_TTF_DEFAULT_NUMCHARS);
|
||||
else
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_FNT)
|
||||
|
@ -329,7 +334,11 @@ Font LoadFont(const char *fileName)
|
|||
TRACELOG(LOG_WARNING, "FONT: [%s] Failed to load font texture -> Using default font", fileName);
|
||||
font = GetFontDefault();
|
||||
}
|
||||
else SetTextureFilter(font.texture, TEXTURE_FILTER_POINT); // By default we set point filter (best performance)
|
||||
else
|
||||
{
|
||||
SetTextureFilter(font.texture, TEXTURE_FILTER_POINT); // By default we set point filter (best performance)
|
||||
TRACELOG(LOG_INFO, "FONT: Data loaded successfully (%i pixel size | %i glyphs)", FONT_TTF_DEFAULT_SIZE, FONT_TTF_DEFAULT_NUMCHARS);
|
||||
}
|
||||
|
||||
return font;
|
||||
}
|
||||
|
@ -515,7 +524,7 @@ Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int
|
|||
|
||||
UnloadImage(atlas);
|
||||
|
||||
// TRACELOG(LOG_INFO, "FONT: Font loaded successfully (%i glyphs)", font.glyphCount);
|
||||
TRACELOG(LOG_INFO, "FONT: Data loaded successfully (%i pixel size | %i glyphs)", font.baseSize, font.glyphCount);
|
||||
}
|
||||
else font = GetFontDefault();
|
||||
}
|
||||
|
@ -677,20 +686,20 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
|
|||
// NOTE 2: SDF font characters already contain an internal padding,
|
||||
// so image size would result bigger than default font type
|
||||
float requiredArea = 0;
|
||||
for (int i = 0; i < glyphCount; i++) requiredArea += ((chars[i].image.width + 2*padding)*(chars[i].image.height + 2*padding));
|
||||
float guessSize = sqrtf(requiredArea)*1.3f;
|
||||
int imageSize = (int)powf(2, ceilf(logf((float)guessSize)/logf(2))); // Calculate next POT
|
||||
for (int i = 0; i < glyphCount; i++) requiredArea += ((chars[i].image.width + 2*padding)*(fontSize + 2*padding));
|
||||
float guessSize = sqrtf(requiredArea)*1.4f;
|
||||
int imageSize = (int)powf(2, ceilf(logf((float)guessSize)/logf(2))); // Calculate next POT
|
||||
|
||||
atlas.width = imageSize; // Atlas bitmap width
|
||||
atlas.height = imageSize; // Atlas bitmap height
|
||||
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.mipmaps = 1;
|
||||
|
||||
// DEBUG: We can see padding in the generated image setting a gray background...
|
||||
//for (int i = 0; i < atlas.width*atlas.height; i++) ((unsigned char *)atlas.data)[i] = 100;
|
||||
|
||||
if (packMethod == 0) // Use basic packing algorythm
|
||||
if (packMethod == 0) // Use basic packing algorithm
|
||||
{
|
||||
int offsetX = padding;
|
||||
int offsetY = padding;
|
||||
|
@ -725,11 +734,23 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
|
|||
// height is bigger than fontSize, it could be up to (fontSize + 8)
|
||||
offsetY += (fontSize + 2*padding);
|
||||
|
||||
if (offsetY > (atlas.height - fontSize - padding)) break;
|
||||
if (offsetY > (atlas.height - fontSize - padding))
|
||||
{
|
||||
for(int j = i + 1; j < glyphCount; j++)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "FONT: Failed to package character (%i)", j);
|
||||
// make sure remaining recs contain valid data
|
||||
recs[j].x = 0;
|
||||
recs[j].y = 0;
|
||||
recs[j].width = 0;
|
||||
recs[j].height = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (packMethod == 1) // Use Skyline rect packing algorythm (stb_pack_rect)
|
||||
else if (packMethod == 1) // Use Skyline rect packing algorithm (stb_pack_rect)
|
||||
{
|
||||
stbrp_context *context = (stbrp_context *)RL_MALLOC(sizeof(*context));
|
||||
stbrp_node *nodes = (stbrp_node *)RL_MALLOC(glyphCount*sizeof(*nodes));
|
||||
|
@ -797,9 +818,12 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
|
|||
// Unload font glyphs info data (RAM)
|
||||
void UnloadFontData(GlyphInfo *glyphs, int glyphCount)
|
||||
{
|
||||
for (int i = 0; i < glyphCount; i++) UnloadImage(glyphs[i].image);
|
||||
if (glyphs != NULL)
|
||||
{
|
||||
for (int i = 0; i < glyphCount; i++) UnloadImage(glyphs[i].image);
|
||||
|
||||
RL_FREE(glyphs);
|
||||
RL_FREE(glyphs);
|
||||
}
|
||||
}
|
||||
|
||||
// Unload Font from GPU memory (VRAM)
|
||||
|
@ -816,15 +840,170 @@ void UnloadFont(Font font)
|
|||
}
|
||||
}
|
||||
|
||||
// Export font as code file, returns true on success
|
||||
bool ExportFontAsCode(Font font, const char *fileName)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
#ifndef TEXT_BYTES_PER_LINE
|
||||
#define TEXT_BYTES_PER_LINE 20
|
||||
#endif
|
||||
|
||||
#define MAX_FONT_DATA_SIZE 1024*1024 // 1 MB
|
||||
|
||||
// Get file name from path
|
||||
char fileNamePascal[256] = { 0 };
|
||||
strcpy(fileNamePascal, TextToPascal(GetFileNameWithoutExt(fileName)));
|
||||
|
||||
// NOTE: Text data buffer size is estimated considering image data size in bytes
|
||||
// and requiring 6 char bytes for every byte: "0x00, "
|
||||
char *txtData = (char *)RL_CALLOC(MAX_FONT_DATA_SIZE, sizeof(char));
|
||||
|
||||
int byteCount = 0;
|
||||
byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// FontAsCode exporter v1.0 - Font data exported as an array of bytes //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// more info and bugs-report: github.com/raysan5/raylib //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// feedback and support: ray[at]raylib.com //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// Copyright (c) 2018-2022 Ramon Santamaria (@raysan5) //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// ---------------------------------------------------------------------------------- //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// TODO: Fill the information and license of the exported font here: //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// Font name: .... //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// Font creator: .... //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// Font LICENSE: .... //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n\n");
|
||||
|
||||
// Support font export and initialization
|
||||
// NOTE: This mechanism is highly coupled to raylib
|
||||
Image image = LoadImageFromTexture(font.texture);
|
||||
if (image.format != PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA) TRACELOG(LOG_WARNING, "Font export as code: Font image format is not GRAY+ALPHA!");
|
||||
int imageDataSize = GetPixelDataSize(image.width, image.height, image.format);
|
||||
|
||||
// Image data is usually GRAYSCALE + ALPHA and can be reduced to GRAYSCALE
|
||||
//ImageFormat(&image, PIXELFORMAT_UNCOMPRESSED_GRAYSCALE);
|
||||
|
||||
#define SUPPORT_COMPRESSED_FONT_ATLAS
|
||||
#if defined(SUPPORT_COMPRESSED_FONT_ATLAS)
|
||||
// WARNING: Data is compressed using raylib CompressData() DEFLATE,
|
||||
// it requires to be decompressed with raylib DecompressData(), that requires
|
||||
// compiling raylib with SUPPORT_COMPRESSION_API config flag enabled
|
||||
|
||||
// Compress font image data
|
||||
int compDataSize = 0;
|
||||
unsigned char *compData = CompressData(image.data, imageDataSize, &compDataSize);
|
||||
|
||||
// Save font image data (compressed)
|
||||
byteCount += sprintf(txtData + byteCount, "#define COMPRESSED_DATA_SIZE_FONT_%s %i\n\n", TextToUpper(fileNamePascal), compDataSize);
|
||||
byteCount += sprintf(txtData + byteCount, "// Font image pixels data compressed (DEFLATE)\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// NOTE: Original pixel data simplified to GRAYSCALE\n");
|
||||
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]);
|
||||
byteCount += sprintf(txtData + byteCount, "0x%02x };\n\n", compData[compDataSize - 1]);
|
||||
MemFree(compData);
|
||||
#else
|
||||
// Save font image data (uncompressed)
|
||||
byteCount += sprintf(txtData + byteCount, "// Font image pixels data\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// NOTE: 2 bytes per pixel, GRAY + ALPHA channels\n");
|
||||
byteCount += sprintf(txtData + byteCount, "static unsigned char fontImageData_%s[%i] = { ", fileNamePascal, imageDataSize);
|
||||
for (int i = 0; i < imageDataSize - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%02x,\n " : "0x%02x, "), ((unsigned char *)imFont.data)[i]);
|
||||
byteCount += sprintf(txtData + byteCount, "0x%02x };\n\n", ((unsigned char *)imFont.data)[imageDataSize - 1]);
|
||||
#endif
|
||||
|
||||
// Save font recs data
|
||||
byteCount += sprintf(txtData + byteCount, "// Font characters rectangles data\n");
|
||||
byteCount += sprintf(txtData + byteCount, "static const Rectangle fontRecs_%s[%i] = {\n", fileNamePascal, font.glyphCount);
|
||||
for (int i = 0; i < font.glyphCount; i++)
|
||||
{
|
||||
byteCount += sprintf(txtData + byteCount, " { %1.0f, %1.0f, %1.0f , %1.0f },\n", font.recs[i].x, font.recs[i].y, font.recs[i].width, font.recs[i].height);
|
||||
}
|
||||
byteCount += sprintf(txtData + byteCount, "};\n\n");
|
||||
|
||||
// Save font glyphs data
|
||||
// NOTE: Glyphs image data not saved (grayscale pixels),
|
||||
// it could be generated from image and recs
|
||||
byteCount += sprintf(txtData + byteCount, "// Font glyphs info data\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// NOTE: No glyphs.image data provided\n");
|
||||
byteCount += sprintf(txtData + byteCount, "static const GlyphInfo fontGlyphs_%s[%i] = {\n", fileNamePascal, font.glyphCount);
|
||||
for (int i = 0; i < font.glyphCount; i++)
|
||||
{
|
||||
byteCount += sprintf(txtData + byteCount, " { %i, %i, %i, %i, { 0 }},\n", font.glyphs[i].value, font.glyphs[i].offsetX, font.glyphs[i].offsetY, font.glyphs[i].advanceX);
|
||||
}
|
||||
byteCount += sprintf(txtData + byteCount, "};\n\n");
|
||||
|
||||
// Custom font loading function
|
||||
byteCount += sprintf(txtData + byteCount, "// Font loading function: %s\n", fileNamePascal);
|
||||
byteCount += sprintf(txtData + byteCount, "static Font LoadFont_%s(void)\n{\n", fileNamePascal);
|
||||
byteCount += sprintf(txtData + byteCount, " Font font = { 0 };\n\n");
|
||||
byteCount += sprintf(txtData + byteCount, " font.baseSize = %i;\n", font.baseSize);
|
||||
byteCount += sprintf(txtData + byteCount, " font.glyphCount = %i;\n", font.glyphCount);
|
||||
byteCount += sprintf(txtData + byteCount, " font.glyphPadding = %i;\n\n", font.glyphPadding);
|
||||
byteCount += sprintf(txtData + byteCount, " // Custom font loading\n");
|
||||
#if defined(SUPPORT_COMPRESSED_FONT_ATLAS)
|
||||
byteCount += sprintf(txtData + byteCount, " // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function\n");
|
||||
byteCount += sprintf(txtData + byteCount, " int fontDataSize_%s = 0;\n", fileNamePascal);
|
||||
byteCount += sprintf(txtData + byteCount, " unsigned char *data = DecompressData(fontData_%s, COMPRESSED_DATA_SIZE_FONT_%s, &fontDataSize_%s);\n", fileNamePascal, TextToUpper(fileNamePascal), fileNamePascal);
|
||||
byteCount += sprintf(txtData + byteCount, " Image imFont = { data, %i, %i, 1, %i };\n\n", image.width, image.height, image.format);
|
||||
#else
|
||||
byteCount += sprintf(txtData + byteCount, " Image imFont = { fontImageData_%s, %i, %i, 1, %i };\n\n", styleName, image.width, image.height, image.format);
|
||||
#endif
|
||||
byteCount += sprintf(txtData + byteCount, " // Load texture from image\n");
|
||||
byteCount += sprintf(txtData + byteCount, " font.texture = LoadTextureFromImage(imFont);\n");
|
||||
#if defined(SUPPORT_COMPRESSED_FONT_ATLAS)
|
||||
byteCount += sprintf(txtData + byteCount, " UnloadImage(imFont); // Uncompressed data can be unloaded from memory\n\n");
|
||||
#endif
|
||||
// We have two possible mechanisms to assign font.recs and font.glyphs data,
|
||||
// that data is already available as global arrays, we two options to assign that data:
|
||||
// - 1. Data copy. This option consumes more memory and Font MUST be unloaded by user, requiring additional code.
|
||||
// - 2. Data assignment. This option consumes less memory and Font MUST NOT be unloaded by user because data is on protected DATA segment
|
||||
//#define SUPPORT_FONT_DATA_COPY
|
||||
#if defined(SUPPORT_FONT_DATA_COPY)
|
||||
byteCount += sprintf(txtData + byteCount, " // Copy glyph recs data from global fontRecs\n");
|
||||
byteCount += sprintf(txtData + byteCount, " // NOTE: Required to avoid issues if trying to free font\n");
|
||||
byteCount += sprintf(txtData + byteCount, " font.recs = (Rectangle *)malloc(font.glyphCount*sizeof(Rectangle));\n");
|
||||
byteCount += sprintf(txtData + byteCount, " memcpy(font.recs, fontRecs_%s, font.glyphCount*sizeof(Rectangle));\n\n", fileNamePascal);
|
||||
|
||||
byteCount += sprintf(txtData + byteCount, " // Copy font glyph info data from global fontChars\n");
|
||||
byteCount += sprintf(txtData + byteCount, " // NOTE: Required to avoid issues if trying to free font\n");
|
||||
byteCount += sprintf(txtData + byteCount, " font.glyphs = (GlyphInfo *)malloc(font.glyphCount*sizeof(GlyphInfo));\n");
|
||||
byteCount += sprintf(txtData + byteCount, " memcpy(font.glyphs, fontGlyphs_%s, font.glyphCount*sizeof(GlyphInfo));\n\n", fileNamePascal);
|
||||
#else
|
||||
byteCount += sprintf(txtData + byteCount, " // Assign glyph recs and info data directly\n");
|
||||
byteCount += sprintf(txtData + byteCount, " // WARNING: This font data must not be unloaded\n");
|
||||
byteCount += sprintf(txtData + byteCount, " font.recs = fontRecs_%s;\n", fileNamePascal);
|
||||
byteCount += sprintf(txtData + byteCount, " font.glyphs = fontGlyphs_%s;\n\n", fileNamePascal);
|
||||
#endif
|
||||
byteCount += sprintf(txtData + byteCount, " return font;\n");
|
||||
byteCount += sprintf(txtData + byteCount, "}\n");
|
||||
|
||||
UnloadImage(image);
|
||||
|
||||
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
||||
success = SaveFileText(fileName, txtData);
|
||||
|
||||
RL_FREE(txtData);
|
||||
|
||||
if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Font as code exported successfully", fileName);
|
||||
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export font as code", fileName);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
// Draw current FPS
|
||||
// NOTE: Uses default font
|
||||
void DrawFPS(int posX, int posY)
|
||||
{
|
||||
Color color = LIME; // good fps
|
||||
Color color = LIME; // Good FPS
|
||||
int fps = GetFPS();
|
||||
|
||||
if (fps < 30 && fps >= 15) color = ORANGE; // warning FPS
|
||||
else if (fps < 15) color = RED; // bad FPS
|
||||
if ((fps < 30) && (fps >= 15)) color = ORANGE; // Warning FPS
|
||||
else if (fps < 15) color = RED; // Low FPS
|
||||
|
||||
DrawText(TextFormat("%2i FPS", GetFPS()), posX, posY, 20, color);
|
||||
}
|
||||
|
@ -875,7 +1054,7 @@ void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, f
|
|||
{
|
||||
// NOTE: Fixed line spacing of 1.5 line-height
|
||||
// TODO: Support custom line spacing defined by user
|
||||
textOffsetY += (int)((font.baseSize + font.baseSize/2)*scaleFactor);
|
||||
textOffsetY += (int)((font.baseSize + font.baseSize/2.0f)*scaleFactor);
|
||||
textOffsetX = 0.0f;
|
||||
}
|
||||
else
|
||||
|
@ -931,10 +1110,42 @@ void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSiz
|
|||
DrawTexturePro(font.texture, srcRec, dstRec, (Vector2){ 0, 0 }, 0.0f, tint);
|
||||
}
|
||||
|
||||
// Draw multiple character (codepoints)
|
||||
void DrawTextCodepoints(Font font, const int *codepoints, int count, Vector2 position, float fontSize, float spacing, Color tint)
|
||||
{
|
||||
int textOffsetY = 0; // Offset between lines (on line break '\n')
|
||||
float textOffsetX = 0.0f; // Offset X to next character to draw
|
||||
|
||||
float scaleFactor = fontSize/font.baseSize; // Character quad scaling factor
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
int index = GetGlyphIndex(font, codepoints[i]);
|
||||
|
||||
if (codepoints[i] == '\n')
|
||||
{
|
||||
// NOTE: Fixed line spacing of 1.5 line-height
|
||||
// TODO: Support custom line spacing defined by user
|
||||
textOffsetY += (int)((font.baseSize + font.baseSize/2.0f)*scaleFactor);
|
||||
textOffsetX = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((codepoints[i] != ' ') && (codepoints[i] != '\t'))
|
||||
{
|
||||
DrawTextCodepoint(font, codepoints[i], (Vector2){ position.x + textOffsetX, position.y + textOffsetY }, fontSize, tint);
|
||||
}
|
||||
|
||||
if (font.glyphs[index].advanceX == 0) textOffsetX += ((float)font.recs[index].width*scaleFactor + spacing);
|
||||
else textOffsetX += ((float)font.glyphs[index].advanceX*scaleFactor + spacing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Measure string width for default font
|
||||
int MeasureText(const char *text, int fontSize)
|
||||
{
|
||||
Vector2 vec = { 0.0f, 0.0f };
|
||||
Vector2 textSize = { 0.0f, 0.0f };
|
||||
|
||||
// Check if default font has been loaded
|
||||
if (GetFontDefault().texture.id != 0)
|
||||
|
@ -943,15 +1154,19 @@ int MeasureText(const char *text, int fontSize)
|
|||
if (fontSize < defaultFontSize) fontSize = defaultFontSize;
|
||||
int spacing = fontSize/defaultFontSize;
|
||||
|
||||
vec = MeasureTextEx(GetFontDefault(), text, (float)fontSize, (float)spacing);
|
||||
textSize = MeasureTextEx(GetFontDefault(), text, (float)fontSize, (float)spacing);
|
||||
}
|
||||
|
||||
return (int)vec.x;
|
||||
return (int)textSize.x;
|
||||
}
|
||||
|
||||
// Measure string size for Font
|
||||
Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing)
|
||||
{
|
||||
Vector2 textSize = { 0 };
|
||||
|
||||
if ((font.texture.id == 0) || (text == NULL)) return textSize;
|
||||
|
||||
int size = TextLength(text); // Get size in bytes of text
|
||||
int tempByteCounter = 0; // Used to count longer text line num chars
|
||||
int byteCounter = 0;
|
||||
|
@ -996,11 +1211,10 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
|
|||
|
||||
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
|
||||
|
||||
Vector2 vec = { 0 };
|
||||
vec.x = tempTextWidth*scaleFactor + (float)((tempByteCounter - 1)*spacing); // Adds chars spacing to measure
|
||||
vec.y = textHeight*scaleFactor;
|
||||
textSize.x = tempTextWidth*scaleFactor + (float)((tempByteCounter - 1)*spacing); // Adds chars spacing to measure
|
||||
textSize.y = textHeight*scaleFactor;
|
||||
|
||||
return vec;
|
||||
return textSize;
|
||||
}
|
||||
|
||||
// Get index position for a unicode character on font
|
||||
|
@ -1179,7 +1393,7 @@ const char *TextSubtext(const char *text, int position, int length)
|
|||
|
||||
// Replace text string
|
||||
// REQUIRES: strlen(), strstr(), strncpy(), strcpy()
|
||||
// WARNING: Returned buffer must be freed by the user (if return != NULL)
|
||||
// WARNING: Allocated memory must be manually freed
|
||||
char *TextReplace(char *text, const char *replace, const char *by)
|
||||
{
|
||||
// Sanity checks and initialization
|
||||
|
@ -1228,7 +1442,7 @@ char *TextReplace(char *text, const char *replace, const char *by)
|
|||
}
|
||||
|
||||
// Insert text in a specific position, moves all text forward
|
||||
// WARNING: Allocated memory should be manually freed
|
||||
// WARNING: Allocated memory must be manually freed
|
||||
char *TextInsert(const char *text, const char *insert, int position)
|
||||
{
|
||||
int textLen = TextLength(text);
|
||||
|
@ -1412,8 +1626,8 @@ const char *TextToPascal(const char *text)
|
|||
|
||||
// Encode text codepoint into UTF-8 text
|
||||
// REQUIRES: memcpy()
|
||||
// WARNING: Allocated memory should be manually freed
|
||||
char *TextCodepointsToUTF8(int *codepoints, int length)
|
||||
// WARNING: Allocated memory must be manually freed
|
||||
char *TextCodepointsToUTF8(const int *codepoints, int length)
|
||||
{
|
||||
// We allocate enough memory fo fit all possible codepoints
|
||||
// NOTE: 5 bytes for every codepoint should be enough
|
||||
|
@ -1593,7 +1807,7 @@ int GetCodepoint(const char *text, int *bytesProcessed)
|
|||
if (((octet == 0xe0) && !((octet1 >= 0xa0) && (octet1 <= 0xbf))) ||
|
||||
((octet == 0xed) && !((octet1 >= 0x80) && (octet1 <= 0x9f)))) { *bytesProcessed = 2; return code; }
|
||||
|
||||
if ((octet >= 0xe0) && (0 <= 0xef))
|
||||
if ((octet >= 0xe0) && (octet <= 0xef))
|
||||
{
|
||||
code = ((octet & 0xf) << 12) | ((octet1 & 0x3f) << 6) | (octet2 & 0x3f);
|
||||
*bytesProcessed = 3;
|
||||
|
@ -1795,3 +2009,5 @@ static Font LoadBMFont(const char *fileName)
|
|||
return font;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // SUPPORT_MODULE_RTEXT
|
||||
|
|
|
@ -4,11 +4,15 @@
|
|||
*
|
||||
* CONFIGURATION:
|
||||
*
|
||||
* #define SUPPORT_MODULE_RTEXTURES
|
||||
* rtextures module is included in the build
|
||||
*
|
||||
* #define SUPPORT_FILEFORMAT_BMP
|
||||
* #define SUPPORT_FILEFORMAT_PNG
|
||||
* #define SUPPORT_FILEFORMAT_TGA
|
||||
* #define SUPPORT_FILEFORMAT_JPG
|
||||
* #define SUPPORT_FILEFORMAT_GIF
|
||||
* #define SUPPORT_FILEFORMAT_QOI
|
||||
* #define SUPPORT_FILEFORMAT_PSD
|
||||
* #define SUPPORT_FILEFORMAT_PIC
|
||||
* #define SUPPORT_FILEFORMAT_HDR
|
||||
|
@ -33,12 +37,12 @@
|
|||
* DEPENDENCIES:
|
||||
* stb_image - Multiple image formats loading (JPEG, PNG, BMP, TGA, PSD, GIF, PIC)
|
||||
* NOTE: stb_image has been slightly modified to support Android platform.
|
||||
* stb_image_resize - Multiple image resize algorythms
|
||||
* stb_image_resize - Multiple image resize algorithms
|
||||
*
|
||||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2013-2021 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2013-2022 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.
|
||||
|
@ -64,11 +68,13 @@
|
|||
#include "config.h" // Defines module configuration flags
|
||||
#endif
|
||||
|
||||
#if defined(SUPPORT_MODULE_RTEXTURES)
|
||||
|
||||
#include "utils.h" // Required for: TRACELOG() and fopen() Android mapping
|
||||
#include "rlgl.h" // OpenGL abstraction layer to OpenGL 1.1, 3.3 or ES2
|
||||
|
||||
#include <stdlib.h> // Required for: malloc(), free()
|
||||
#include <string.h> // Required for: strlen() [Used in ImageTextEx()]
|
||||
#include <string.h> // Required for: strlen() [Used in ImageTextEx()], strcmp() [Used in LoadImageFromMemory()]
|
||||
#include <math.h> // Required for: fabsf()
|
||||
#include <stdio.h> // Required for: sprintf() [Used in ExportImageAsCode()]
|
||||
|
||||
|
@ -124,6 +130,14 @@
|
|||
// NOTE: Used to read image data (multiple formats support)
|
||||
#endif
|
||||
|
||||
#if defined(SUPPORT_FILEFORMAT_QOI)
|
||||
#define QOI_MALLOC RL_MALLOC
|
||||
#define QOI_FREE RL_FREE
|
||||
|
||||
#define QOI_IMPLEMENTATION
|
||||
#include "external/qoi.h"
|
||||
#endif
|
||||
|
||||
#if defined(SUPPORT_IMAGE_EXPORT)
|
||||
#define STBIW_MALLOC RL_MALLOC
|
||||
#define STBIW_FREE RL_FREE
|
||||
|
@ -202,7 +216,8 @@ Image LoadImage(const char *fileName)
|
|||
defined(SUPPORT_FILEFORMAT_PIC) || \
|
||||
defined(SUPPORT_FILEFORMAT_HDR) || \
|
||||
defined(SUPPORT_FILEFORMAT_PSD)
|
||||
#define STBI_REQUIRED
|
||||
|
||||
#define STBI_REQUIRED
|
||||
#endif
|
||||
|
||||
// Loading file to memory
|
||||
|
@ -286,36 +301,32 @@ Image LoadImageAnim(const char *fileName, int *frames)
|
|||
}
|
||||
|
||||
// Load image from memory buffer, fileType refers to extension: i.e. ".png"
|
||||
// WARNING: File extension must be provided in lower-case
|
||||
Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, int dataSize)
|
||||
{
|
||||
Image image = { 0 };
|
||||
|
||||
char fileExtLower[16] = { 0 };
|
||||
strcpy(fileExtLower, TextToLower(fileType));
|
||||
|
||||
#if defined(SUPPORT_FILEFORMAT_PNG)
|
||||
if ((TextIsEqual(fileExtLower, ".png"))
|
||||
#else
|
||||
if ((false)
|
||||
#if defined(SUPPORT_FILEFORMAT_PNG)
|
||||
|| (strcmp(fileType, ".png") == 0)
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_BMP)
|
||||
|| (TextIsEqual(fileExtLower, ".bmp"))
|
||||
|| (strcmp(fileType, ".bmp") == 0)
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_TGA)
|
||||
|| (TextIsEqual(fileExtLower, ".tga"))
|
||||
|| (strcmp(fileType, ".tga") == 0)
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_JPG)
|
||||
|| (TextIsEqual(fileExtLower, ".jpg") ||
|
||||
TextIsEqual(fileExtLower, ".jpeg"))
|
||||
|| ((strcmp(fileType, ".jpg") == 0) || (strcmp(fileType, ".jpeg") == 0))
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_GIF)
|
||||
|| (TextIsEqual(fileExtLower, ".gif"))
|
||||
|| (strcmp(fileType, ".gif") == 0)
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_PIC)
|
||||
|| (TextIsEqual(fileExtLower, ".pic"))
|
||||
|| (strcmp(fileType, ".pic") == 0)
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_PSD)
|
||||
|| (TextIsEqual(fileExtLower, ".psd"))
|
||||
|| (strcmp(fileType, ".psd") == 0)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
|
@ -340,7 +351,7 @@ Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, i
|
|||
#endif
|
||||
}
|
||||
#if defined(SUPPORT_FILEFORMAT_HDR)
|
||||
else if (TextIsEqual(fileExtLower, ".hdr"))
|
||||
else if (strcmp(fileType, ".hdr") == 0)
|
||||
{
|
||||
#if defined(STBI_REQUIRED)
|
||||
if (fileData != NULL)
|
||||
|
@ -362,20 +373,31 @@ Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, i
|
|||
#endif
|
||||
}
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_QOI)
|
||||
else if (strcmp(fileType, ".qoi") == 0)
|
||||
{
|
||||
qoi_desc desc = { 0 };
|
||||
image.data = qoi_decode(fileData, dataSize, &desc, 4);
|
||||
image.width = desc.width;
|
||||
image.height = desc.height;
|
||||
image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
|
||||
image.mipmaps = 1;
|
||||
}
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_DDS)
|
||||
else if (TextIsEqual(fileExtLower, ".dds")) image = LoadDDS(fileData, dataSize);
|
||||
else if (strcmp(fileType, ".dds") == 0) image = LoadDDS(fileData, dataSize);
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_PKM)
|
||||
else if (TextIsEqual(fileExtLower, ".pkm")) image = LoadPKM(fileData, dataSize);
|
||||
else if (strcmp(fileType, ".pkm") == 0) image = LoadPKM(fileData, dataSize);
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_KTX)
|
||||
else if (TextIsEqual(fileExtLower, ".ktx")) image = LoadKTX(fileData, dataSize);
|
||||
else if (strcmp(fileType, ".ktx") == 0) image = LoadKTX(fileData, dataSize);
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_PVR)
|
||||
else if (TextIsEqual(fileExtLower, ".pvr")) image = LoadPVR(fileData, dataSize);
|
||||
else if (strcmp(fileType, ".pvr") == 0) image = LoadPVR(fileData, dataSize);
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_ASTC)
|
||||
else if (TextIsEqual(fileExtLower, ".astc")) image = LoadASTC(fileData, dataSize);
|
||||
else if (strcmp(fileType, ".astc") == 0) image = LoadASTC(fileData, dataSize);
|
||||
#endif
|
||||
else TRACELOG(LOG_WARNING, "IMAGE: Data format not supported");
|
||||
|
||||
|
@ -477,7 +499,28 @@ bool ExportImage(Image image, const char *fileName)
|
|||
else if (IsFileExtension(fileName, ".tga")) success = stbi_write_tga(fileName, image.width, image.height, channels, imgData);
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_JPG)
|
||||
else if (IsFileExtension(fileName, ".jpg")) success = stbi_write_jpg(fileName, image.width, image.height, channels, imgData, 90); // JPG quality: between 1 and 100
|
||||
else if (IsFileExtension(fileName, ".jpg") ||
|
||||
IsFileExtension(fileName, ".jpeg")) success = stbi_write_jpg(fileName, image.width, image.height, channels, imgData, 90); // JPG quality: between 1 and 100
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_QOI)
|
||||
else if (IsFileExtension(fileName, ".qoi"))
|
||||
{
|
||||
channels = 0;
|
||||
if (image.format == PIXELFORMAT_UNCOMPRESSED_R8G8B8) channels = 3;
|
||||
else if (image.format == PIXELFORMAT_UNCOMPRESSED_R8G8B8A8) channels = 4;
|
||||
else TRACELOG(LOG_WARNING, "IMAGE: Image pixel format must be R8G8B8 or R8G8B8A8");
|
||||
|
||||
if ((channels == 3) || (channels == 4))
|
||||
{
|
||||
qoi_desc desc = { 0 };
|
||||
desc.width = image.width;
|
||||
desc.height = image.height;
|
||||
desc.channels = channels;
|
||||
desc.colorspace = QOI_SRGB;
|
||||
|
||||
success = qoi_write(fileName, imgData, &desc);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_KTX)
|
||||
else if (IsFileExtension(fileName, ".ktx")) success = SaveKTX(image, fileName);
|
||||
|
@ -523,7 +566,7 @@ bool ExportImageAsCode(Image image, const char *fileName)
|
|||
byteCount += sprintf(txtData + byteCount, "// more info and bugs-report: github.com/raysan5/raylib //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// feedback and support: ray[at]raylib.com //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// Copyright (c) 2018-2021 Ramon Santamaria (@raysan5) //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// Copyright (c) 2018-2022 Ramon Santamaria (@raysan5) //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n\n");
|
||||
|
||||
|
@ -549,8 +592,8 @@ bool ExportImageAsCode(Image image, const char *fileName)
|
|||
|
||||
#endif // SUPPORT_IMAGE_EXPORT
|
||||
|
||||
if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Image exported successfully", fileName);
|
||||
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export image", fileName);
|
||||
if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Image as code exported successfully", fileName);
|
||||
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export image as code", fileName);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
@ -732,7 +775,7 @@ Image GenImageCellular(int width, int height, int tileSize)
|
|||
{
|
||||
int y = (i/seedsPerRow)*tileSize + GetRandomValue(0, tileSize - 1);
|
||||
int x = (i%seedsPerRow)*tileSize + GetRandomValue(0, tileSize - 1);
|
||||
seeds[i] = (Vector2){ (float)x, (float)y};
|
||||
seeds[i] = (Vector2){ (float)x, (float)y };
|
||||
}
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
|
@ -743,7 +786,7 @@ Image GenImageCellular(int width, int height, int tileSize)
|
|||
{
|
||||
int tileX = x/tileSize;
|
||||
|
||||
float minDistance = (float)strtod("Inf", NULL);
|
||||
float minDistance = 65536.0f; //(float)strtod("Inf", NULL);
|
||||
|
||||
// Check all adjacent tiles
|
||||
for (int i = -1; i < 2; i++)
|
||||
|
@ -832,11 +875,11 @@ Image ImageFromImage(Image image, Rectangle rec)
|
|||
|
||||
result.width = (int)rec.width;
|
||||
result.height = (int)rec.height;
|
||||
result.data = RL_CALLOC((int)(rec.width*rec.height)*bytesPerPixel, 1);
|
||||
result.data = RL_CALLOC((int)rec.width*(int)rec.height*bytesPerPixel, 1);
|
||||
result.format = image.format;
|
||||
result.mipmaps = 1;
|
||||
|
||||
for (int y = 0; y < rec.height; y++)
|
||||
for (int y = 0; y < (int)rec.height; y++)
|
||||
{
|
||||
memcpy(((unsigned char *)result.data) + y*(int)rec.width*bytesPerPixel, ((unsigned char *)image.data) + ((y + (int)rec.y)*image.width + (int)rec.x)*bytesPerPixel, (int)rec.width*bytesPerPixel);
|
||||
}
|
||||
|
@ -1092,35 +1135,41 @@ void ImageToPOT(Image *image, Color fill)
|
|||
// Create an image from text (default font)
|
||||
Image ImageText(const char *text, int fontSize, Color color)
|
||||
{
|
||||
Image imText = { 0 };
|
||||
#if defined(SUPPORT_MODULE_RTEXT)
|
||||
int defaultFontSize = 10; // Default Font chars height in pixel
|
||||
if (fontSize < defaultFontSize) fontSize = defaultFontSize;
|
||||
int spacing = fontSize/defaultFontSize;
|
||||
|
||||
Image imText = ImageTextEx(GetFontDefault(), text, (float)fontSize, (float)spacing, color);
|
||||
|
||||
imText = ImageTextEx(GetFontDefault(), text, (float)fontSize, (float)spacing, color); // WARNING: Module required: rtext
|
||||
#else
|
||||
imText = GenImageColor(200, 60, BLACK); // Generating placeholder black image rectangle
|
||||
TRACELOG(LOG_WARNING, "IMAGE: ImageTextEx() requires module: rtext");
|
||||
#endif
|
||||
return imText;
|
||||
}
|
||||
|
||||
// Create an image from text (custom sprite font)
|
||||
Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Color tint)
|
||||
{
|
||||
Image imText = { 0 };
|
||||
#if defined(SUPPORT_MODULE_RTEXT)
|
||||
int size = (int)strlen(text); // Get size in bytes of text
|
||||
|
||||
int textOffsetX = 0; // Image drawing position X
|
||||
int textOffsetY = 0; // Offset between lines (on line break '\n')
|
||||
|
||||
// NOTE: Text image is generated at font base size, later scaled to desired font size
|
||||
Vector2 imSize = MeasureTextEx(font, text, (float)font.baseSize, spacing);
|
||||
Vector2 imSize = MeasureTextEx(font, text, (float)font.baseSize, spacing); // WARNING: Module required: rtext
|
||||
|
||||
// Create image to store text
|
||||
Image imText = GenImageColor((int)imSize.x, (int)imSize.y, BLANK);
|
||||
imText = GenImageColor((int)imSize.x, (int)imSize.y, BLANK);
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
// Get next codepoint from byte string and glyph index in font
|
||||
int codepointByteCount = 0;
|
||||
int codepoint = GetCodepoint(&text[i], &codepointByteCount);
|
||||
int index = GetGlyphIndex(font, codepoint);
|
||||
int codepoint = GetCodepoint(&text[i], &codepointByteCount); // WARNING: Module required: rtext
|
||||
int index = GetGlyphIndex(font, codepoint); // WARNING: Module required: rtext
|
||||
|
||||
// NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
|
||||
// but we need to draw all of the bad bytes using the '?' symbol moving one byte
|
||||
|
@ -1155,10 +1204,14 @@ Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Co
|
|||
TRACELOG(LOG_INFO, "IMAGE: Text scaled by factor: %f", scaleFactor);
|
||||
|
||||
// Using nearest-neighbor scaling algorithm for default font
|
||||
// WARNING: Module required: rtext
|
||||
if (font.texture.id == GetFontDefault().texture.id) ImageResizeNN(&imText, (int)(imSize.x*scaleFactor), (int)(imSize.y*scaleFactor));
|
||||
else ImageResize(&imText, (int)(imSize.x*scaleFactor), (int)(imSize.y*scaleFactor));
|
||||
}
|
||||
|
||||
#else
|
||||
imText = GenImageColor(200, 60, BLACK); // Generating placeholder black image rectangle
|
||||
TRACELOG(LOG_WARNING, "IMAGE: ImageTextEx() requires module: rtext");
|
||||
#endif
|
||||
return imText;
|
||||
}
|
||||
|
||||
|
@ -1361,10 +1414,12 @@ void ImageResize(Image *image, int newWidth, int newHeight)
|
|||
// Security check to avoid program crash
|
||||
if ((image->data == NULL) || (image->width == 0) || (image->height == 0)) return;
|
||||
|
||||
bool fastPath = true;
|
||||
if ((image->format != PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) && (image->format != PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA) && (image->format != PIXELFORMAT_UNCOMPRESSED_R8G8B8) && (image->format != PIXELFORMAT_UNCOMPRESSED_R8G8B8A8)) fastPath = true;
|
||||
|
||||
if (fastPath)
|
||||
// Check if we can use a fast path on image scaling
|
||||
// It can be for 8 bit per channel images with 1 to 4 channels per pixel
|
||||
if ((image->format == PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) ||
|
||||
(image->format == PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA) ||
|
||||
(image->format == PIXELFORMAT_UNCOMPRESSED_R8G8B8) ||
|
||||
(image->format == PIXELFORMAT_UNCOMPRESSED_R8G8B8A8))
|
||||
{
|
||||
int bytesPerPixel = GetPixelDataSize(1, 1, image->format);
|
||||
unsigned char *output = (unsigned char *)RL_MALLOC(newWidth*newHeight*bytesPerPixel);
|
||||
|
@ -1836,10 +1891,10 @@ void ImageColorTint(Image *image, Color color)
|
|||
unsigned char b = (unsigned char)(((float)pixels[index].b/255*cB)*255.0f);
|
||||
unsigned char a = (unsigned char)(((float)pixels[index].a/255*cA)*255.0f);
|
||||
|
||||
pixels[y*image->width + x].r = r;
|
||||
pixels[y*image->width + x].g = g;
|
||||
pixels[y*image->width + x].b = b;
|
||||
pixels[y*image->width + x].a = a;
|
||||
pixels[index].r = r;
|
||||
pixels[index].g = g;
|
||||
pixels[index].b = b;
|
||||
pixels[index].a = a;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1905,25 +1960,25 @@ void ImageColorContrast(Image *image, float contrast)
|
|||
for (int x = 0; x < image->width; x++)
|
||||
{
|
||||
float pR = (float)pixels[y*image->width + x].r/255.0f;
|
||||
pR -= 0.5;
|
||||
pR -= 0.5f;
|
||||
pR *= contrast;
|
||||
pR += 0.5;
|
||||
pR += 0.5f;
|
||||
pR *= 255;
|
||||
if (pR < 0) pR = 0;
|
||||
if (pR > 255) pR = 255;
|
||||
|
||||
float pG = (float)pixels[y*image->width + x].g/255.0f;
|
||||
pG -= 0.5;
|
||||
pG -= 0.5f;
|
||||
pG *= contrast;
|
||||
pG += 0.5;
|
||||
pG += 0.5f;
|
||||
pG *= 255;
|
||||
if (pG < 0) pG = 0;
|
||||
if (pG > 255) pG = 255;
|
||||
|
||||
float pB = (float)pixels[y*image->width + x].b/255.0f;
|
||||
pB -= 0.5;
|
||||
pB -= 0.5f;
|
||||
pB *= contrast;
|
||||
pB += 0.5;
|
||||
pB += 0.5f;
|
||||
pB *= 255;
|
||||
if (pB < 0) pB = 0;
|
||||
if (pB > 255) pB = 255;
|
||||
|
@ -2358,7 +2413,20 @@ Color GetImageColor(Image image, int x, int y)
|
|||
// Clear image background with given color
|
||||
void ImageClearBackground(Image *dst, Color color)
|
||||
{
|
||||
for (int i = 0; i < dst->width*dst->height; ++i) ImageDrawPixel(dst, i%dst->width, i/dst->width, color);
|
||||
// Security check to avoid program crash
|
||||
if ((dst->data == NULL) || (dst->width == 0) || (dst->height == 0)) return;
|
||||
|
||||
// Fill in first pixel based on image format
|
||||
ImageDrawPixel(dst, 0, 0, color);
|
||||
|
||||
unsigned char *pSrcPixel = (unsigned char *)dst->data;
|
||||
int bytesPerPixel = GetPixelDataSize(1, 1, dst->format);
|
||||
|
||||
// Repeat the first pixel data throughout the image
|
||||
for (int i = 1; i < dst->width * dst->height; i++)
|
||||
{
|
||||
memcpy(pSrcPixel + i * bytesPerPixel, pSrcPixel, bytesPerPixel);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw pixel within an image
|
||||
|
@ -2632,13 +2700,21 @@ void ImageDrawRectangleRec(Image *dst, Rectangle rec, Color color)
|
|||
int ey = sy + (int)rec.height;
|
||||
|
||||
int sx = (int)rec.x;
|
||||
int ex = sx + (int)rec.width;
|
||||
|
||||
int bytesPerPixel = GetPixelDataSize(1, 1, dst->format);
|
||||
|
||||
for (int y = sy; y < ey; y++)
|
||||
{
|
||||
for (int x = sx; x < ex; x++)
|
||||
// Fill in the first pixel of the row based on image format
|
||||
ImageDrawPixel(dst, sx, y, color);
|
||||
|
||||
int bytesOffset = ((y * dst->width) + sx) * bytesPerPixel;
|
||||
unsigned char *pSrcPixel = (unsigned char *)dst->data + bytesOffset;
|
||||
|
||||
// Repeat the first pixel data throughout the row
|
||||
for (int x = 1; x < (int)rec.width; x++)
|
||||
{
|
||||
ImageDrawPixel(dst, x, y, color);
|
||||
memcpy(pSrcPixel + x * bytesPerPixel, pSrcPixel, bytesPerPixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2716,6 +2792,9 @@ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec, Color
|
|||
// [x] Consider fast path: no alpha blending required cases (src has no alpha)
|
||||
// [x] Consider fast path: same src/dst format with no alpha -> direct line copy
|
||||
// [-] GetPixelColor(): Get Vector4 instead of Color, easier for ColorAlphaBlend()
|
||||
// [ ] Support f32bit channels drawing
|
||||
|
||||
// TODO: Support PIXELFORMAT_UNCOMPRESSED_R32, PIXELFORMAT_UNCOMPRESSED_R32G32B32, PIXELFORMAT_UNCOMPRESSED_R32G32B32A32
|
||||
|
||||
Color colSrc, colDst, blend;
|
||||
bool blendRequired = true;
|
||||
|
@ -2768,10 +2847,13 @@ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec, Color
|
|||
// Draw text (default font) within an image (destination)
|
||||
void ImageDrawText(Image *dst, const char *text, int posX, int posY, int fontSize, Color color)
|
||||
{
|
||||
#if defined(SUPPORT_MODULE_RTEXT)
|
||||
Vector2 position = { (float)posX, (float)posY };
|
||||
|
||||
// NOTE: For default font, sapcing is set to desired font size / default font size (10)
|
||||
ImageDrawTextEx(dst, GetFontDefault(), text, position, (float)fontSize, (float)fontSize/10, color);
|
||||
// NOTE: For default font, spacing is set to desired font size / default font size (10)
|
||||
ImageDrawTextEx(dst, GetFontDefault(), text, position, (float)fontSize, (float)fontSize/10, color); // WARNING: Module required: rtext
|
||||
#else
|
||||
TRACELOG(LOG_WARNING, "IMAGE: ImageDrawText() requires module: rtext");
|
||||
#endif
|
||||
}
|
||||
|
||||
// Draw text (custom sprite font) within an image (destination)
|
||||
|
@ -2812,7 +2894,7 @@ Texture2D LoadTextureFromImage(Image image)
|
|||
{
|
||||
Texture2D texture = { 0 };
|
||||
|
||||
if ((image.data != NULL) && (image.width != 0) && (image.height != 0))
|
||||
if ((image.width != 0) && (image.height != 0))
|
||||
{
|
||||
texture.id = rlLoadTexture(image.data, image.width, image.height, image.format, image.mipmaps);
|
||||
}
|
||||
|
@ -2849,6 +2931,7 @@ TextureCubemap LoadTextureCubemap(Image image, int layout)
|
|||
cubemap.height = cubemap.width;
|
||||
}
|
||||
|
||||
// Layout provided or already auto-detected
|
||||
if (layout != CUBEMAP_LAYOUT_AUTO_DETECT)
|
||||
{
|
||||
int size = cubemap.width;
|
||||
|
@ -2859,8 +2942,7 @@ TextureCubemap LoadTextureCubemap(Image image, int layout)
|
|||
|
||||
if (layout == CUBEMAP_LAYOUT_LINE_VERTICAL)
|
||||
{
|
||||
faces = image;
|
||||
for (int i = 0; i < 6; i++) faceRecs[i].y = (float)size*i;
|
||||
faces = ImageCopy(image); // Image data already follows expected convention
|
||||
}
|
||||
else if (layout == CUBEMAP_LAYOUT_PANORAMA)
|
||||
{
|
||||
|
@ -2894,10 +2976,12 @@ TextureCubemap LoadTextureCubemap(Image image, int layout)
|
|||
ImageFormat(&faces, image.format);
|
||||
|
||||
// NOTE: Image formating does not work with compressed textures
|
||||
|
||||
for (int i = 0; i < 6; i++) ImageDraw(&faces, image, faceRecs[i], (Rectangle){ 0, (float)size*i, (float)size, (float)size }, WHITE);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 6; i++) ImageDraw(&faces, image, faceRecs[i], (Rectangle){ 0, (float)size*i, (float)size, (float)size }, WHITE);
|
||||
|
||||
// NOTE: Cubemap data is expected to be provided as 6 images in a single data array,
|
||||
// one after the other (that's a vertical image), following convention: +X, -X, +Y, -Y, +Z, -Z
|
||||
cubemap.id = rlLoadTextureCubemap(faces.data, size, faces.format);
|
||||
if (cubemap.id == 0) TRACELOG(LOG_WARNING, "IMAGE: Failed to load cubemap image");
|
||||
|
||||
|
@ -3071,6 +3155,7 @@ void SetTextureWrap(Texture2D texture, int wrap)
|
|||
{
|
||||
case TEXTURE_WRAP_REPEAT:
|
||||
{
|
||||
// NOTE: It only works if NPOT textures are supported, i.e. OpenGL ES 2.0 could not support it
|
||||
rlTextureParameters(texture.id, RL_TEXTURE_WRAP_S, RL_TEXTURE_WRAP_REPEAT);
|
||||
rlTextureParameters(texture.id, RL_TEXTURE_WRAP_T, RL_TEXTURE_WRAP_REPEAT);
|
||||
} break;
|
||||
|
@ -3132,6 +3217,8 @@ void DrawTextureRec(Texture2D texture, Rectangle source, Vector2 position, Color
|
|||
// i.e tiling = { 1.0f, 1.0f } refers to all texture, offset = { 0.5f, 0.5f } moves texture origin to center
|
||||
void DrawTextureQuad(Texture2D texture, Vector2 tiling, Vector2 offset, Rectangle quad, Color tint)
|
||||
{
|
||||
// WARNING: This solution only works if TEXTURE_WRAP_REPEAT is supported,
|
||||
// NPOT textures supported is required and OpenGL ES 2.0 could not support it
|
||||
Rectangle source = { offset.x*texture.width, offset.y*texture.height, tiling.x*texture.width, tiling.y*texture.height };
|
||||
Vector2 origin = { 0.0f, 0.0f };
|
||||
|
||||
|
@ -3143,6 +3230,7 @@ void DrawTextureQuad(Texture2D texture, Vector2 tiling, Vector2 offset, Rectangl
|
|||
void DrawTextureTiled(Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, float scale, Color tint)
|
||||
{
|
||||
if ((texture.id <= 0) || (scale <= 0.0f)) return; // Wanna see a infinite loop?!...just delete this line!
|
||||
if ((source.width == 0) || (source.height == 0)) return;
|
||||
|
||||
int tileWidth = (int)(source.width*scale), tileHeight = (int)(source.height*scale);
|
||||
if ((dest.width < tileWidth) && (dest.height < tileHeight))
|
||||
|
@ -3406,6 +3494,8 @@ void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle dest,
|
|||
coordD.x = (nPatchInfo.source.x + nPatchInfo.source.width)/width;
|
||||
coordD.y = (nPatchInfo.source.y + nPatchInfo.source.height)/height;
|
||||
|
||||
rlCheckRenderBatchLimit(9 * 3 * 2); // Maxium number of verts that could happen
|
||||
|
||||
rlSetTexture(texture.id);
|
||||
|
||||
rlPushMatrix();
|
||||
|
@ -3553,7 +3643,7 @@ void DrawTexturePoly(Texture2D texture, Vector2 center, Vector2 *points, Vector2
|
|||
|
||||
rlSetTexture(texture.id);
|
||||
|
||||
// Texturing is only supported on QUADs
|
||||
// Texturing is only supported on RL_QUADS
|
||||
rlBegin(RL_QUADS);
|
||||
|
||||
rlColor4ub(tint.r, tint.g, tint.b, tint.a);
|
||||
|
@ -3721,10 +3811,10 @@ Color ColorAlphaBlend(Color dst, Color src, Color tint)
|
|||
Color out = WHITE;
|
||||
|
||||
// Apply color tint to source color
|
||||
src.r = (unsigned char)(((unsigned int)src.r*(unsigned int)tint.r) >> 8);
|
||||
src.g = (unsigned char)(((unsigned int)src.g*(unsigned int)tint.g) >> 8);
|
||||
src.b = (unsigned char)(((unsigned int)src.b*(unsigned int)tint.b) >> 8);
|
||||
src.a = (unsigned char)(((unsigned int)src.a*(unsigned int)tint.a) >> 8);
|
||||
src.r = (unsigned char)(((unsigned int)src.r*((unsigned int)tint.r+1)) >> 8);
|
||||
src.g = (unsigned char)(((unsigned int)src.g*((unsigned int)tint.g+1)) >> 8);
|
||||
src.b = (unsigned char)(((unsigned int)src.b*((unsigned int)tint.b+1)) >> 8);
|
||||
src.a = (unsigned char)(((unsigned int)src.a*((unsigned int)tint.a+1)) >> 8);
|
||||
|
||||
//#define COLORALPHABLEND_FLOAT
|
||||
#define COLORALPHABLEND_INTEGERS
|
||||
|
@ -4259,6 +4349,7 @@ static Image LoadPKM(const unsigned char *fileData, unsigned int fileSize)
|
|||
|
||||
#if defined(SUPPORT_FILEFORMAT_KTX)
|
||||
// Load KTX compressed image data (ETC1/ETC2 compression)
|
||||
// TODO: Review KTX loading, many things changed!
|
||||
static Image LoadKTX(const unsigned char *fileData, unsigned int fileSize)
|
||||
{
|
||||
unsigned char *fileDataPtr = (unsigned char *)fileData;
|
||||
|
@ -4333,6 +4424,8 @@ static Image LoadKTX(const unsigned char *fileData, unsigned int fileSize)
|
|||
if (ktxHeader->glInternalFormat == 0x8D64) image.format = PIXELFORMAT_COMPRESSED_ETC1_RGB;
|
||||
else if (ktxHeader->glInternalFormat == 0x9274) image.format = PIXELFORMAT_COMPRESSED_ETC2_RGB;
|
||||
else if (ktxHeader->glInternalFormat == 0x9278) image.format = PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA;
|
||||
|
||||
// TODO: Support uncompressed data formats? Right now it returns format = 0!
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4341,11 +4434,12 @@ static Image LoadKTX(const unsigned char *fileData, unsigned int fileSize)
|
|||
|
||||
// Save image data as KTX file
|
||||
// NOTE: By default KTX 1.1 spec is used, 2.0 is still on draft (01Oct2018)
|
||||
// TODO: Review KTX saving, many things changed!
|
||||
static int SaveKTX(Image image, const char *fileName)
|
||||
{
|
||||
// KTX file Header (64 bytes)
|
||||
// v1.1 - https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/
|
||||
// v2.0 - http://github.khronos.org/KTX-Specification/ - still on draft, not ready for implementation
|
||||
// v2.0 - http://github.khronos.org/KTX-Specification/ - Final specs by 2021-04-18
|
||||
typedef struct {
|
||||
char id[12]; // Identifier: "«KTX 11»\r\n\x1A\n" // KTX 2.0: "«KTX 22»\r\n\x1A\n"
|
||||
unsigned int endianness; // Little endian: 0x01 0x02 0x03 0x04
|
||||
|
@ -4480,7 +4574,7 @@ static Image LoadPVR(const unsigned char *fileData, unsigned int fileSize)
|
|||
unsigned int flags;
|
||||
unsigned char channels[4]; // pixelFormat high part
|
||||
unsigned char channelDepth[4]; // pixelFormat low part
|
||||
unsigned int colourSpace;
|
||||
unsigned int colorSpace;
|
||||
unsigned int channelType;
|
||||
unsigned int height;
|
||||
unsigned int width;
|
||||
|
@ -4759,3 +4853,5 @@ static Vector4 *LoadImageDataNormalized(Image image)
|
|||
|
||||
return pixels;
|
||||
}
|
||||
|
||||
#endif // SUPPORT_MODULE_RTEXTURES
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2014-2021 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2014-2022 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.
|
||||
|
@ -148,6 +148,7 @@ void TraceLog(int logType, const char *text, ...)
|
|||
strcat(buffer, text);
|
||||
strcat(buffer, "\n");
|
||||
vprintf(buffer, args);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
|
||||
va_end(args);
|
||||
|
@ -268,6 +269,51 @@ bool SaveFileData(const char *fileName, void *data, unsigned int bytesToWrite)
|
|||
return success;
|
||||
}
|
||||
|
||||
// Export data to code (.h), returns true on success
|
||||
bool ExportDataAsCode(const char *data, unsigned int size, const char *fileName)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
#ifndef TEXT_BYTES_PER_LINE
|
||||
#define TEXT_BYTES_PER_LINE 20
|
||||
#endif
|
||||
|
||||
// NOTE: Text data buffer size is estimated considering raw data size in bytes
|
||||
// and requiring 6 char bytes for every byte: "0x00, "
|
||||
char *txtData = (char *)RL_CALLOC(size*6 + 2000, sizeof(char));
|
||||
|
||||
int byteCount = 0;
|
||||
byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// DataAsCode exporter v1.0 - Raw data exported as an array of bytes //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// more info and bugs-report: github.com/raysan5/raylib //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// feedback and support: ray[at]raylib.com //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// Copyright (c) 2022 Ramon Santamaria (@raysan5) //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n\n");
|
||||
|
||||
// Get file name from path and convert variable name to uppercase
|
||||
char varFileName[256] = { 0 };
|
||||
strcpy(varFileName, GetFileNameWithoutExt(fileName));
|
||||
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);
|
||||
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]);
|
||||
|
||||
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
||||
success = SaveFileText(fileName, txtData);
|
||||
|
||||
RL_FREE(txtData);
|
||||
|
||||
if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Data as code exported successfully", fileName);
|
||||
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export data as code", fileName);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
// Load text data from file, returns a '\0' terminated string
|
||||
// NOTE: text chars array should be freed manually
|
||||
char *LoadFileText(const char *fileName)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2014-2021 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2014-2022 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.
|
||||
|
@ -65,7 +65,7 @@
|
|||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
//----------------------------------------------------------------------------------
|
||||
#ifdef __cplusplus
|
||||
#if defined(__cplusplus)
|
||||
extern "C" { // Prevents name mangling of functions
|
||||
#endif
|
||||
|
||||
|
@ -74,7 +74,7 @@ void InitAssetManager(AAssetManager *manager, const char *dataPath); // Initia
|
|||
FILE *android_fopen(const char *fileName, const char *mode); // Replacement for fopen() -> Read-only!
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue