Update C sources and add new functions
This commit is contained in:
parent
9784968948
commit
7874621942
24 changed files with 2149 additions and 1316 deletions
623
raylib/audio.c
623
raylib/audio.c
File diff suppressed because it is too large
Load diff
|
@ -10,19 +10,24 @@
|
||||||
* - Manage mixing channels
|
* - Manage mixing channels
|
||||||
* - Manage raw audio context
|
* - Manage raw audio context
|
||||||
*
|
*
|
||||||
* LIMITATIONS:
|
* LIMITATIONS (only OpenAL Soft):
|
||||||
* Only up to two channels supported: MONO and STEREO (for additional channels, use AL_EXT_MCFORMATS)
|
* Only up to two channels supported: MONO and STEREO (for additional channels, use AL_EXT_MCFORMATS)
|
||||||
* Only the following sample sizes supported: 8bit PCM, 16bit PCM, 32-bit float PCM (using AL_EXT_FLOAT32)
|
* Only the following sample sizes supported: 8bit PCM, 16bit PCM, 32-bit float PCM (using AL_EXT_FLOAT32)
|
||||||
*
|
*
|
||||||
* DEPENDENCIES:
|
* DEPENDENCIES:
|
||||||
* OpenAL Soft - Audio device management (http://kcat.strangesoft.net/openal.html)
|
* mini_al - Audio device/context management (https://github.com/dr-soft/mini_al)
|
||||||
* stb_vorbis - OGG audio files loading (http://www.nothings.org/stb_vorbis/)
|
* stb_vorbis - OGG audio files loading (http://www.nothings.org/stb_vorbis/)
|
||||||
* jar_xm - XM module file loading (#define SUPPORT_FILEFORMAT_XM)
|
* jar_xm - XM module file loading
|
||||||
* jar_mod - MOD audio file loading (#define SUPPORT_FILEFORMAT_MOD)
|
* jar_mod - MOD audio file loading
|
||||||
* dr_flac - FLAC audio file loading (#define SUPPORT_FILEFORMAT_FLAC)
|
* dr_flac - FLAC audio file loading
|
||||||
|
*
|
||||||
|
* *OpenAL Soft - Audio device management, still used on HTML5 and OSX platforms
|
||||||
*
|
*
|
||||||
* CONTRIBUTORS:
|
* CONTRIBUTORS:
|
||||||
* Joshua Reisenauer (github: @kd7tck):
|
* David Reid (github: @mackron) (Nov. 2017):
|
||||||
|
* - Complete port to mini_al library
|
||||||
|
*
|
||||||
|
* Joshua Reisenauer (github: @kd7tck) (2015)
|
||||||
* - XM audio module support (jar_xm)
|
* - XM audio module support (jar_xm)
|
||||||
* - MOD audio module support (jar_mod)
|
* - MOD audio module support (jar_mod)
|
||||||
* - Mixing channels support
|
* - Mixing channels support
|
||||||
|
@ -31,7 +36,7 @@
|
||||||
*
|
*
|
||||||
* LICENSE: zlib/libpng
|
* LICENSE: zlib/libpng
|
||||||
*
|
*
|
||||||
* Copyright (c) 2014-2017 Ramon Santamaria (@raysan5)
|
* Copyright (c) 2014-2018 Ramon Santamaria (@raysan5)
|
||||||
*
|
*
|
||||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
* 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.
|
* will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
@ -81,9 +86,11 @@ typedef struct Wave {
|
||||||
|
|
||||||
// Sound source type
|
// Sound source type
|
||||||
typedef struct Sound {
|
typedef struct Sound {
|
||||||
unsigned int source; // OpenAL audio source id
|
void *audioBuffer; // Pointer to internal data used by the audio system
|
||||||
unsigned int buffer; // OpenAL audio buffer id
|
|
||||||
int format; // OpenAL audio format specifier
|
unsigned int source; // Audio source id
|
||||||
|
unsigned int buffer; // Audio buffer id
|
||||||
|
int format; // Audio format specifier
|
||||||
} Sound;
|
} Sound;
|
||||||
|
|
||||||
// Music type (file streaming from memory)
|
// Music type (file streaming from memory)
|
||||||
|
@ -97,9 +104,11 @@ typedef struct AudioStream {
|
||||||
unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported)
|
unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported)
|
||||||
unsigned int channels; // Number of channels (1-mono, 2-stereo)
|
unsigned int channels; // Number of channels (1-mono, 2-stereo)
|
||||||
|
|
||||||
int format; // OpenAL audio format specifier
|
void *audioBuffer; // Pointer to internal data used by the audio system.
|
||||||
unsigned int source; // OpenAL audio source id
|
|
||||||
unsigned int buffers[2]; // OpenAL audio buffers (double buffering)
|
int format; // Audio format specifier
|
||||||
|
unsigned int source; // Audio source id
|
||||||
|
unsigned int buffers[2]; // Audio buffers (double buffering)
|
||||||
} AudioStream;
|
} AudioStream;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -147,12 +156,12 @@ void ResumeMusicStream(Music music); // Resume playin
|
||||||
bool IsMusicPlaying(Music music); // Check if music is playing
|
bool IsMusicPlaying(Music music); // Check if music is playing
|
||||||
void SetMusicVolume(Music music, float volume); // Set volume for music (1.0 is max level)
|
void SetMusicVolume(Music music, float volume); // Set volume for music (1.0 is max level)
|
||||||
void SetMusicPitch(Music music, float pitch); // Set pitch for a music (1.0 is base level)
|
void SetMusicPitch(Music music, float pitch); // Set pitch for a music (1.0 is base level)
|
||||||
void SetMusicLoopCount(Music music, float count); // Set music loop count (loop repeats)
|
void SetMusicLoopCount(Music music, int count); // Set music loop count (loop repeats)
|
||||||
float GetMusicTimeLength(Music music); // Get music time length (in seconds)
|
float GetMusicTimeLength(Music music); // Get music time length (in seconds)
|
||||||
float GetMusicTimePlayed(Music music); // Get current music time played (in seconds)
|
float GetMusicTimePlayed(Music music); // Get current music time played (in seconds)
|
||||||
|
|
||||||
// Raw audio stream functions
|
// AudioStream management functions
|
||||||
AudioStream InitAudioStream(unsigned int sampleRate,
|
AudioStream InitAudioStream(unsigned int sampleRate,
|
||||||
unsigned int sampleSize,
|
unsigned int sampleSize,
|
||||||
unsigned int channels); // Init audio stream (to stream raw audio pcm data)
|
unsigned int channels); // Init audio stream (to stream raw audio pcm data)
|
||||||
void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount); // Update audio stream buffers with data
|
void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount); // Update audio stream buffers with data
|
||||||
|
@ -161,7 +170,10 @@ bool IsAudioBufferProcessed(AudioStream stream); // Check if any
|
||||||
void PlayAudioStream(AudioStream stream); // Play audio stream
|
void PlayAudioStream(AudioStream stream); // Play audio stream
|
||||||
void PauseAudioStream(AudioStream stream); // Pause audio stream
|
void PauseAudioStream(AudioStream stream); // Pause audio stream
|
||||||
void ResumeAudioStream(AudioStream stream); // Resume audio stream
|
void ResumeAudioStream(AudioStream stream); // Resume audio stream
|
||||||
|
bool IsAudioStreamPlaying(AudioStream stream); // Check if audio stream is playing
|
||||||
void StopAudioStream(AudioStream stream); // Stop audio stream
|
void StopAudioStream(AudioStream stream); // Stop audio stream
|
||||||
|
void SetAudioStreamVolume(AudioStream stream, float volume); // Set volume for audio stream (1.0 is max level)
|
||||||
|
void SetAudioStreamPitch(AudioStream stream, float pitch); // Set pitch for audio stream (1.0 is base level)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
499
raylib/core.c
499
raylib/core.c
|
@ -1,18 +1,16 @@
|
||||||
// +build !js
|
|
||||||
|
|
||||||
/**********************************************************************************************
|
/**********************************************************************************************
|
||||||
*
|
*
|
||||||
* raylib.core - Basic functions to manage windows, OpenGL context and input on multiple platforms
|
* raylib.core - Basic functions to manage windows, OpenGL context and input on multiple platforms
|
||||||
*
|
*
|
||||||
* PLATFORMS SUPPORTED:
|
* PLATFORMS SUPPORTED:
|
||||||
* PLATFORM_DESKTOP: Windows (Win32, Win64)
|
* - PLATFORM_DESKTOP: Windows (Win32, Win64)
|
||||||
* PLATFORM_DESKTOP: Linux (32 and 64 bit)
|
* - PLATFORM_DESKTOP: Linux (X11 desktop mode)
|
||||||
* PLATFORM_DESKTOP: OSX/macOS
|
* - PLATFORM_DESKTOP: FreeBSD (X11 desktop)
|
||||||
* PLATFORM_DESKTOP: FreeBSD
|
* - PLATFORM_DESKTOP: OSX/macOS
|
||||||
* PLATFORM_ANDROID: Android (ARM, ARM64)
|
* - PLATFORM_ANDROID: Android 4.0 (ARM, ARM64)
|
||||||
* PLATFORM_RPI: Raspberry Pi (Raspbian)
|
* - PLATFORM_RPI: Raspberry Pi 0,1,2,3 (Raspbian)
|
||||||
* PLATFORM_WEB: HTML5 (Chrome, Firefox)
|
* - PLATFORM_WEB: HTML5 with asm.js (Chrome, Firefox)
|
||||||
* PLATFORM_UWP: Universal Windows Platform
|
* - PLATFORM_UWP: Windows 10 App, Windows Phone, Xbox One
|
||||||
*
|
*
|
||||||
* CONFIGURATION:
|
* CONFIGURATION:
|
||||||
*
|
*
|
||||||
|
@ -32,6 +30,10 @@
|
||||||
* Windowing and input system configured for HTML5 (run on browser), code converted from C to asm.js
|
* Windowing and input system configured for HTML5 (run on browser), code converted from C to asm.js
|
||||||
* using emscripten compiler. OpenGL ES 2.0 required for direct translation to WebGL equivalent code.
|
* using emscripten compiler. OpenGL ES 2.0 required for direct translation to WebGL equivalent code.
|
||||||
*
|
*
|
||||||
|
* #define PLATFORM_UWP
|
||||||
|
* Universal Windows Platform support, using OpenGL ES 2.0 through ANGLE on multiple Windows platforms,
|
||||||
|
* including Windows 10 App, Windows Phone and Xbox One platforms.
|
||||||
|
*
|
||||||
* #define SUPPORT_DEFAULT_FONT (default)
|
* #define SUPPORT_DEFAULT_FONT (default)
|
||||||
* Default font is loaded on window initialization to be available for the user to render simple text.
|
* 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 (module: text)
|
* NOTE: If enabled, uses external module functions to load default raylib font (module: text)
|
||||||
|
@ -91,7 +93,7 @@
|
||||||
|
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
|
|
||||||
#if (defined(__linux__) || defined(PLATFORM_WEB)) && _POSIX_S_SOURCE < 199309L
|
#if (defined(__linux__) || defined(PLATFORM_WEB)) && _POSIX_C_SOURCE < 199309L
|
||||||
#undef _POSIX_C_SOURCE
|
#undef _POSIX_C_SOURCE
|
||||||
#define _POSIX_C_SOURCE 199309L // Required for CLOCK_MONOTONIC if compiled with c99 without gnu ext.
|
#define _POSIX_C_SOURCE 199309L // Required for CLOCK_MONOTONIC if compiled with c99 without gnu ext.
|
||||||
#endif
|
#endif
|
||||||
|
@ -126,7 +128,7 @@
|
||||||
#include <string.h> // Required for: strrchr(), strcmp()
|
#include <string.h> // Required for: strrchr(), strcmp()
|
||||||
//#include <errno.h> // Macros for reporting and retrieving error conditions through error codes
|
//#include <errno.h> // Macros for reporting and retrieving error conditions through error codes
|
||||||
|
|
||||||
#ifdef _WIN32
|
#if defined(_WIN32)
|
||||||
#include <direct.h> // Required for: _getch(), _chdir()
|
#include <direct.h> // Required for: _getch(), _chdir()
|
||||||
#define GETCWD _getcwd // NOTE: MSDN recommends not to use getcwd(), chdir()
|
#define GETCWD _getcwd // NOTE: MSDN recommends not to use getcwd(), chdir()
|
||||||
#define CHDIR _chdir
|
#define CHDIR _chdir
|
||||||
|
@ -152,11 +154,11 @@
|
||||||
#include <GLFW/glfw3native.h> // which are required for hiding mouse
|
#include <GLFW/glfw3native.h> // which are required for hiding mouse
|
||||||
#endif
|
#endif
|
||||||
//#include <GL/gl.h> // OpenGL functions (GLFW3 already includes gl.h)
|
//#include <GL/gl.h> // OpenGL functions (GLFW3 already includes gl.h)
|
||||||
//#define GLFW_DLL // Using GLFW DLL on Windows -> No, we use static version!
|
|
||||||
|
|
||||||
#if !defined(SUPPORT_BUSY_WAIT_LOOP) && defined(_WIN32)
|
#if !defined(SUPPORT_BUSY_WAIT_LOOP) && defined(_WIN32)
|
||||||
__stdcall unsigned int timeBeginPeriod(unsigned int uPeriod);
|
// NOTE: Those functions require linking with winmm library
|
||||||
__stdcall unsigned int timeEndPeriod(unsigned int uPeriod);
|
unsigned int __stdcall timeBeginPeriod(unsigned int uPeriod);
|
||||||
|
unsigned int __stdcall timeEndPeriod(unsigned int uPeriod);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -187,6 +189,12 @@
|
||||||
#include "GLES2/gl2.h" // Khronos OpenGL ES 2.0 library
|
#include "GLES2/gl2.h" // Khronos OpenGL ES 2.0 library
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(PLATFORM_UWP)
|
||||||
|
#include "EGL/egl.h" // Khronos EGL library - Native platform display device control functions
|
||||||
|
#include "EGL/eglext.h" // Khronos EGL library - Extensions
|
||||||
|
#include "GLES2/gl2.h" // Khronos OpenGL ES 2.0 library
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(PLATFORM_WEB)
|
#if defined(PLATFORM_WEB)
|
||||||
#include <emscripten/emscripten.h>
|
#include <emscripten/emscripten.h>
|
||||||
#include <emscripten/html5.h>
|
#include <emscripten/html5.h>
|
||||||
|
@ -226,16 +234,17 @@
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
||||||
static GLFWwindow *window; // Native window (graphic device)
|
static GLFWwindow *window; // Native window (graphic device)
|
||||||
static bool windowMinimized = false;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static bool windowReady = false; // Check if window has been initialized successfully
|
||||||
|
static bool windowMinimized = false; // Check if window has been minimized
|
||||||
|
|
||||||
#if defined(PLATFORM_ANDROID)
|
#if defined(PLATFORM_ANDROID)
|
||||||
static struct android_app *app; // Android activity
|
static struct android_app *app; // Android activity
|
||||||
static struct android_poll_source *source; // Android events polling source
|
static struct android_poll_source *source; // Android events polling source
|
||||||
static int ident, events; // Android ALooper_pollAll() variables
|
static int ident, events; // Android ALooper_pollAll() variables
|
||||||
static const char *internalDataPath; // Android internal data path to write data (/data/data/<package>/files)
|
static const char *internalDataPath; // Android internal data path to write data (/data/data/<package>/files)
|
||||||
|
|
||||||
static bool windowReady = false; // Used to detect display initialization
|
|
||||||
static bool appEnabled = true; // Used to detec if app is active
|
static bool appEnabled = true; // Used to detec if app is active
|
||||||
static bool contextRebindRequired = false; // Used to know context rebind required
|
static bool contextRebindRequired = false; // Used to know context rebind required
|
||||||
#endif
|
#endif
|
||||||
|
@ -264,7 +273,7 @@ static pthread_t gamepadThreadId; // Gamepad reading thread id
|
||||||
static char gamepadName[64]; // Gamepad name holder
|
static char gamepadName[64]; // Gamepad name holder
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
|
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_UWP)
|
||||||
static EGLDisplay display; // Native display device (physical screen connection)
|
static EGLDisplay display; // Native display device (physical screen connection)
|
||||||
static EGLSurface surface; // Surface to draw on, framebuffers (connected to context)
|
static EGLSurface surface; // Surface to draw on, framebuffers (connected to context)
|
||||||
static EGLContext context; // Graphic context, mode in which drawing can be done
|
static EGLContext context; // Graphic context, mode in which drawing can be done
|
||||||
|
@ -273,6 +282,10 @@ static uint64_t baseTime; // Base time measure for hi-res timer
|
||||||
static bool windowShouldClose = false; // Flag to set window for closing
|
static bool windowShouldClose = false; // Flag to set window for closing
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(PLATFORM_UWP)
|
||||||
|
static EGLNativeWindowType uwpWindow;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Display size-related data
|
// Display size-related data
|
||||||
static unsigned int displayWidth, displayHeight; // Display width and height (monitor, device-screen, LCD, ...)
|
static unsigned int displayWidth, displayHeight; // Display width and height (monitor, device-screen, LCD, ...)
|
||||||
static int screenWidth, screenHeight; // Screen width and height (used render area)
|
static int screenWidth, screenHeight; // Screen width and height (used render area)
|
||||||
|
@ -281,12 +294,11 @@ static int renderOffsetX = 0; // Offset X from render area (must b
|
||||||
static int renderOffsetY = 0; // Offset Y from render area (must be divided by 2)
|
static int renderOffsetY = 0; // Offset Y from render area (must be divided by 2)
|
||||||
static bool fullscreen = false; // Fullscreen mode (useful only for PLATFORM_DESKTOP)
|
static bool fullscreen = false; // Fullscreen mode (useful only for PLATFORM_DESKTOP)
|
||||||
static Matrix downscaleView; // Matrix to downscale view (in case screen size bigger than display size)
|
static Matrix downscaleView; // Matrix to downscale view (in case screen size bigger than display size)
|
||||||
|
|
||||||
static bool cursorHidden = false; // Track if cursor is hidden
|
static bool cursorHidden = false; // Track if cursor is hidden
|
||||||
|
|
||||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
|
|
||||||
static const char *windowTitle = NULL; // Window text title...
|
|
||||||
static bool cursorOnScreen = false; // Tracks if cursor is inside client area
|
static bool cursorOnScreen = false; // Tracks if cursor is inside client area
|
||||||
|
|
||||||
|
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) || defined(PLATFORM_UWP)
|
||||||
|
static const char *windowTitle = NULL; // Window text title...
|
||||||
static int screenshotCounter = 0; // Screenshots counter
|
static int screenshotCounter = 0; // Screenshots counter
|
||||||
|
|
||||||
// Register mouse states
|
// Register mouse states
|
||||||
|
@ -331,7 +343,7 @@ static double updateTime, drawTime; // Time measures for update and draw
|
||||||
static double frameTime = 0.0; // Time measure for one frame
|
static double frameTime = 0.0; // Time measure for one frame
|
||||||
static double targetTime = 0.0; // Desired time for one frame, if 0 not applied
|
static double targetTime = 0.0; // Desired time for one frame, if 0 not applied
|
||||||
|
|
||||||
static char configFlags = 0; // Configuration flags (bit based)
|
static unsigned char configFlags = 0; // Configuration flags (bit based)
|
||||||
static bool showLogo = false; // Track if showing logo at init is enabled
|
static bool showLogo = false; // Track if showing logo at init is enabled
|
||||||
|
|
||||||
#if defined(SUPPORT_GIF_RECORDING)
|
#if defined(SUPPORT_GIF_RECORDING)
|
||||||
|
@ -350,10 +362,9 @@ extern void UnloadDefaultFont(void); // [Module: text] Unloads default fo
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module specific Functions Declaration
|
// Module specific Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
static void InitGraphicsDevice(int width, int height); // Initialize graphics device
|
static bool InitGraphicsDevice(int width, int height); // Initialize graphics device
|
||||||
static void SetupFramebufferSize(int displayWidth, int displayHeight);
|
static void SetupFramebufferSize(int displayWidth, int displayHeight);
|
||||||
static void InitTimer(void); // Initialize timer
|
static void InitTimer(void); // Initialize timer
|
||||||
static double GetTime(void); // Returns time since InitTimer() was run
|
|
||||||
static void Wait(float ms); // Wait for some milliseconds (stop program execution)
|
static void Wait(float ms); // Wait for some milliseconds (stop program execution)
|
||||||
static bool GetKeyStatus(int key); // Returns if a key has been pressed
|
static bool GetKeyStatus(int key); // Returns if a key has been pressed
|
||||||
static bool GetMouseButtonStatus(int button); // Returns if a mouse button has been pressed
|
static bool GetMouseButtonStatus(int button); // Returns if a mouse button has been pressed
|
||||||
|
@ -403,6 +414,10 @@ static void InitGamepad(void); // Init raw gamepad inpu
|
||||||
static void *GamepadThread(void *arg); // Mouse reading thread
|
static void *GamepadThread(void *arg); // Mouse reading thread
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(PLATFORM_UWP)
|
||||||
|
// Define functions required to manage inputs
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
// NOTE: We include Sleep() function signature here to avoid windows.h inclusion
|
// NOTE: We include Sleep() function signature here to avoid windows.h inclusion
|
||||||
void __stdcall Sleep(unsigned long msTimeout); // Required for Wait()
|
void __stdcall Sleep(unsigned long msTimeout); // Required for Wait()
|
||||||
|
@ -411,18 +426,28 @@ static void *GamepadThread(void *arg); // Mouse reading thread
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Functions Definition - Window and OpenGL Context Functions
|
// Module Functions Definition - Window and OpenGL Context Functions
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
|
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) || defined(PLATFORM_UWP)
|
||||||
// Initialize window and OpenGL context
|
// Initialize window and OpenGL context
|
||||||
// NOTE: data parameter could be used to pass any kind of required data to the initialization
|
// NOTE: data parameter could be used to pass any kind of required data to the initialization
|
||||||
void InitWindow(int width, int height, void *data)
|
void InitWindow(int width, int height, void *data)
|
||||||
{
|
{
|
||||||
TraceLog(LOG_INFO, "Initializing raylib (v1.9-dev)");
|
TraceLog(LOG_INFO, "Initializing raylib (v1.9.4-dev)");
|
||||||
|
|
||||||
// Input data is window title char data
|
#if defined(PLATFORM_DESKTOP)
|
||||||
windowTitle = (char *)data;
|
windowTitle = (char *)data;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(PLATFORM_UWP)
|
||||||
|
uwpWindow = (EGLNativeWindowType)data;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Init hi-res timer
|
||||||
|
InitTimer();
|
||||||
|
|
||||||
// Init graphics device (display device and OpenGL context)
|
// Init graphics device (display device and OpenGL context)
|
||||||
InitGraphicsDevice(width, height);
|
// NOTE: returns true if window and graphic device has been initialized successfully
|
||||||
|
windowReady = InitGraphicsDevice(width, height);
|
||||||
|
if (!windowReady) return;
|
||||||
|
|
||||||
#if defined(SUPPORT_DEFAULT_FONT)
|
#if defined(SUPPORT_DEFAULT_FONT)
|
||||||
// Load default font
|
// Load default font
|
||||||
|
@ -430,9 +455,6 @@ void InitWindow(int width, int height, void *data)
|
||||||
LoadDefaultFont();
|
LoadDefaultFont();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Init hi-res timer
|
|
||||||
InitTimer();
|
|
||||||
|
|
||||||
#if defined(PLATFORM_RPI)
|
#if defined(PLATFORM_RPI)
|
||||||
// Init raw input system
|
// Init raw input system
|
||||||
InitMouse(); // Mouse init
|
InitMouse(); // Mouse init
|
||||||
|
@ -480,7 +502,7 @@ void InitWindow(int width, int height, void *data)
|
||||||
// NOTE: data parameter could be used to pass any kind of required data to the initialization
|
// NOTE: data parameter could be used to pass any kind of required data to the initialization
|
||||||
void InitWindow(int width, int height, void *data)
|
void InitWindow(int width, int height, void *data)
|
||||||
{
|
{
|
||||||
TraceLog(LOG_INFO, "Initializing raylib (v1.9-dev)");
|
TraceLog(LOG_INFO, "Initializing raylib (v1.9.4-dev)");
|
||||||
|
|
||||||
screenWidth = width;
|
screenWidth = width;
|
||||||
screenHeight = height;
|
screenHeight = height;
|
||||||
|
@ -564,7 +586,7 @@ void CloseWindow(void)
|
||||||
timeEndPeriod(1); // Restore time period
|
timeEndPeriod(1); // Restore time period
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
|
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_UWP)
|
||||||
// Close surface, context and display
|
// Close surface, context and display
|
||||||
if (display != EGL_NO_DISPLAY)
|
if (display != EGL_NO_DISPLAY)
|
||||||
{
|
{
|
||||||
|
@ -602,25 +624,36 @@ void CloseWindow(void)
|
||||||
TraceLog(LOG_INFO, "Window closed successfully");
|
TraceLog(LOG_INFO, "Window closed successfully");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if window has been initialized successfully
|
||||||
|
bool IsWindowReady(void)
|
||||||
|
{
|
||||||
|
return windowReady;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if KEY_ESCAPE pressed or Close icon pressed
|
// Check if KEY_ESCAPE pressed or Close icon pressed
|
||||||
bool WindowShouldClose(void)
|
bool WindowShouldClose(void)
|
||||||
{
|
{
|
||||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
||||||
// While window minimized, stop loop execution
|
if (windowReady)
|
||||||
while (windowMinimized) glfwWaitEvents();
|
{
|
||||||
|
// While window minimized, stop loop execution
|
||||||
|
while (windowMinimized) glfwWaitEvents();
|
||||||
|
|
||||||
return (glfwWindowShouldClose(window));
|
return (glfwWindowShouldClose(window));
|
||||||
|
}
|
||||||
|
else return true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
|
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_UWP)
|
||||||
return windowShouldClose;
|
if (windowReady) return windowShouldClose;
|
||||||
|
else return true;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if window has been minimized (or lost focus)
|
// Check if window has been minimized (or lost focus)
|
||||||
bool IsWindowMinimized(void)
|
bool IsWindowMinimized(void)
|
||||||
{
|
{
|
||||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) || defined(PLATFORM_UWP)
|
||||||
return windowMinimized;
|
return windowMinimized;
|
||||||
#else
|
#else
|
||||||
return false;
|
return false;
|
||||||
|
@ -687,7 +720,7 @@ void SetWindowMonitor(int monitor)
|
||||||
|
|
||||||
if ((monitor >= 0) && (monitor < monitorCount))
|
if ((monitor >= 0) && (monitor < monitorCount))
|
||||||
{
|
{
|
||||||
glfwSetWindowMonitor(window, monitors[monitor], 0, 0, screenWidth, screenHeight, GLFW_DONT_CARE);
|
//glfwSetWindowMonitor(window, monitors[monitor], 0, 0, screenWidth, screenHeight, GLFW_DONT_CARE);
|
||||||
TraceLog(LOG_INFO, "Selected fullscreen monitor: [%i] %s", monitor, glfwGetMonitorName(monitors[monitor]));
|
TraceLog(LOG_INFO, "Selected fullscreen monitor: [%i] %s", monitor, glfwGetMonitorName(monitors[monitor]));
|
||||||
}
|
}
|
||||||
else TraceLog(LOG_WARNING, "Selected monitor not found");
|
else TraceLog(LOG_WARNING, "Selected monitor not found");
|
||||||
|
@ -781,18 +814,17 @@ void DisableCursor()
|
||||||
// Set background color (framebuffer clear color)
|
// Set background color (framebuffer clear color)
|
||||||
void ClearBackground(Color color)
|
void ClearBackground(Color color)
|
||||||
{
|
{
|
||||||
// Clear full framebuffer (not only render area) to color
|
rlClearColor(color.r, color.g, color.b, color.a); // Set clear color
|
||||||
rlClearColor(color.r, color.g, color.b, color.a);
|
rlClearScreenBuffers(); // Clear current framebuffers
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup canvas (framebuffer) to start drawing
|
// Setup canvas (framebuffer) to start drawing
|
||||||
void BeginDrawing(void)
|
void BeginDrawing(void)
|
||||||
{
|
{
|
||||||
currentTime = GetTime(); // Number of elapsed seconds since InitTimer() was called
|
currentTime = GetTime(); // Number of elapsed seconds since InitTimer()
|
||||||
updateTime = currentTime - previousTime;
|
updateTime = currentTime - previousTime;
|
||||||
previousTime = currentTime;
|
previousTime = currentTime;
|
||||||
|
|
||||||
rlClearScreenBuffers(); // Clear current framebuffers
|
|
||||||
rlLoadIdentity(); // Reset current matrix (MODELVIEW)
|
rlLoadIdentity(); // Reset current matrix (MODELVIEW)
|
||||||
rlMultMatrixf(MatrixToFloat(downscaleView)); // If downscale required, apply it here
|
rlMultMatrixf(MatrixToFloat(downscaleView)); // If downscale required, apply it here
|
||||||
|
|
||||||
|
@ -930,7 +962,7 @@ void BeginTextureMode(RenderTexture2D target)
|
||||||
rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2)
|
rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2)
|
||||||
|
|
||||||
rlEnableRenderTexture(target.id); // Enable render target
|
rlEnableRenderTexture(target.id); // Enable render target
|
||||||
|
|
||||||
rlClearScreenBuffers(); // Clear render texture buffers
|
rlClearScreenBuffers(); // Clear render texture buffers
|
||||||
|
|
||||||
// Set viewport to framebuffer size
|
// Set viewport to framebuffer size
|
||||||
|
@ -1062,7 +1094,25 @@ float GetFrameTime(void)
|
||||||
return (float)frameTime;
|
return (float)frameTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Converts Color to float array and normalizes
|
// Get elapsed time measure in seconds since InitTimer()
|
||||||
|
// NOTE: On PLATFORM_DESKTOP InitTimer() is called on InitWindow()
|
||||||
|
// NOTE: On PLATFORM_DESKTOP, timer is initialized on glfwInit()
|
||||||
|
double GetTime(void)
|
||||||
|
{
|
||||||
|
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
||||||
|
return glfwGetTime(); // Elapsed time since glfwInit()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
|
||||||
|
struct timespec ts;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||||
|
uint64_t time = (uint64_t)ts.tv_sec*1000000000LLU + (uint64_t)ts.tv_nsec;
|
||||||
|
|
||||||
|
return (double)(time - baseTime)*1e-9; // Elapsed time since InitTimer()
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns normalized float array for a Color
|
||||||
float *ColorToFloat(Color color)
|
float *ColorToFloat(Color color)
|
||||||
{
|
{
|
||||||
static float buffer[4];
|
static float buffer[4];
|
||||||
|
@ -1075,6 +1125,64 @@ float *ColorToFloat(Color color)
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns hexadecimal value for a Color
|
||||||
|
int ColorToInt(Color color)
|
||||||
|
{
|
||||||
|
return (((int)color.r << 24) | ((int)color.g << 16) | ((int)color.b << 8) | (int)color.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns HSV values for a Color
|
||||||
|
// NOTE: Hue is returned as degrees [0..360]
|
||||||
|
Vector3 ColorToHSV(Color color)
|
||||||
|
{
|
||||||
|
Vector3 rgb = { (float)color.r/255.0f, (float)color.g/255.0f, (float)color.b/255.0f };
|
||||||
|
Vector3 hsv = { 0.0f, 0.0f, 0.0f };
|
||||||
|
float min, max, delta;
|
||||||
|
|
||||||
|
min = rgb.x < rgb.y ? rgb.x : rgb.y;
|
||||||
|
min = min < rgb.z ? min : rgb.z;
|
||||||
|
|
||||||
|
max = rgb.x > rgb.y ? rgb.x : rgb.y;
|
||||||
|
max = max > rgb.z ? max : rgb.z;
|
||||||
|
|
||||||
|
hsv.z = max; // Value
|
||||||
|
delta = max - min;
|
||||||
|
|
||||||
|
if (delta < 0.00001f)
|
||||||
|
{
|
||||||
|
hsv.y = 0.0f;
|
||||||
|
hsv.x = 0.0f; // Undefined, maybe NAN?
|
||||||
|
return hsv;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max > 0.0f)
|
||||||
|
{
|
||||||
|
// NOTE: If max is 0, this divide would cause a crash
|
||||||
|
hsv.y = (delta/max); // Saturation
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// NOTE: If max is 0, then r = g = b = 0, s = 0, h is undefined
|
||||||
|
hsv.y = 0.0f;
|
||||||
|
hsv.x = NAN; // Undefined
|
||||||
|
return hsv;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: Comparing float values could not work properly
|
||||||
|
if (rgb.x >= max) hsv.x = (rgb.y - rgb.z)/delta; // Between yellow & magenta
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (rgb.y >= max) hsv.x = 2.0f + (rgb.z - rgb.x)/delta; // Between cyan & yellow
|
||||||
|
else hsv.x = 4.0f + (rgb.x - rgb.y)/delta; // Between magenta & cyan
|
||||||
|
}
|
||||||
|
|
||||||
|
hsv.x *= 60.0f; // Convert to degrees
|
||||||
|
|
||||||
|
if (hsv.x < 0.0f) hsv.x += 360.0f;
|
||||||
|
|
||||||
|
return hsv;
|
||||||
|
}
|
||||||
|
|
||||||
// Returns a Color struct from hexadecimal value
|
// Returns a Color struct from hexadecimal value
|
||||||
Color GetColor(int hexValue)
|
Color GetColor(int hexValue)
|
||||||
{
|
{
|
||||||
|
@ -1088,11 +1196,7 @@ Color GetColor(int hexValue)
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns hexadecimal value for a Color
|
|
||||||
int GetHexValue(Color color)
|
|
||||||
{
|
|
||||||
return (((int)color.r << 24) | ((int)color.g << 16) | ((int)color.b << 8) | (int)color.a);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a random value between min and max (both included)
|
// Returns a random value between min and max (both included)
|
||||||
int GetRandomValue(int min, int max)
|
int GetRandomValue(int min, int max)
|
||||||
|
@ -1123,7 +1227,7 @@ void ShowLogo(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup window configuration flags (view FLAGS)
|
// Setup window configuration flags (view FLAGS)
|
||||||
void SetConfigFlags(char flags)
|
void SetConfigFlags(unsigned char flags)
|
||||||
{
|
{
|
||||||
configFlags = flags;
|
configFlags = flags;
|
||||||
|
|
||||||
|
@ -1159,7 +1263,7 @@ bool IsFileExtension(const char *fileName, const char *ext)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the extension for a filename
|
// Get pointer to extension for a filename string
|
||||||
const char *GetExtension(const char *fileName)
|
const char *GetExtension(const char *fileName)
|
||||||
{
|
{
|
||||||
const char *dot = strrchr(fileName, '.');
|
const char *dot = strrchr(fileName, '.');
|
||||||
|
@ -1169,6 +1273,17 @@ const char *GetExtension(const char *fileName)
|
||||||
return (dot + 1);
|
return (dot + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get pointer to filename for a path string
|
||||||
|
const char *GetFileName(const char *filePath)
|
||||||
|
{
|
||||||
|
const char *fileName = strrchr(filePath, '\\');
|
||||||
|
|
||||||
|
if (!fileName || fileName == filePath) return filePath;
|
||||||
|
|
||||||
|
return fileName + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Get directory for a given fileName (with path)
|
// Get directory for a given fileName (with path)
|
||||||
const char *GetDirectoryPath(const char *fileName)
|
const char *GetDirectoryPath(const char *fileName)
|
||||||
{
|
{
|
||||||
|
@ -1649,7 +1764,8 @@ Vector2 GetTouchPosition(int index)
|
||||||
// Initialize display device and framebuffer
|
// Initialize display device and framebuffer
|
||||||
// NOTE: width and height represent the screen (framebuffer) desired size, not actual display size
|
// NOTE: width and height represent the screen (framebuffer) desired size, not actual display size
|
||||||
// If width or height are 0, default display size will be used for framebuffer size
|
// If width or height are 0, default display size will be used for framebuffer size
|
||||||
static void InitGraphicsDevice(int width, int height)
|
// NOTE: returns false in case graphic device could not be created
|
||||||
|
static bool InitGraphicsDevice(int width, int height)
|
||||||
{
|
{
|
||||||
screenWidth = width; // User desired width
|
screenWidth = width; // User desired width
|
||||||
screenHeight = height; // User desired height
|
screenHeight = height; // User desired height
|
||||||
|
@ -1663,12 +1779,22 @@ static void InitGraphicsDevice(int width, int height)
|
||||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
||||||
glfwSetErrorCallback(ErrorCallback);
|
glfwSetErrorCallback(ErrorCallback);
|
||||||
|
|
||||||
if (!glfwInit()) TraceLog(LOG_ERROR, "Failed to initialize GLFW");
|
if (!glfwInit())
|
||||||
|
{
|
||||||
|
TraceLog(LOG_WARNING, "Failed to initialize GLFW");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: Getting video modes is not implemented in emscripten GLFW3 version
|
// NOTE: Getting video modes is not implemented in emscripten GLFW3 version
|
||||||
#if defined(PLATFORM_DESKTOP)
|
#if defined(PLATFORM_DESKTOP)
|
||||||
// Find monitor resolution
|
// Find monitor resolution
|
||||||
const GLFWvidmode *mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
|
GLFWmonitor *monitor = glfwGetPrimaryMonitor();
|
||||||
|
if (!monitor)
|
||||||
|
{
|
||||||
|
TraceLog(LOG_WARNING, "Failed to get monitor");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
|
||||||
|
|
||||||
displayWidth = mode->width;
|
displayWidth = mode->width;
|
||||||
displayHeight = mode->height;
|
displayHeight = mode->height;
|
||||||
|
@ -1774,24 +1900,28 @@ static void InitGraphicsDevice(int width, int height)
|
||||||
// No-fullscreen window creation
|
// No-fullscreen window creation
|
||||||
window = glfwCreateWindow(screenWidth, screenHeight, windowTitle, NULL, NULL);
|
window = glfwCreateWindow(screenWidth, screenHeight, windowTitle, NULL, NULL);
|
||||||
|
|
||||||
|
if (window)
|
||||||
|
{
|
||||||
#if defined(PLATFORM_DESKTOP)
|
#if defined(PLATFORM_DESKTOP)
|
||||||
// Center window on screen
|
// Center window on screen
|
||||||
int windowPosX = displayWidth/2 - screenWidth/2;
|
int windowPosX = displayWidth/2 - screenWidth/2;
|
||||||
int windowPosY = displayHeight/2 - screenHeight/2;
|
int windowPosY = displayHeight/2 - screenHeight/2;
|
||||||
|
|
||||||
if (windowPosX < 0) windowPosX = 0;
|
if (windowPosX < 0) windowPosX = 0;
|
||||||
if (windowPosY < 0) windowPosY = 0;
|
if (windowPosY < 0) windowPosY = 0;
|
||||||
|
|
||||||
glfwSetWindowPos(window, windowPosX, windowPosY);
|
glfwSetWindowPos(window, windowPosX, windowPosY);
|
||||||
#endif
|
#endif
|
||||||
renderWidth = screenWidth;
|
renderWidth = screenWidth;
|
||||||
renderHeight = screenHeight;
|
renderHeight = screenHeight;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!window)
|
if (!window)
|
||||||
{
|
{
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
TraceLog(LOG_ERROR, "GLFW Failed to initialize Window");
|
TraceLog(LOG_WARNING, "GLFW Failed to initialize Window");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1837,7 +1967,7 @@ static void InitGraphicsDevice(int width, int height)
|
||||||
}
|
}
|
||||||
#endif // defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
#endif // defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
||||||
|
|
||||||
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
|
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_UWP)
|
||||||
fullscreen = true;
|
fullscreen = true;
|
||||||
|
|
||||||
// Screen size security check
|
// Screen size security check
|
||||||
|
@ -1880,19 +2010,194 @@ static void InitGraphicsDevice(int width, int height)
|
||||||
EGL_NONE
|
EGL_NONE
|
||||||
};
|
};
|
||||||
|
|
||||||
EGLint contextAttribs[] =
|
const EGLint contextAttribs[] =
|
||||||
{
|
{
|
||||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||||
EGL_NONE
|
EGL_NONE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if defined(PLATFORM_UWP)
|
||||||
|
const EGLint surfaceAttributes[] =
|
||||||
|
{
|
||||||
|
// EGL_ANGLE_SURFACE_RENDER_TO_BACK_BUFFER is part of the same optimization as EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER (see above).
|
||||||
|
// If you have compilation issues with it then please update your Visual Studio templates.
|
||||||
|
EGL_ANGLE_SURFACE_RENDER_TO_BACK_BUFFER, EGL_TRUE,
|
||||||
|
EGL_NONE
|
||||||
|
};
|
||||||
|
|
||||||
|
const EGLint defaultDisplayAttributes[] =
|
||||||
|
{
|
||||||
|
// These are the default display attributes, used to request ANGLE's D3D11 renderer.
|
||||||
|
// eglInitialize will only succeed with these attributes if the hardware supports D3D11 Feature Level 10_0+.
|
||||||
|
EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
|
||||||
|
|
||||||
|
// EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER is an optimization that can have large performance benefits on mobile devices.
|
||||||
|
// Its syntax is subject to change, though. Please update your Visual Studio templates if you experience compilation issues with it.
|
||||||
|
EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE,
|
||||||
|
|
||||||
|
// EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE is an option that enables ANGLE to automatically call
|
||||||
|
// the IDXGIDevice3::Trim method on behalf of the application when it gets suspended.
|
||||||
|
// Calling IDXGIDevice3::Trim when an application is suspended is a Windows Store application certification requirement.
|
||||||
|
EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE,
|
||||||
|
EGL_NONE,
|
||||||
|
};
|
||||||
|
|
||||||
|
const EGLint fl9_3DisplayAttributes[] =
|
||||||
|
{
|
||||||
|
// These can be used to request ANGLE's D3D11 renderer, with D3D11 Feature Level 9_3.
|
||||||
|
// These attributes are used if the call to eglInitialize fails with the default display attributes.
|
||||||
|
EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
|
||||||
|
EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, 9,
|
||||||
|
EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, 3,
|
||||||
|
EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE,
|
||||||
|
EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE,
|
||||||
|
EGL_NONE,
|
||||||
|
};
|
||||||
|
|
||||||
|
const EGLint warpDisplayAttributes[] =
|
||||||
|
{
|
||||||
|
// These attributes can be used to request D3D11 WARP.
|
||||||
|
// They are used if eglInitialize fails with both the default display attributes and the 9_3 display attributes.
|
||||||
|
EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
|
||||||
|
EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE,
|
||||||
|
EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE,
|
||||||
|
EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE,
|
||||||
|
EGL_NONE,
|
||||||
|
};
|
||||||
|
|
||||||
|
EGLConfig config = NULL;
|
||||||
|
|
||||||
|
// eglGetPlatformDisplayEXT is an alternative to eglGetDisplay. It allows us to pass in display attributes, used to configure D3D11.
|
||||||
|
PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = (PFNEGLGETPLATFORMDISPLAYEXTPROC)(eglGetProcAddress("eglGetPlatformDisplayEXT"));
|
||||||
|
if (!eglGetPlatformDisplayEXT)
|
||||||
|
{
|
||||||
|
TraceLog(LOG_WARNING, "Failed to get function eglGetPlatformDisplayEXT");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// To initialize the display, we make three sets of calls to eglGetPlatformDisplayEXT and eglInitialize, with varying
|
||||||
|
// parameters passed to eglGetPlatformDisplayEXT:
|
||||||
|
// 1) The first calls uses "defaultDisplayAttributes" as a parameter. This corresponds to D3D11 Feature Level 10_0+.
|
||||||
|
// 2) If eglInitialize fails for step 1 (e.g. because 10_0+ isn't supported by the default GPU), then we try again
|
||||||
|
// using "fl9_3DisplayAttributes". This corresponds to D3D11 Feature Level 9_3.
|
||||||
|
// 3) If eglInitialize fails for step 2 (e.g. because 9_3+ isn't supported by the default GPU), then we try again
|
||||||
|
// using "warpDisplayAttributes". This corresponds to D3D11 Feature Level 11_0 on WARP, a D3D11 software rasterizer.
|
||||||
|
//
|
||||||
|
|
||||||
|
// This tries to initialize EGL to D3D11 Feature Level 10_0+. See above comment for details.
|
||||||
|
display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, defaultDisplayAttributes);
|
||||||
|
if (display == EGL_NO_DISPLAY)
|
||||||
|
{
|
||||||
|
TraceLog(LOG_WARNING, "Failed to initialize EGL display");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eglInitialize(display, NULL, NULL) == EGL_FALSE)
|
||||||
|
{
|
||||||
|
// This tries to initialize EGL to D3D11 Feature Level 9_3, if 10_0+ is unavailable (e.g. on some mobile devices).
|
||||||
|
display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, fl9_3DisplayAttributes);
|
||||||
|
if (display == EGL_NO_DISPLAY)
|
||||||
|
{
|
||||||
|
TraceLog(LOG_WARNING, "Failed to initialize EGL display");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eglInitialize(display, NULL, NULL) == EGL_FALSE)
|
||||||
|
{
|
||||||
|
// This initializes EGL to D3D11 Feature Level 11_0 on WARP, if 9_3+ is unavailable on the default GPU.
|
||||||
|
display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, warpDisplayAttributes);
|
||||||
|
if (display == EGL_NO_DISPLAY)
|
||||||
|
{
|
||||||
|
TraceLog(LOG_WARNING, "Failed to initialize EGL display");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eglInitialize(display, NULL, NULL) == EGL_FALSE)
|
||||||
|
{
|
||||||
|
// If all of the calls to eglInitialize returned EGL_FALSE then an error has occurred.
|
||||||
|
TraceLog(LOG_WARNING, "Failed to initialize EGL");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//SetupFramebufferSize(displayWidth, displayHeight);
|
||||||
|
|
||||||
|
EGLint numConfigs = 0;
|
||||||
|
if ((eglChooseConfig(display, framebufferAttribs, &config, 1, &numConfigs) == EGL_FALSE) || (numConfigs == 0))
|
||||||
|
{
|
||||||
|
TraceLog(LOG_WARNING, "Failed to choose first EGLConfig");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a PropertySet and initialize with the EGLNativeWindowType.
|
||||||
|
//PropertySet^ surfaceCreationProperties = ref new PropertySet();
|
||||||
|
//surfaceCreationProperties->Insert(ref new String(EGLNativeWindowTypeProperty), window); // CoreWindow^ window
|
||||||
|
|
||||||
|
// You can configure the surface to render at a lower resolution and be scaled up to
|
||||||
|
// the full window size. The scaling is often free on mobile hardware.
|
||||||
|
//
|
||||||
|
// One way to configure the SwapChainPanel is to specify precisely which resolution it should render at.
|
||||||
|
// Size customRenderSurfaceSize = Size(800, 600);
|
||||||
|
// surfaceCreationProperties->Insert(ref new String(EGLRenderSurfaceSizeProperty), PropertyValue::CreateSize(customRenderSurfaceSize));
|
||||||
|
//
|
||||||
|
// Another way is to tell the SwapChainPanel to render at a certain scale factor compared to its size.
|
||||||
|
// e.g. if the SwapChainPanel is 1920x1280 then setting a factor of 0.5f will make the app render at 960x640
|
||||||
|
// float customResolutionScale = 0.5f;
|
||||||
|
// surfaceCreationProperties->Insert(ref new String(EGLRenderResolutionScaleProperty), PropertyValue::CreateSingle(customResolutionScale));
|
||||||
|
|
||||||
|
|
||||||
|
// eglCreateWindowSurface() requires a EGLNativeWindowType parameter,
|
||||||
|
// In Windows platform: typedef HWND EGLNativeWindowType;
|
||||||
|
|
||||||
|
|
||||||
|
// Property: EGLNativeWindowTypeProperty
|
||||||
|
// Type: IInspectable
|
||||||
|
// Description: Set this property to specify the window type to use for creating a surface.
|
||||||
|
// If this property is missing, surface creation will fail.
|
||||||
|
//
|
||||||
|
//const wchar_t EGLNativeWindowTypeProperty[] = L"EGLNativeWindowTypeProperty";
|
||||||
|
|
||||||
|
//https://stackoverflow.com/questions/46550182/how-to-create-eglsurface-using-c-winrt-and-angle
|
||||||
|
|
||||||
|
//surface = eglCreateWindowSurface(display, config, reinterpret_cast<IInspectable*>(surfaceCreationProperties), surfaceAttributes);
|
||||||
|
surface = eglCreateWindowSurface(display, config, uwpWindow, surfaceAttributes);
|
||||||
|
if (surface == EGL_NO_SURFACE)
|
||||||
|
{
|
||||||
|
TraceLog(LOG_WARNING, "Failed to create EGL fullscreen surface");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs);
|
||||||
|
if (context == EGL_NO_CONTEXT)
|
||||||
|
{
|
||||||
|
TraceLog(LOG_WARNING, "Failed to create EGL context");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get EGL display window size
|
||||||
|
eglQuerySurface(display, surface, EGL_WIDTH, &screenWidth);
|
||||||
|
eglQuerySurface(display, surface, EGL_HEIGHT, &screenHeight);
|
||||||
|
|
||||||
|
#else // PLATFORM_ANDROID, PLATFORM_RPI
|
||||||
EGLint numConfigs;
|
EGLint numConfigs;
|
||||||
|
|
||||||
// Get an EGL display connection
|
// Get an EGL display connection
|
||||||
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||||
|
if (display == EGL_NO_DISPLAY)
|
||||||
|
{
|
||||||
|
TraceLog(LOG_WARNING, "Failed to initialize EGL display");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize the EGL display connection
|
// Initialize the EGL display connection
|
||||||
eglInitialize(display, NULL, NULL);
|
if (eglInitialize(display, NULL, NULL) == EGL_FALSE)
|
||||||
|
{
|
||||||
|
// If all of the calls to eglInitialize returned EGL_FALSE then an error has occurred.
|
||||||
|
TraceLog(LOG_WARNING, "Failed to initialize EGL");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Get an appropriate EGL framebuffer configuration
|
// Get an appropriate EGL framebuffer configuration
|
||||||
eglChooseConfig(display, framebufferAttribs, &config, 1, &numConfigs);
|
eglChooseConfig(display, framebufferAttribs, &config, 1, &numConfigs);
|
||||||
|
@ -1902,6 +2207,12 @@ static void InitGraphicsDevice(int width, int height)
|
||||||
|
|
||||||
// Create an EGL rendering context
|
// Create an EGL rendering context
|
||||||
context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs);
|
context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs);
|
||||||
|
if (context == EGL_NO_CONTEXT)
|
||||||
|
{
|
||||||
|
TraceLog(LOG_WARNING, "Failed to create EGL context");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Create an EGL window surface
|
// Create an EGL window surface
|
||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
|
@ -1969,7 +2280,8 @@ static void InitGraphicsDevice(int width, int height)
|
||||||
|
|
||||||
if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)
|
if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)
|
||||||
{
|
{
|
||||||
TraceLog(LOG_ERROR, "Unable to attach EGL rendering context to EGL surface");
|
TraceLog(LOG_WARNING, "Unable to attach EGL rendering context to EGL surface");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1985,6 +2297,9 @@ static void InitGraphicsDevice(int width, int height)
|
||||||
}
|
}
|
||||||
#endif // defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
|
#endif // defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
|
||||||
|
|
||||||
|
renderWidth = screenWidth;
|
||||||
|
renderHeight = screenHeight;
|
||||||
|
|
||||||
// Initialize OpenGL context (states and resources)
|
// Initialize OpenGL context (states and resources)
|
||||||
// NOTE: screenWidth and screenHeight not used, just stored as globals
|
// NOTE: screenWidth and screenHeight not used, just stored as globals
|
||||||
rlglInit(screenWidth, screenHeight);
|
rlglInit(screenWidth, screenHeight);
|
||||||
|
@ -2005,6 +2320,7 @@ static void InitGraphicsDevice(int width, int height)
|
||||||
#if defined(PLATFORM_ANDROID)
|
#if defined(PLATFORM_ANDROID)
|
||||||
windowReady = true; // IMPORTANT!
|
windowReady = true; // IMPORTANT!
|
||||||
#endif
|
#endif
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set viewport parameters
|
// Set viewport parameters
|
||||||
|
@ -2120,22 +2436,6 @@ static void InitTimer(void)
|
||||||
previousTime = GetTime(); // Get time as double
|
previousTime = GetTime(); // Get time as double
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get current time measure (in seconds) since InitTimer()
|
|
||||||
static double GetTime(void)
|
|
||||||
{
|
|
||||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
|
||||||
return glfwGetTime();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
|
|
||||||
struct timespec ts;
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
|
||||||
uint64_t time = (uint64_t)ts.tv_sec*1000000000LLU + (uint64_t)ts.tv_nsec;
|
|
||||||
|
|
||||||
return (double)(time - baseTime)*1e-9;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for some milliseconds (stop program execution)
|
// Wait for some milliseconds (stop program execution)
|
||||||
// NOTE: Sleep() granularity could be around 10 ms, it means, Sleep() could
|
// NOTE: Sleep() granularity could be around 10 ms, it means, Sleep() could
|
||||||
// take longer than expected... for that reason we use the busy wait loop
|
// take longer than expected... for that reason we use the busy wait loop
|
||||||
|
@ -2369,7 +2669,7 @@ static void SwapBuffers(void)
|
||||||
glfwSwapBuffers(window);
|
glfwSwapBuffers(window);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
|
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_UWP)
|
||||||
eglSwapBuffers(display, surface);
|
eglSwapBuffers(display, surface);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -2433,7 +2733,9 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
currentKeyState[key] = action;
|
currentKeyState[key] = action;
|
||||||
if (action == GLFW_PRESS) lastKeyPressed = key;
|
|
||||||
|
// NOTE: lastKeyPressed already registered on CharCallback()
|
||||||
|
//if (action == GLFW_PRESS) lastKeyPressed = key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2499,12 +2801,15 @@ static void MouseCursorPosCallback(GLFWwindow *window, double x, double y)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// GLFW3 Char Key Callback, runs on key pressed (get char value)
|
// GLFW3 Char Key Callback, runs on key down (get unicode char value)
|
||||||
static void CharCallback(GLFWwindow *window, unsigned int key)
|
static void CharCallback(GLFWwindow *window, unsigned int key)
|
||||||
{
|
{
|
||||||
|
// NOTE: Registers any key down considering OS keyboard layout but
|
||||||
|
// do not detects action events, those should be managed by user...
|
||||||
|
// https://github.com/glfw/glfw/issues/668#issuecomment-166794907
|
||||||
|
// http://www.glfw.org/docs/latest/input_guide.html#input_char
|
||||||
|
|
||||||
lastKeyPressed = key;
|
lastKeyPressed = key;
|
||||||
|
|
||||||
//TraceLog(LOG_INFO, "Char Callback Key pressed: %i\n", key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GLFW3 CursorEnter Callback, when cursor enters the window
|
// GLFW3 CursorEnter Callback, when cursor enters the window
|
||||||
|
@ -2604,6 +2909,9 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
|
||||||
{
|
{
|
||||||
// Init graphics device (display device and OpenGL context)
|
// Init graphics device (display device and OpenGL context)
|
||||||
InitGraphicsDevice(screenWidth, screenHeight);
|
InitGraphicsDevice(screenWidth, screenHeight);
|
||||||
|
|
||||||
|
// Init hi-res timer
|
||||||
|
InitTimer();
|
||||||
|
|
||||||
#if defined(SUPPORT_DEFAULT_FONT)
|
#if defined(SUPPORT_DEFAULT_FONT)
|
||||||
// Load default font
|
// Load default font
|
||||||
|
@ -2626,9 +2934,6 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Init hi-res timer
|
|
||||||
InitTimer();
|
|
||||||
|
|
||||||
// raylib logo appearing animation (if enabled)
|
// raylib logo appearing animation (if enabled)
|
||||||
if (showLogo)
|
if (showLogo)
|
||||||
{
|
{
|
||||||
|
|
|
@ -211,6 +211,13 @@ func GetFrameTime() float32 {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTime - Return time in seconds
|
||||||
|
func GetTime() float32 {
|
||||||
|
ret := C.GetTime()
|
||||||
|
v := (float32)(ret)
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
// GetColor - Returns a Color struct from hexadecimal value
|
// GetColor - Returns a Color struct from hexadecimal value
|
||||||
func GetColor(hexValue int32) Color {
|
func GetColor(hexValue int32) Color {
|
||||||
chexValue := (C.int)(hexValue)
|
chexValue := (C.int)(hexValue)
|
||||||
|
@ -219,14 +226,23 @@ func GetColor(hexValue int32) Color {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHexValue - Returns hexadecimal value for a Color
|
// ColorToInt - Returns hexadecimal value for a Color
|
||||||
func GetHexValue(color Color) int32 {
|
func ColorToInt(color Color) int32 {
|
||||||
ccolor := color.cptr()
|
ccolor := color.cptr()
|
||||||
ret := C.GetHexValue(*ccolor)
|
ret := C.ColorToInt(*ccolor)
|
||||||
v := (int32)(ret)
|
v := (int32)(ret)
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ColorToHSV - Returns HSV values for a Color
|
||||||
|
// NOTE: Hue is returned as degrees [0..360]
|
||||||
|
func ColorToHSV(color Color) Vector3 {
|
||||||
|
ccolor := color.cptr()
|
||||||
|
ret := C.ColorToHSV(*ccolor)
|
||||||
|
v := newVector3FromPointer(unsafe.Pointer(&ret))
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
// ColorToFloat - Converts Color to float32 slice and normalizes
|
// ColorToFloat - Converts Color to float32 slice and normalizes
|
||||||
func ColorToFloat(color Color) []float32 {
|
func ColorToFloat(color Color) []float32 {
|
||||||
data := make([]float32, 0)
|
data := make([]float32, 0)
|
||||||
|
@ -297,7 +313,7 @@ func ShowLogo() {
|
||||||
|
|
||||||
// SetConfigFlags - Setup some window configuration flags
|
// SetConfigFlags - Setup some window configuration flags
|
||||||
func SetConfigFlags(flags byte) {
|
func SetConfigFlags(flags byte) {
|
||||||
cflags := (C.char)(flags)
|
cflags := (C.uchar)(flags)
|
||||||
C.SetConfigFlags(cflags)
|
C.SetConfigFlags(cflags)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
119
raylib/external/mini_al.h
vendored
119
raylib/external/mini_al.h
vendored
|
@ -1,5 +1,5 @@
|
||||||
// Audio playback and capture library. Public domain. See "unlicense" statement at the end of this file.
|
// Audio playback and capture library. Public domain. See "unlicense" statement at the end of this file.
|
||||||
// mini_al - v0.x - 2017-xx-xx
|
// mini_al - v0.6b - 2018-02-03
|
||||||
//
|
//
|
||||||
// David Reid - davidreidsoftware@gmail.com
|
// David Reid - davidreidsoftware@gmail.com
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@
|
||||||
//
|
//
|
||||||
// Building (BSD)
|
// Building (BSD)
|
||||||
// --------------
|
// --------------
|
||||||
// The BSD build uses OSS and should Just Work without any linking nor include path configuration.
|
// BSD build uses OSS. Requires linking to -lossaudio on {Open,Net}BSD, but not FreeBSD.
|
||||||
//
|
//
|
||||||
// Building (Emscripten)
|
// Building (Emscripten)
|
||||||
// ---------------------
|
// ---------------------
|
||||||
|
@ -1422,12 +1422,13 @@ mal_uint32 mal_src_read_frames(mal_src* pSRC, mal_uint32 frameCount, void* pFram
|
||||||
// The same mal_src_read_frames() with extra control over whether or not the internal buffers should be flushed at the end.
|
// The same mal_src_read_frames() with extra control over whether or not the internal buffers should be flushed at the end.
|
||||||
//
|
//
|
||||||
// Internally there exists a buffer that keeps track of the previous and next samples for sample rate conversion. The simple
|
// Internally there exists a buffer that keeps track of the previous and next samples for sample rate conversion. The simple
|
||||||
// version of this function does _not_ flush this buffer because otherwise it causes clitches for streaming based conversion
|
// version of this function does _not_ flush this buffer because otherwise it causes glitches for streaming based conversion
|
||||||
// pipelines. The problem, however, is that sometimes you need those last few samples (such as if you're doing a bulk conversion
|
// pipelines. The problem, however, is that sometimes you need those last few samples (such as if you're doing a bulk conversion
|
||||||
// of a static file). Enabling flushing will fix this for you.
|
// of a static file). Enabling flushing will fix this for you.
|
||||||
mal_uint32 mal_src_read_frames_ex(mal_src* pSRC, mal_uint32 frameCount, void* pFramesOut, mal_bool32 flush);
|
mal_uint32 mal_src_read_frames_ex(mal_src* pSRC, mal_uint32 frameCount, void* pFramesOut, mal_bool32 flush);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// DSP
|
// DSP
|
||||||
|
@ -1465,6 +1466,8 @@ mal_uint32 mal_convert_frames(void* pOut, mal_format formatOut, mal_uint32 chann
|
||||||
// Helper for initializing a mal_dsp_config object.
|
// Helper for initializing a mal_dsp_config object.
|
||||||
mal_dsp_config mal_dsp_config_init(mal_format formatIn, mal_uint32 channelsIn, mal_uint32 sampleRateIn, mal_format formatOut, mal_uint32 channelsOut, mal_uint32 sampleRateOut);
|
mal_dsp_config mal_dsp_config_init(mal_format formatIn, mal_uint32 channelsIn, mal_uint32 sampleRateIn, mal_format formatOut, mal_uint32 channelsOut, mal_uint32 sampleRateOut);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Utiltities
|
// Utiltities
|
||||||
|
@ -1554,6 +1557,10 @@ void mal_pcm_convert(void* pOut, mal_format formatOut, const void* pIn, mal_form
|
||||||
#include <string.h> // For memset()
|
#include <string.h> // For memset()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(MAL_APPLE) && (__MAC_OS_X_VERSION_MIN_REQUIRED < 101200)
|
||||||
|
#include <mach/mach_time.h> // For mach_absolute_time()
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef MAL_POSIX
|
#ifdef MAL_POSIX
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
@ -1635,7 +1642,14 @@ void mal_pcm_convert(void* pOut, mal_format formatOut, const void* pIn, mal_form
|
||||||
#define MAL_HAS_OPENSL // Like OSS, OpenSL is the only supported backend for Android. It must be present.
|
#define MAL_HAS_OPENSL // Like OSS, OpenSL is the only supported backend for Android. It must be present.
|
||||||
#endif
|
#endif
|
||||||
#ifdef MAL_ENABLE_OPENAL
|
#ifdef MAL_ENABLE_OPENAL
|
||||||
#define MAL_HAS_OPENAL // mini_al inlines the necessary OpenAL stuff.
|
#define MAL_HAS_OPENAL
|
||||||
|
#ifdef MAL_NO_RUNTIME_LINKING
|
||||||
|
#ifdef __has_include
|
||||||
|
#if !__has_include(<AL/al.h>)
|
||||||
|
#undef MAL_HAS_OPENAL
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#ifdef MAL_ENABLE_SDL
|
#ifdef MAL_ENABLE_SDL
|
||||||
#define MAL_HAS_SDL
|
#define MAL_HAS_SDL
|
||||||
|
@ -1764,7 +1778,10 @@ typedef HWND (WINAPI * MAL_PFN_GetDesktopWindow)();
|
||||||
#define mal_buffer_frame_capacity(buffer, channels, format) (sizeof(buffer) / mal_get_sample_size_in_bytes(format) / (channels))
|
#define mal_buffer_frame_capacity(buffer, channels, format) (sizeof(buffer) / mal_get_sample_size_in_bytes(format) / (channels))
|
||||||
|
|
||||||
// Some of these string utility functions are unused on some platforms.
|
// Some of these string utility functions are unused on some platforms.
|
||||||
#if defined(__GNUC__)
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable:4505)
|
||||||
|
#elif defined(__GNUC__)
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||||
#endif
|
#endif
|
||||||
|
@ -1962,7 +1979,9 @@ static int mal_strcmp(const char* str1, const char* str2)
|
||||||
|
|
||||||
return ((unsigned char*)str1)[0] - ((unsigned char*)str2)[0];
|
return ((unsigned char*)str1)[0] - ((unsigned char*)str2)[0];
|
||||||
}
|
}
|
||||||
#if defined(__GNUC__)
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(pop)
|
||||||
|
#elif defined(__GNUC__)
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2067,6 +2086,24 @@ double mal_timer_get_time_in_seconds(mal_timer* pTimer)
|
||||||
|
|
||||||
return (counter.QuadPart - pTimer->counter) / (double)g_mal_TimerFrequency.QuadPart;
|
return (counter.QuadPart - pTimer->counter) / (double)g_mal_TimerFrequency.QuadPart;
|
||||||
}
|
}
|
||||||
|
#elif defined(MAL_APPLE) && (__MAC_OS_X_VERSION_MIN_REQUIRED < 101200)
|
||||||
|
static uint64_t g_mal_TimerFrequency = 0;
|
||||||
|
void mal_timer_init(mal_timer* pTimer)
|
||||||
|
{
|
||||||
|
mach_timebase_info_data_t baseTime;
|
||||||
|
mach_timebase_info(&baseTime);
|
||||||
|
g_mal_TimerFrequency = (baseTime.denom * 1e9) / baseTime.numer;
|
||||||
|
|
||||||
|
pTimer->counter = mach_absolute_time();
|
||||||
|
}
|
||||||
|
|
||||||
|
double mal_timer_get_time_in_seconds(mal_timer* pTimer)
|
||||||
|
{
|
||||||
|
uint64_t newTimeCounter = mach_absolute_time();
|
||||||
|
uint64_t oldTimeCounter = pTimer->counter;
|
||||||
|
|
||||||
|
return (newTimeCounter - oldTimeCounter) / g_mal_TimerFrequency;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
void mal_timer_init(mal_timer* pTimer)
|
void mal_timer_init(mal_timer* pTimer)
|
||||||
{
|
{
|
||||||
|
@ -2746,10 +2783,10 @@ static mal_result mal_context__try_get_device_name_by_id(mal_context* pContext,
|
||||||
} break;
|
} break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef MAL_HAS_COREAUDIO
|
#ifdef MAL_HAS_COREAUDIO
|
||||||
case mal_backend_coreaudio
|
//case mal_backend_coreaudio:
|
||||||
{
|
//{
|
||||||
// TODO: Implement me.
|
// // TODO: Implement me.
|
||||||
} break;
|
//} break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef MAL_HAS_OSS
|
#ifdef MAL_HAS_OSS
|
||||||
case mal_backend_oss:
|
case mal_backend_oss:
|
||||||
|
@ -5486,8 +5523,8 @@ struct
|
||||||
const char* name;
|
const char* name;
|
||||||
float scale;
|
float scale;
|
||||||
} g_malDefaultBufferSizeScalesALSA[] = {
|
} g_malDefaultBufferSizeScalesALSA[] = {
|
||||||
{"bcm2835 IEC958/HDMI", 32},
|
{"bcm2835 IEC958/HDMI", 20},
|
||||||
{"bcm2835 ALSA", 32}
|
{"bcm2835 ALSA", 20}
|
||||||
};
|
};
|
||||||
|
|
||||||
static float mal_find_default_buffer_size_scale__alsa(const char* deviceName)
|
static float mal_find_default_buffer_size_scale__alsa(const char* deviceName)
|
||||||
|
@ -6697,6 +6734,10 @@ static mal_result mal_device__main_loop__alsa(mal_device* pDevice)
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/soundcard.h>
|
#include <sys/soundcard.h>
|
||||||
|
|
||||||
|
#ifndef SNDCTL_DSP_HALT
|
||||||
|
#define SNDCTL_DSP_HALT SNDCTL_DSP_RESET
|
||||||
|
#endif
|
||||||
|
|
||||||
int mal_open_temp_device__oss()
|
int mal_open_temp_device__oss()
|
||||||
{
|
{
|
||||||
// The OSS sample code uses "/dev/mixer" as the device for getting system properties so I'm going to do the same.
|
// The OSS sample code uses "/dev/mixer" as the device for getting system properties so I'm going to do the same.
|
||||||
|
@ -8833,6 +8874,8 @@ mal_result mal_device_init__sdl(mal_context* pContext, mal_device_type type, mal
|
||||||
mal_assert(pConfig != NULL);
|
mal_assert(pConfig != NULL);
|
||||||
mal_assert(pDevice != NULL);
|
mal_assert(pDevice != NULL);
|
||||||
|
|
||||||
|
(void)pContext;
|
||||||
|
|
||||||
// SDL wants the buffer size to be a power of 2. The SDL_AudioSpec property for this is only a Uint16, so we need
|
// SDL wants the buffer size to be a power of 2. The SDL_AudioSpec property for this is only a Uint16, so we need
|
||||||
// to explicitly clamp this because it will be easy to overflow.
|
// to explicitly clamp this because it will be easy to overflow.
|
||||||
mal_uint32 bufferSize = pConfig->bufferSizeInFrames;
|
mal_uint32 bufferSize = pConfig->bufferSizeInFrames;
|
||||||
|
@ -10750,7 +10793,7 @@ static void mal_dsp_mix_channels__inc(float* pFramesOut, mal_uint32 channelsOut,
|
||||||
(void)channelMapOut;
|
(void)channelMapOut;
|
||||||
(void)channelMapIn;
|
(void)channelMapIn;
|
||||||
|
|
||||||
if (mode == mal_channel_mix_mode_basic) {\
|
if (mode == mal_channel_mix_mode_basic) {
|
||||||
// Basic mode is where we just zero out extra channels.
|
// Basic mode is where we just zero out extra channels.
|
||||||
for (mal_uint32 iFrame = 0; iFrame < frameCount; ++iFrame) {
|
for (mal_uint32 iFrame = 0; iFrame < frameCount; ++iFrame) {
|
||||||
switch (channelsIn) {
|
switch (channelsIn) {
|
||||||
|
@ -10775,23 +10818,23 @@ static void mal_dsp_mix_channels__inc(float* pFramesOut, mal_uint32 channelsOut,
|
||||||
|
|
||||||
// Zero out extra channels.
|
// Zero out extra channels.
|
||||||
switch (channelsOut - channelsIn) {
|
switch (channelsOut - channelsIn) {
|
||||||
case 17: pFramesOut[iFrame*channelsOut+16] = 0;
|
case 17: pFramesOut[iFrame*channelsOut+16 + channelsIn] = 0;
|
||||||
case 16: pFramesOut[iFrame*channelsOut+15] = 0;
|
case 16: pFramesOut[iFrame*channelsOut+15 + channelsIn] = 0;
|
||||||
case 15: pFramesOut[iFrame*channelsOut+14] = 0;
|
case 15: pFramesOut[iFrame*channelsOut+14 + channelsIn] = 0;
|
||||||
case 14: pFramesOut[iFrame*channelsOut+13] = 0;
|
case 14: pFramesOut[iFrame*channelsOut+13 + channelsIn] = 0;
|
||||||
case 13: pFramesOut[iFrame*channelsOut+12] = 0;
|
case 13: pFramesOut[iFrame*channelsOut+12 + channelsIn] = 0;
|
||||||
case 12: pFramesOut[iFrame*channelsOut+11] = 0;
|
case 12: pFramesOut[iFrame*channelsOut+11 + channelsIn] = 0;
|
||||||
case 11: pFramesOut[iFrame*channelsOut+10] = 0;
|
case 11: pFramesOut[iFrame*channelsOut+10 + channelsIn] = 0;
|
||||||
case 10: pFramesOut[iFrame*channelsOut+ 9] = 0;
|
case 10: pFramesOut[iFrame*channelsOut+ 9 + channelsIn] = 0;
|
||||||
case 9: pFramesOut[iFrame*channelsOut+ 8] = 0;
|
case 9: pFramesOut[iFrame*channelsOut+ 8 + channelsIn] = 0;
|
||||||
case 8: pFramesOut[iFrame*channelsOut+ 7] = 0;
|
case 8: pFramesOut[iFrame*channelsOut+ 7 + channelsIn] = 0;
|
||||||
case 7: pFramesOut[iFrame*channelsOut+ 6] = 0;
|
case 7: pFramesOut[iFrame*channelsOut+ 6 + channelsIn] = 0;
|
||||||
case 6: pFramesOut[iFrame*channelsOut+ 5] = 0;
|
case 6: pFramesOut[iFrame*channelsOut+ 5 + channelsIn] = 0;
|
||||||
case 5: pFramesOut[iFrame*channelsOut+ 4] = 0;
|
case 5: pFramesOut[iFrame*channelsOut+ 4 + channelsIn] = 0;
|
||||||
case 4: pFramesOut[iFrame*channelsOut+ 3] = 0;
|
case 4: pFramesOut[iFrame*channelsOut+ 3 + channelsIn] = 0;
|
||||||
case 3: pFramesOut[iFrame*channelsOut+ 2] = 0;
|
case 3: pFramesOut[iFrame*channelsOut+ 2 + channelsIn] = 0;
|
||||||
case 2: pFramesOut[iFrame*channelsOut+ 1] = 0;
|
case 2: pFramesOut[iFrame*channelsOut+ 1 + channelsIn] = 0;
|
||||||
case 1: pFramesOut[iFrame*channelsOut+ 0] = 0;
|
case 1: pFramesOut[iFrame*channelsOut+ 0 + channelsIn] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -10822,10 +10865,10 @@ static void mal_dsp_mix_channels__inc(float* pFramesOut, mal_uint32 channelsOut,
|
||||||
}
|
}
|
||||||
} else if (channelsIn == 2) {
|
} else if (channelsIn == 2) {
|
||||||
// TODO: Implement an optimized stereo conversion.
|
// TODO: Implement an optimized stereo conversion.
|
||||||
mal_dsp_mix_channels__dec(pFramesOut, channelsOut, channelMapOut, pFramesIn, channelsIn, channelMapIn, frameCount, mal_channel_mix_mode_basic);
|
mal_dsp_mix_channels__inc(pFramesOut, channelsOut, channelMapOut, pFramesIn, channelsIn, channelMapIn, frameCount, mal_channel_mix_mode_basic);
|
||||||
} else {
|
} else {
|
||||||
// Fall back to basic mixing mode.
|
// Fall back to basic mixing mode.
|
||||||
mal_dsp_mix_channels__dec(pFramesOut, channelsOut, channelMapOut, pFramesIn, channelsIn, channelMapIn, frameCount, mal_channel_mix_mode_basic);
|
mal_dsp_mix_channels__inc(pFramesOut, channelsOut, channelMapOut, pFramesIn, channelsIn, channelMapIn, frameCount, mal_channel_mix_mode_basic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11484,7 +11527,15 @@ void mal_pcm_f32_to_s32(int* pOut, const float* pIn, unsigned int count)
|
||||||
// REVISION HISTORY
|
// REVISION HISTORY
|
||||||
// ================
|
// ================
|
||||||
//
|
//
|
||||||
// v0.x - 2017-xx-xx
|
// v0.6b - 2018-02-03
|
||||||
|
// - Fix some warnings when compiling with Visual C++.
|
||||||
|
//
|
||||||
|
// v0.6a - 2018-01-26
|
||||||
|
// - Fix errors with channel mixing when increasing the channel count.
|
||||||
|
// - Improvements to the build system for the OpenAL backend.
|
||||||
|
// - Documentation fixes.
|
||||||
|
//
|
||||||
|
// v0.6 - 2017-12-08
|
||||||
// - API CHANGE: Expose and improve mutex APIs. If you were using the mutex APIs before this version you'll
|
// - API CHANGE: Expose and improve mutex APIs. If you were using the mutex APIs before this version you'll
|
||||||
// need to update.
|
// need to update.
|
||||||
// - API CHANGE: SRC and DSP callbacks now take a pointer to a mal_src and mal_dsp object respectively.
|
// - API CHANGE: SRC and DSP callbacks now take a pointer to a mal_src and mal_dsp object respectively.
|
||||||
|
@ -11497,7 +11548,7 @@ void mal_pcm_f32_to_s32(int* pOut, const float* pIn, unsigned int count)
|
||||||
// - Add mal_convert_frames(). This is a high-level helper API for performing a one-time, bulk conversion of
|
// - Add mal_convert_frames(). This is a high-level helper API for performing a one-time, bulk conversion of
|
||||||
// audio data to a different format.
|
// audio data to a different format.
|
||||||
// - Improvements to f32 -> u8/s16/s24/s32 conversion routines.
|
// - Improvements to f32 -> u8/s16/s24/s32 conversion routines.
|
||||||
// - Fix a bug where the wrong value is returned from mal_device_start() for the OpenSL and SDL backends.
|
// - Fix a bug where the wrong value is returned from mal_device_start() for the OpenSL backend.
|
||||||
// - Fixes and improvements for Raspberry Pi.
|
// - Fixes and improvements for Raspberry Pi.
|
||||||
// - Warning fixes.
|
// - Warning fixes.
|
||||||
//
|
//
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
*
|
*
|
||||||
* LICENSE: zlib/libpng
|
* LICENSE: zlib/libpng
|
||||||
*
|
*
|
||||||
* Copyright (c) 2014-2017 Ramon Santamaria (@raysan5)
|
* Copyright (c) 2014-2018 Ramon Santamaria (@raysan5)
|
||||||
*
|
*
|
||||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
* 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.
|
* will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
@ -522,7 +522,7 @@ static double GetCurrentTime(void)
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
unsigned long long int clockFrequency, currentTime;
|
unsigned long long int clockFrequency, currentTime;
|
||||||
|
|
||||||
QueryPerformanceFrequency(&clockFrequency);
|
QueryPerformanceFrequency(&clockFrequency); // BE CAREFUL: Costly operation!
|
||||||
QueryPerformanceCounter(¤tTime);
|
QueryPerformanceCounter(¤tTime);
|
||||||
|
|
||||||
time = (double)currentTime/clockFrequency*1000.0f; // Time in miliseconds
|
time = (double)currentTime/clockFrequency*1000.0f; // Time in miliseconds
|
||||||
|
@ -538,8 +538,8 @@ static double GetCurrentTime(void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
//#define CLOCK_REALTIME CALENDAR_CLOCK
|
//#define CLOCK_REALTIME CALENDAR_CLOCK // returns UTC time since 1970-01-01
|
||||||
//#define CLOCK_MONOTONIC SYSTEM_CLOCK
|
//#define CLOCK_MONOTONIC SYSTEM_CLOCK // returns the time since boot time
|
||||||
|
|
||||||
clock_serv_t cclock;
|
clock_serv_t cclock;
|
||||||
mach_timespec_t now;
|
mach_timespec_t now;
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
// +build !js
|
|
||||||
|
|
||||||
/**********************************************************************************************
|
/**********************************************************************************************
|
||||||
*
|
*
|
||||||
* raylib.models - Basic functions to deal with 3d shapes and 3d models
|
* raylib.models - Basic functions to deal with 3d shapes and 3d models
|
||||||
|
@ -19,7 +17,7 @@
|
||||||
*
|
*
|
||||||
* LICENSE: zlib/libpng
|
* LICENSE: zlib/libpng
|
||||||
*
|
*
|
||||||
* Copyright (c) 2014-2017 Ramon Santamaria (@raysan5)
|
* Copyright (c) 2014-2018 Ramon Santamaria (@raysan5)
|
||||||
*
|
*
|
||||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
* 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.
|
* will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
@ -47,9 +45,7 @@
|
||||||
|
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
|
|
||||||
#if defined(PLATFORM_ANDROID)
|
#include "utils.h" // Required for: fopen() Android mapping
|
||||||
#include "utils.h" // Android fopen function map
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h> // Required for: FILE, fopen(), fclose(), fscanf(), feof(), rewind(), fgets()
|
#include <stdio.h> // Required for: FILE, fopen(), fclose(), fscanf(), feof(), rewind(), fgets()
|
||||||
#include <stdlib.h> // Required for: malloc(), free()
|
#include <stdlib.h> // Required for: malloc(), free()
|
||||||
|
@ -59,7 +55,7 @@
|
||||||
#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2
|
#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2
|
||||||
|
|
||||||
#define PAR_SHAPES_IMPLEMENTATION
|
#define PAR_SHAPES_IMPLEMENTATION
|
||||||
#include "external/par_shapes.h"
|
#include "external/par_shapes.h" // Shapes 3d parametric generation
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Defines and Macros
|
// Defines and Macros
|
||||||
|
|
|
@ -178,11 +178,23 @@ const (
|
||||||
KeySpace = 32
|
KeySpace = 32
|
||||||
KeyEscape = 256
|
KeyEscape = 256
|
||||||
KeyEnter = 257
|
KeyEnter = 257
|
||||||
|
KeyTab = 258
|
||||||
KeyBackspace = 259
|
KeyBackspace = 259
|
||||||
|
KeyInsert = 260
|
||||||
|
KeyDelete = 261
|
||||||
KeyRight = 262
|
KeyRight = 262
|
||||||
KeyLeft = 263
|
KeyLeft = 263
|
||||||
KeyDown = 264
|
KeyDown = 264
|
||||||
KeyUp = 265
|
KeyUp = 265
|
||||||
|
KeyPageUp = 266
|
||||||
|
KeyPageDown = 267
|
||||||
|
KeyHome = 268
|
||||||
|
KeyEnd = 269
|
||||||
|
KeyCapsLock = 280
|
||||||
|
KeyScrollLock = 281
|
||||||
|
KeyNumLock = 282
|
||||||
|
KeyPrintScreen = 283
|
||||||
|
KeyPause = 284
|
||||||
KeyF1 = 290
|
KeyF1 = 290
|
||||||
KeyF2 = 291
|
KeyF2 = 291
|
||||||
KeyF3 = 292
|
KeyF3 = 292
|
||||||
|
@ -872,15 +884,15 @@ func newSpriteFontFromPointer(ptr unsafe.Pointer) SpriteFont {
|
||||||
return *(*SpriteFont)(ptr)
|
return *(*SpriteFont)(ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TextureFormat - Texture format
|
// PixelFormat - Texture format
|
||||||
type TextureFormat int32
|
type PixelFormat int32
|
||||||
|
|
||||||
// Texture formats
|
// Texture formats
|
||||||
// NOTE: Support depends on OpenGL version and platform
|
// NOTE: Support depends on OpenGL version and platform
|
||||||
const (
|
const (
|
||||||
// 8 bit per pixel (no alpha)
|
// 8 bit per pixel (no alpha)
|
||||||
UncompressedGrayscale TextureFormat = iota + 1
|
UncompressedGrayscale PixelFormat = iota + 1
|
||||||
// 16 bpp (2 channels)
|
// 8*2 bpp (2 channels)
|
||||||
UncompressedGrayAlpha
|
UncompressedGrayAlpha
|
||||||
// 16 bpp
|
// 16 bpp
|
||||||
UncompressedR5g6b5
|
UncompressedR5g6b5
|
||||||
|
@ -892,6 +904,12 @@ const (
|
||||||
UncompressedR4g4b4a4
|
UncompressedR4g4b4a4
|
||||||
// 32 bpp
|
// 32 bpp
|
||||||
UncompressedR8g8b8a8
|
UncompressedR8g8b8a8
|
||||||
|
// 32 bpp (1 channel - float)
|
||||||
|
UncompressedR32
|
||||||
|
// 32*3 bpp (3 channels - float)
|
||||||
|
UncompressedR32g32b32
|
||||||
|
// 32*4 bpp (4 channels - float)
|
||||||
|
UncompressedR32g32b32a32
|
||||||
// 4 bpp (no alpha)
|
// 4 bpp (no alpha)
|
||||||
CompressedDxt1Rgb
|
CompressedDxt1Rgb
|
||||||
// 4 bpp (1 bit alpha)
|
// 4 bpp (1 bit alpha)
|
||||||
|
@ -958,8 +976,8 @@ type Image struct {
|
||||||
Height int32
|
Height int32
|
||||||
// Mipmap levels, 1 by default
|
// Mipmap levels, 1 by default
|
||||||
Mipmaps int32
|
Mipmaps int32
|
||||||
// Data format (TextureFormat)
|
// Data format (PixelFormat)
|
||||||
Format TextureFormat
|
Format PixelFormat
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToImage converts a Image to Go image.Image
|
// ToImage converts a Image to Go image.Image
|
||||||
|
@ -975,7 +993,7 @@ func (i *Image) ToImage() image.Image {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewImage - Returns new Image
|
// NewImage - Returns new Image
|
||||||
func NewImage(data []byte, width, height, mipmaps int32, format TextureFormat) *Image {
|
func NewImage(data []byte, width, height, mipmaps int32, format PixelFormat) *Image {
|
||||||
d := unsafe.Pointer(&data[0])
|
d := unsafe.Pointer(&data[0])
|
||||||
return &Image{d, width, height, mipmaps, format}
|
return &Image{d, width, height, mipmaps, format}
|
||||||
}
|
}
|
||||||
|
@ -1012,12 +1030,12 @@ type Texture2D struct {
|
||||||
Height int32
|
Height int32
|
||||||
// Mipmap levels, 1 by default
|
// Mipmap levels, 1 by default
|
||||||
Mipmaps int32
|
Mipmaps int32
|
||||||
// Data format (TextureFormat)
|
// Data format (PixelFormat)
|
||||||
Format TextureFormat
|
Format PixelFormat
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTexture2D - Returns new Texture2D
|
// NewTexture2D - Returns new Texture2D
|
||||||
func NewTexture2D(id uint32, width, height, mipmaps int32, format TextureFormat) Texture2D {
|
func NewTexture2D(id uint32, width, height, mipmaps int32, format PixelFormat) Texture2D {
|
||||||
return Texture2D{id, width, height, mipmaps, format}
|
return Texture2D{id, width, height, mipmaps, format}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1048,15 +1066,11 @@ func newRenderTexture2DFromPointer(ptr unsafe.Pointer) RenderTexture2D {
|
||||||
|
|
||||||
// Log message types
|
// Log message types
|
||||||
const (
|
const (
|
||||||
LogInfo = iota
|
LogInfo = 1 << iota
|
||||||
LogWarning
|
LogWarning
|
||||||
LogError
|
LogError
|
||||||
LogDebug
|
LogDebug
|
||||||
|
LogOther
|
||||||
)
|
)
|
||||||
|
|
||||||
var traceDebugMsgs = false
|
var logTypeFlags = LogInfo | LogWarning | LogError
|
||||||
|
|
||||||
// SetDebug - Set debug messages
|
|
||||||
func SetDebug(enabled bool) {
|
|
||||||
traceDebugMsgs = enabled
|
|
||||||
}
|
|
||||||
|
|
129
raylib/raylib.h
129
raylib/raylib.h
|
@ -1,6 +1,6 @@
|
||||||
/**********************************************************************************************
|
/**********************************************************************************************
|
||||||
*
|
*
|
||||||
* raylib v1.9-dev
|
* raylib v1.9.4-dev
|
||||||
*
|
*
|
||||||
* A simple and easy-to-use library to learn videogames programming (www.raylib.com)
|
* A simple and easy-to-use library to learn videogames programming (www.raylib.com)
|
||||||
*
|
*
|
||||||
|
@ -103,11 +103,23 @@
|
||||||
#define KEY_SPACE 32
|
#define KEY_SPACE 32
|
||||||
#define KEY_ESCAPE 256
|
#define KEY_ESCAPE 256
|
||||||
#define KEY_ENTER 257
|
#define KEY_ENTER 257
|
||||||
|
#define KEY_TAB 258
|
||||||
#define KEY_BACKSPACE 259
|
#define KEY_BACKSPACE 259
|
||||||
|
#define KEY_INSERT 260
|
||||||
|
#define KEY_DELETE 261
|
||||||
#define KEY_RIGHT 262
|
#define KEY_RIGHT 262
|
||||||
#define KEY_LEFT 263
|
#define KEY_LEFT 263
|
||||||
#define KEY_DOWN 264
|
#define KEY_DOWN 264
|
||||||
#define KEY_UP 265
|
#define KEY_UP 265
|
||||||
|
#define KEY_PAGE_UP 266
|
||||||
|
#define KEY_PAGE_DOWN 267
|
||||||
|
#define KEY_HOME 268
|
||||||
|
#define KEY_END 269
|
||||||
|
#define KEY_CAPS_LOCK 280
|
||||||
|
#define KEY_SCROLL_LOCK 281
|
||||||
|
#define KEY_NUM_LOCK 282
|
||||||
|
#define KEY_PRINT_SCREEN 283
|
||||||
|
#define KEY_PAUSE 284
|
||||||
#define KEY_F1 290
|
#define KEY_F1 290
|
||||||
#define KEY_F2 291
|
#define KEY_F2 291
|
||||||
#define KEY_F3 292
|
#define KEY_F3 292
|
||||||
|
@ -341,7 +353,7 @@ typedef struct Image {
|
||||||
int width; // Image base width
|
int width; // Image base width
|
||||||
int height; // Image base height
|
int height; // Image base height
|
||||||
int mipmaps; // Mipmap levels, 1 by default
|
int mipmaps; // Mipmap levels, 1 by default
|
||||||
int format; // Data format (TextureFormat type)
|
int format; // Data format (PixelFormat type)
|
||||||
} Image;
|
} Image;
|
||||||
|
|
||||||
// Texture2D type
|
// Texture2D type
|
||||||
|
@ -351,7 +363,7 @@ typedef struct Texture2D {
|
||||||
int width; // Texture base width
|
int width; // Texture base width
|
||||||
int height; // Texture base height
|
int height; // Texture base height
|
||||||
int mipmaps; // Mipmap levels, 1 by default
|
int mipmaps; // Mipmap levels, 1 by default
|
||||||
int format; // Data format (TextureFormat type)
|
int format; // Data format (PixelFormat type)
|
||||||
} Texture2D;
|
} Texture2D;
|
||||||
|
|
||||||
// RenderTexture2D type, for texture rendering
|
// RenderTexture2D type, for texture rendering
|
||||||
|
@ -470,11 +482,11 @@ typedef struct Wave {
|
||||||
|
|
||||||
// Sound source type
|
// Sound source type
|
||||||
typedef struct Sound {
|
typedef struct Sound {
|
||||||
void* audioBuffer; // A pointer to internal data used by the audio system.
|
void *audioBuffer; // Pointer to internal data used by the audio system
|
||||||
|
|
||||||
unsigned int source; // OpenAL audio source id
|
unsigned int source; // Audio source id
|
||||||
unsigned int buffer; // OpenAL audio buffer id
|
unsigned int buffer; // Audio buffer id
|
||||||
int format; // OpenAL audio format specifier
|
int format; // Audio format specifier
|
||||||
} Sound;
|
} Sound;
|
||||||
|
|
||||||
// Music type (file streaming from memory)
|
// Music type (file streaming from memory)
|
||||||
|
@ -488,29 +500,13 @@ typedef struct AudioStream {
|
||||||
unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported)
|
unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported)
|
||||||
unsigned int channels; // Number of channels (1-mono, 2-stereo)
|
unsigned int channels; // Number of channels (1-mono, 2-stereo)
|
||||||
|
|
||||||
void* audioBuffer; // A pointer to internal data used by the audio system.
|
void *audioBuffer; // Pointer to internal data used by the audio system.
|
||||||
|
|
||||||
int format; // OpenAL audio format specifier
|
int format; // Audio format specifier
|
||||||
unsigned int source; // OpenAL audio source id
|
unsigned int source; // Audio source id
|
||||||
unsigned int buffers[2]; // OpenAL audio buffers (double buffering)
|
unsigned int buffers[2]; // Audio buffers (double buffering)
|
||||||
} AudioStream;
|
} AudioStream;
|
||||||
|
|
||||||
// rRES data returned when reading a resource,
|
|
||||||
// it contains all required data for user (24 byte)
|
|
||||||
typedef struct RRESData {
|
|
||||||
unsigned int type; // Resource type (4 byte)
|
|
||||||
|
|
||||||
unsigned int param1; // Resouce parameter 1 (4 byte)
|
|
||||||
unsigned int param2; // Resouce parameter 2 (4 byte)
|
|
||||||
unsigned int param3; // Resouce parameter 3 (4 byte)
|
|
||||||
unsigned int param4; // Resouce parameter 4 (4 byte)
|
|
||||||
|
|
||||||
void *data; // Resource data pointer (4 byte)
|
|
||||||
} RRESData;
|
|
||||||
|
|
||||||
// RRES type (pointer to RRESData array)
|
|
||||||
typedef struct RRESData *RRES;
|
|
||||||
|
|
||||||
// Head-Mounted-Display device parameters
|
// Head-Mounted-Display device parameters
|
||||||
typedef struct VrDeviceInfo {
|
typedef struct VrDeviceInfo {
|
||||||
int hResolution; // HMD horizontal resolution in pixels
|
int hResolution; // HMD horizontal resolution in pixels
|
||||||
|
@ -530,11 +526,11 @@ typedef struct VrDeviceInfo {
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Trace log type
|
// Trace log type
|
||||||
typedef enum {
|
typedef enum {
|
||||||
LOG_INFO = 0,
|
LOG_INFO = 1,
|
||||||
LOG_WARNING,
|
LOG_WARNING = 2,
|
||||||
LOG_ERROR,
|
LOG_ERROR = 4,
|
||||||
LOG_DEBUG,
|
LOG_DEBUG = 8,
|
||||||
LOG_OTHER
|
LOG_OTHER = 16
|
||||||
} LogType;
|
} LogType;
|
||||||
|
|
||||||
// Shader location point type
|
// Shader location point type
|
||||||
|
@ -587,17 +583,19 @@ typedef enum {
|
||||||
#define MAP_DIFFUSE MAP_ALBEDO
|
#define MAP_DIFFUSE MAP_ALBEDO
|
||||||
#define MAP_SPECULAR MAP_METALNESS
|
#define MAP_SPECULAR MAP_METALNESS
|
||||||
|
|
||||||
// Texture formats
|
// Pixel formats
|
||||||
// NOTE: Support depends on OpenGL version and platform
|
// NOTE: Support depends on OpenGL version and platform
|
||||||
typedef enum {
|
typedef enum {
|
||||||
UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha)
|
UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha)
|
||||||
UNCOMPRESSED_GRAY_ALPHA, // 16 bpp (2 channels)
|
UNCOMPRESSED_GRAY_ALPHA, // 8*2 bpp (2 channels)
|
||||||
UNCOMPRESSED_R5G6B5, // 16 bpp
|
UNCOMPRESSED_R5G6B5, // 16 bpp
|
||||||
UNCOMPRESSED_R8G8B8, // 24 bpp
|
UNCOMPRESSED_R8G8B8, // 24 bpp
|
||||||
UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha)
|
UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha)
|
||||||
UNCOMPRESSED_R4G4B4A4, // 16 bpp (4 bit alpha)
|
UNCOMPRESSED_R4G4B4A4, // 16 bpp (4 bit alpha)
|
||||||
UNCOMPRESSED_R8G8B8A8, // 32 bpp
|
UNCOMPRESSED_R8G8B8A8, // 32 bpp
|
||||||
UNCOMPRESSED_R32G32B32, // 32 bit per channel (float) - HDR
|
UNCOMPRESSED_R32, // 32 bpp (1 channel - float)
|
||||||
|
UNCOMPRESSED_R32G32B32, // 32*3 bpp (3 channels - float)
|
||||||
|
UNCOMPRESSED_R32G32B32A32, // 32*4 bpp (4 channels - float)
|
||||||
COMPRESSED_DXT1_RGB, // 4 bpp (no alpha)
|
COMPRESSED_DXT1_RGB, // 4 bpp (no alpha)
|
||||||
COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha)
|
COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha)
|
||||||
COMPRESSED_DXT3_RGBA, // 8 bpp
|
COMPRESSED_DXT3_RGBA, // 8 bpp
|
||||||
|
@ -609,7 +607,7 @@ typedef enum {
|
||||||
COMPRESSED_PVRT_RGBA, // 4 bpp
|
COMPRESSED_PVRT_RGBA, // 4 bpp
|
||||||
COMPRESSED_ASTC_4x4_RGBA, // 8 bpp
|
COMPRESSED_ASTC_4x4_RGBA, // 8 bpp
|
||||||
COMPRESSED_ASTC_8x8_RGBA // 2 bpp
|
COMPRESSED_ASTC_8x8_RGBA // 2 bpp
|
||||||
} TextureFormat;
|
} PixelFormat;
|
||||||
|
|
||||||
// Texture parameters: filter mode
|
// Texture parameters: filter mode
|
||||||
// NOTE 1: Filtering considers mipmaps if available in the texture
|
// NOTE 1: Filtering considers mipmaps if available in the texture
|
||||||
|
@ -672,18 +670,6 @@ typedef enum {
|
||||||
HMD_SONY_PSVR
|
HMD_SONY_PSVR
|
||||||
} VrDeviceType;
|
} VrDeviceType;
|
||||||
|
|
||||||
// RRESData type
|
|
||||||
typedef enum {
|
|
||||||
RRES_TYPE_RAW = 0,
|
|
||||||
RRES_TYPE_IMAGE,
|
|
||||||
RRES_TYPE_WAVE,
|
|
||||||
RRES_TYPE_VERTEX,
|
|
||||||
RRES_TYPE_TEXT,
|
|
||||||
RRES_TYPE_FONT_IMAGE,
|
|
||||||
RRES_TYPE_FONT_CHARDATA, // CharInfo data array
|
|
||||||
RRES_TYPE_DIRECTORY
|
|
||||||
} RRESDataType;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" { // Prevents name mangling of functions
|
extern "C" { // Prevents name mangling of functions
|
||||||
#endif
|
#endif
|
||||||
|
@ -700,6 +686,7 @@ extern "C" { // Prevents name mangling of functions
|
||||||
// Window-related functions
|
// Window-related functions
|
||||||
RLAPI void InitWindow(int width, int height, void *data); // Initialize window and OpenGL context
|
RLAPI void InitWindow(int width, int height, void *data); // Initialize window and OpenGL context
|
||||||
RLAPI void CloseWindow(void); // Close window and unload OpenGL context
|
RLAPI void CloseWindow(void); // Close window and unload OpenGL context
|
||||||
|
RLAPI bool IsWindowReady(void); // Check if window has been initialized successfully
|
||||||
RLAPI bool WindowShouldClose(void); // Check if KEY_ESCAPE pressed or Close icon pressed
|
RLAPI bool WindowShouldClose(void); // Check if KEY_ESCAPE pressed or Close icon pressed
|
||||||
RLAPI bool IsWindowMinimized(void); // Check if window has been minimized (or lost focus)
|
RLAPI bool IsWindowMinimized(void); // Check if window has been minimized (or lost focus)
|
||||||
RLAPI void ToggleFullscreen(void); // Toggle fullscreen mode (only PLATFORM_DESKTOP)
|
RLAPI void ToggleFullscreen(void); // Toggle fullscreen mode (only PLATFORM_DESKTOP)
|
||||||
|
@ -738,12 +725,14 @@ RLAPI Matrix GetCameraMatrix(Camera camera); // Returns cam
|
||||||
RLAPI void SetTargetFPS(int fps); // Set target FPS (maximum)
|
RLAPI void SetTargetFPS(int fps); // Set target FPS (maximum)
|
||||||
RLAPI int GetFPS(void); // Returns current FPS
|
RLAPI int GetFPS(void); // Returns current FPS
|
||||||
RLAPI float GetFrameTime(void); // Returns time in seconds for last frame drawn
|
RLAPI float GetFrameTime(void); // Returns time in seconds for last frame drawn
|
||||||
|
RLAPI double GetTime(void); // Returns elapsed time in seconds since InitWindow()
|
||||||
|
|
||||||
// Color-related functions
|
// Color-related functions
|
||||||
RLAPI int GetHexValue(Color color); // Returns hexadecimal value for a Color
|
RLAPI float *ColorToFloat(Color color); // Returns normalized float array for a Color
|
||||||
|
RLAPI int ColorToInt(Color color); // Returns hexadecimal value for a Color
|
||||||
|
RLAPI Vector3 ColorToHSV(Color color); // Returns HSV values for a Color
|
||||||
RLAPI Color GetColor(int hexValue); // Returns a Color struct from hexadecimal value
|
RLAPI Color GetColor(int hexValue); // Returns a Color struct from hexadecimal value
|
||||||
RLAPI Color Fade(Color color, float alpha); // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f
|
RLAPI Color Fade(Color color, float alpha); // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f
|
||||||
RLAPI float *ColorToFloat(Color color); // Converts Color to float array and normalizes
|
|
||||||
|
|
||||||
// Math useful functions (available from raymath.h)
|
// Math useful functions (available from raymath.h)
|
||||||
RLAPI float *Vector3ToFloat(Vector3 vec); // Returns Vector3 as float array
|
RLAPI float *Vector3ToFloat(Vector3 vec); // Returns Vector3 as float array
|
||||||
|
@ -754,16 +743,18 @@ RLAPI Matrix MatrixIdentity(void); // Returns ide
|
||||||
|
|
||||||
// Misc. functions
|
// Misc. functions
|
||||||
RLAPI void ShowLogo(void); // Activate raylib logo at startup (can be done with flags)
|
RLAPI void ShowLogo(void); // Activate raylib logo at startup (can be done with flags)
|
||||||
RLAPI void SetConfigFlags(char flags); // Setup window configuration flags (view FLAGS)
|
RLAPI void SetConfigFlags(unsigned char flags); // Setup window configuration flags (view FLAGS)
|
||||||
|
RLAPI void SetTraceLog(unsigned char types); // Enable trace log message types (bit flags based)
|
||||||
RLAPI void TraceLog(int logType, const char *text, ...); // Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG)
|
RLAPI void TraceLog(int logType, const char *text, ...); // Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG)
|
||||||
RLAPI void TakeScreenshot(const char *fileName); // Takes a screenshot of current screen (saved a .png)
|
RLAPI void TakeScreenshot(const char *fileName); // Takes a screenshot of current screen (saved a .png)
|
||||||
RLAPI int GetRandomValue(int min, int max); // Returns a random value between min and max (both included)
|
RLAPI int GetRandomValue(int min, int max); // Returns a random value between min and max (both included)
|
||||||
|
|
||||||
// Files management functions
|
// Files management functions
|
||||||
RLAPI bool IsFileExtension(const char *fileName, const char *ext);// Check file extension
|
RLAPI bool IsFileExtension(const char *fileName, const char *ext);// Check file extension
|
||||||
RLAPI const char *GetExtension(const char *fileName); // Get file extension
|
RLAPI const char *GetExtension(const char *fileName); // Get pointer to extension for a filename string
|
||||||
RLAPI const char *GetDirectoryPath(const char *fileName); // Get directory for a given fileName (with path)
|
RLAPI const char *GetFileName(const char *filePath); // Get pointer to filename for a path string
|
||||||
RLAPI const char *GetWorkingDirectory(void); // Get current working directory
|
RLAPI const char *GetDirectoryPath(const char *fileName); // Get full path for a given fileName (uses static string)
|
||||||
|
RLAPI const char *GetWorkingDirectory(void); // Get current working directory (uses static string)
|
||||||
RLAPI bool ChangeDirectory(const char *dir); // Change working directory, returns true if success
|
RLAPI bool ChangeDirectory(const char *dir); // Change working directory, returns true if success
|
||||||
RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window
|
RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window
|
||||||
RLAPI char **GetDroppedFiles(int *count); // Get dropped files names
|
RLAPI char **GetDroppedFiles(int *count); // Get dropped files names
|
||||||
|
@ -855,14 +846,14 @@ RLAPI void DrawCircleGradient(int centerX, int centerY, float radius, Color colo
|
||||||
RLAPI void DrawCircleV(Vector2 center, float radius, Color color); // Draw a color-filled circle (Vector version)
|
RLAPI void DrawCircleV(Vector2 center, float radius, Color color); // Draw a color-filled circle (Vector version)
|
||||||
RLAPI void DrawCircleLines(int centerX, int centerY, float radius, Color color); // Draw circle outline
|
RLAPI void DrawCircleLines(int centerX, int centerY, float radius, Color color); // Draw circle outline
|
||||||
RLAPI void DrawRectangle(int posX, int posY, int width, int height, Color color); // Draw a color-filled rectangle
|
RLAPI void DrawRectangle(int posX, int posY, int width, int height, Color color); // Draw a color-filled rectangle
|
||||||
|
RLAPI void DrawRectangleV(Vector2 position, Vector2 size, Color color); // Draw a color-filled rectangle (Vector version)
|
||||||
RLAPI void DrawRectangleRec(Rectangle rec, Color color); // Draw a color-filled rectangle
|
RLAPI void DrawRectangleRec(Rectangle rec, Color color); // Draw a color-filled rectangle
|
||||||
RLAPI void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color); // Draw a color-filled rectangle with pro parameters
|
RLAPI void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color); // Draw a color-filled rectangle with pro parameters
|
||||||
RLAPI void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2);// Draw a vertical-gradient-filled rectangle
|
RLAPI void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2);// Draw a vertical-gradient-filled rectangle
|
||||||
RLAPI void DrawRectangleGradientH(int posX, int posY, int width, int height, Color color1, Color color2);// Draw a horizontal-gradient-filled rectangle
|
RLAPI void DrawRectangleGradientH(int posX, int posY, int width, int height, Color color1, Color color2);// Draw a horizontal-gradient-filled rectangle
|
||||||
RLAPI void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4); // Draw a gradient-filled rectangle with custom vertex colors
|
RLAPI void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4); // Draw a gradient-filled rectangle with custom vertex colors
|
||||||
RLAPI void DrawRectangleV(Vector2 position, Vector2 size, Color color); // Draw a color-filled rectangle (Vector version)
|
|
||||||
RLAPI void DrawRectangleLines(int posX, int posY, int width, int height, Color color); // Draw rectangle outline
|
RLAPI void DrawRectangleLines(int posX, int posY, int width, int height, Color color); // Draw rectangle outline
|
||||||
RLAPI void DrawRectangleT(int posX, int posY, int width, int height, Color color); // Draw rectangle using text character
|
RLAPI void DrawRectangleLinesEx(Rectangle rec, int lineThick, Color color); // Draw rectangle outline with extended parameters
|
||||||
RLAPI void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw a color-filled triangle
|
RLAPI void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw a color-filled triangle
|
||||||
RLAPI void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline
|
RLAPI void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline
|
||||||
RLAPI void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a regular polygon (Vector version)
|
RLAPI void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a regular polygon (Vector version)
|
||||||
|
@ -894,19 +885,24 @@ RLAPI void UnloadImage(Image image);
|
||||||
RLAPI void UnloadTexture(Texture2D texture); // Unload texture from GPU memory (VRAM)
|
RLAPI void UnloadTexture(Texture2D texture); // Unload texture from GPU memory (VRAM)
|
||||||
RLAPI void UnloadRenderTexture(RenderTexture2D target); // Unload render texture from GPU memory (VRAM)
|
RLAPI void UnloadRenderTexture(RenderTexture2D target); // Unload render texture from GPU memory (VRAM)
|
||||||
RLAPI Color *GetImageData(Image image); // Get pixel data from image as a Color struct array
|
RLAPI Color *GetImageData(Image image); // Get pixel data from image as a Color struct array
|
||||||
|
RLAPI int GetPixelDataSize(int width, int height, int format); // Get pixel data size in bytes (image or texture)
|
||||||
RLAPI Image GetTextureData(Texture2D texture); // Get pixel data from GPU texture and return an Image
|
RLAPI Image GetTextureData(Texture2D texture); // Get pixel data from GPU texture and return an Image
|
||||||
RLAPI void UpdateTexture(Texture2D texture, const void *pixels); // Update GPU texture with new data
|
RLAPI void UpdateTexture(Texture2D texture, const void *pixels); // Update GPU texture with new data
|
||||||
RLAPI void SaveImageAs(const char *fileName, Image image); // Save image to a PNG file
|
RLAPI void SaveImageAs(const char *fileName, Image image); // Save image to a PNG file
|
||||||
|
|
||||||
// Image manipulation functions
|
// Image manipulation functions
|
||||||
|
RLAPI Image ImageCopy(Image image); // Create an image duplicate (useful for transformations)
|
||||||
RLAPI void ImageToPOT(Image *image, Color fillColor); // Convert image to POT (power-of-two)
|
RLAPI void ImageToPOT(Image *image, Color fillColor); // Convert image to POT (power-of-two)
|
||||||
RLAPI void ImageFormat(Image *image, int newFormat); // Convert image data to desired format
|
RLAPI void ImageFormat(Image *image, int newFormat); // Convert image data to desired format
|
||||||
RLAPI void ImageAlphaMask(Image *image, Image alphaMask); // Apply alpha mask to image
|
RLAPI void ImageAlphaMask(Image *image, Image alphaMask); // Apply alpha mask to image
|
||||||
RLAPI void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp); // Dither image data to 16bpp or lower (Floyd-Steinberg dithering)
|
RLAPI void ImageAlphaClear(Image *image, Color color, float threshold); // Clear alpha channel to desired color
|
||||||
RLAPI Image ImageCopy(Image image); // Create an image duplicate (useful for transformations)
|
RLAPI void ImageAlphaCrop(Image *image, float threshold); // Crop image depending on alpha value
|
||||||
|
RLAPI void ImageAlphaPremultiply(Image *image); // Premultiply alpha channel
|
||||||
RLAPI void ImageCrop(Image *image, Rectangle crop); // Crop an image to a defined rectangle
|
RLAPI void ImageCrop(Image *image, Rectangle crop); // Crop an image to a defined rectangle
|
||||||
RLAPI void ImageResize(Image *image, int newWidth, int newHeight); // Resize and image (bilinear filtering)
|
RLAPI void ImageResize(Image *image, int newWidth, int newHeight); // Resize and image (bilinear filtering)
|
||||||
RLAPI void ImageResizeNN(Image *image,int newWidth,int newHeight); // Resize and image (Nearest-Neighbor scaling algorithm)
|
RLAPI void ImageResizeNN(Image *image,int newWidth,int newHeight); // Resize and image (Nearest-Neighbor scaling algorithm)
|
||||||
|
RLAPI void ImageMipmaps(Image *image); // Generate all mipmap levels for a provided image
|
||||||
|
RLAPI void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp); // Dither image data to 16bpp or lower (Floyd-Steinberg dithering)
|
||||||
RLAPI Image ImageText(const char *text, int fontSize, Color color); // Create an image from text (default font)
|
RLAPI Image ImageText(const char *text, int fontSize, Color color); // Create an image from text (default font)
|
||||||
RLAPI Image ImageTextEx(SpriteFont font, const char *text, float fontSize, int spacing, Color tint); // Create an image from text (custom sprite font)
|
RLAPI Image ImageTextEx(SpriteFont font, const char *text, float fontSize, int spacing, Color tint); // Create an image from text (custom sprite font)
|
||||||
RLAPI void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec); // Draw a source image within a destination image
|
RLAPI void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec); // Draw a source image within a destination image
|
||||||
|
@ -928,7 +924,7 @@ RLAPI Image GenImageGradientH(int width, int height, Color left, Color right);
|
||||||
RLAPI Image GenImageGradientRadial(int width, int height, float density, Color inner, Color outer); // Generate image: radial gradient
|
RLAPI Image GenImageGradientRadial(int width, int height, float density, Color inner, Color outer); // Generate image: radial gradient
|
||||||
RLAPI Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2); // Generate image: checked
|
RLAPI Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2); // Generate image: checked
|
||||||
RLAPI Image GenImageWhiteNoise(int width, int height, float factor); // Generate image: white noise
|
RLAPI Image GenImageWhiteNoise(int width, int height, float factor); // Generate image: white noise
|
||||||
RLAPI Image GenImagePerlinNoise(int width, int height, float scale); // Generate image: perlin noise
|
RLAPI Image GenImagePerlinNoise(int width, int height, int offsetX, int offsetY, float scale); // Generate image: perlin noise
|
||||||
RLAPI Image GenImageCellular(int width, int height, int tileSize); // Generate image: cellular algorithm. Bigger tileSize means bigger cells
|
RLAPI Image GenImageCellular(int width, int height, int tileSize); // Generate image: cellular algorithm. Bigger tileSize means bigger cells
|
||||||
|
|
||||||
// Texture2D configuration functions
|
// Texture2D configuration functions
|
||||||
|
@ -952,19 +948,20 @@ RLAPI void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle dest
|
||||||
RLAPI SpriteFont GetDefaultFont(void); // Get the default SpriteFont
|
RLAPI SpriteFont GetDefaultFont(void); // Get the default SpriteFont
|
||||||
RLAPI SpriteFont LoadSpriteFont(const char *fileName); // Load SpriteFont from file into GPU memory (VRAM)
|
RLAPI SpriteFont LoadSpriteFont(const char *fileName); // Load SpriteFont from file into GPU memory (VRAM)
|
||||||
RLAPI SpriteFont LoadSpriteFontEx(const char *fileName, int fontSize, int charsCount, int *fontChars); // Load SpriteFont from file with extended parameters
|
RLAPI SpriteFont LoadSpriteFontEx(const char *fileName, int fontSize, int charsCount, int *fontChars); // Load SpriteFont from file with extended parameters
|
||||||
RLAPI void UnloadSpriteFont(SpriteFont spriteFont); // Unload SpriteFont from GPU memory (VRAM)
|
RLAPI void UnloadSpriteFont(SpriteFont font); // Unload SpriteFont from GPU memory (VRAM)
|
||||||
|
|
||||||
// Text drawing functions
|
// Text drawing functions
|
||||||
RLAPI void DrawFPS(int posX, int posY); // Shows current FPS
|
RLAPI void DrawFPS(int posX, int posY); // Shows current FPS
|
||||||
RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font)
|
RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font)
|
||||||
RLAPI void DrawTextEx(SpriteFont spriteFont, const char* text, Vector2 position, // Draw text using SpriteFont and additional parameters
|
RLAPI void DrawTextEx(SpriteFont font, const char* text, Vector2 position, // Draw text using SpriteFont and additional parameters
|
||||||
float fontSize, int spacing, Color tint);
|
float fontSize, int spacing, Color tint);
|
||||||
|
|
||||||
// Text misc. functions
|
// Text misc. functions
|
||||||
RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font
|
RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font
|
||||||
RLAPI Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, float fontSize, int spacing); // Measure string size for SpriteFont
|
RLAPI Vector2 MeasureTextEx(SpriteFont font, const char *text, float fontSize, int spacing); // Measure string size for SpriteFont
|
||||||
RLAPI const char *FormatText(const char *text, ...); // Formatting of text with variables to 'embed'
|
RLAPI const char *FormatText(const char *text, ...); // Formatting of text with variables to 'embed'
|
||||||
RLAPI const char *SubText(const char *text, int position, int length); // Get a piece of a text string
|
RLAPI const char *SubText(const char *text, int position, int length); // Get a piece of a text string
|
||||||
|
RLAPI int GetGlyphIndex(SpriteFont font, int character); // Returns index position for a unicode character on sprite font
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Basic 3d Shapes Drawing Functions (Module: models)
|
// Basic 3d Shapes Drawing Functions (Module: models)
|
||||||
|
@ -1049,7 +1046,8 @@ RLAPI RayHitInfo GetCollisionRayGround(Ray ray, float groundHeight);
|
||||||
|
|
||||||
// Shader loading/unloading functions
|
// Shader loading/unloading functions
|
||||||
RLAPI char *LoadText(const char *fileName); // Load chars array from text file
|
RLAPI char *LoadText(const char *fileName); // Load chars array from text file
|
||||||
RLAPI Shader LoadShader(char *vsFileName, char *fsFileName); // Load shader from files and bind default locations
|
RLAPI Shader LoadShader(const char *vsFileName, const char *fsFileName); // Load shader from files and bind default locations
|
||||||
|
RLAPI Shader LoadShaderCode(char *vsCode, char *fsCode); // Load shader from code strings and bind default locations
|
||||||
RLAPI void UnloadShader(Shader shader); // Unload shader from GPU memory (VRAM)
|
RLAPI void UnloadShader(Shader shader); // Unload shader from GPU memory (VRAM)
|
||||||
|
|
||||||
RLAPI Shader GetShaderDefault(void); // Get default shader
|
RLAPI Shader GetShaderDefault(void); // Get default shader
|
||||||
|
@ -1062,6 +1060,7 @@ RLAPI void SetShaderValuei(Shader shader, int uniformLoc, const int *value, int
|
||||||
RLAPI void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // Set shader uniform value (matrix 4x4)
|
RLAPI void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // Set shader uniform value (matrix 4x4)
|
||||||
RLAPI void SetMatrixProjection(Matrix proj); // Set a custom projection matrix (replaces internal projection matrix)
|
RLAPI void SetMatrixProjection(Matrix proj); // Set a custom projection matrix (replaces internal projection matrix)
|
||||||
RLAPI void SetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix)
|
RLAPI void SetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix)
|
||||||
|
RLAPI Matrix GetMatrixModelview(); // Get internal modelview matrix
|
||||||
|
|
||||||
// Texture maps generation (PBR)
|
// Texture maps generation (PBR)
|
||||||
// NOTE: Required shaders should be provided
|
// NOTE: Required shaders should be provided
|
||||||
|
@ -1145,8 +1144,8 @@ RLAPI void PauseAudioStream(AudioStream stream); // Pause a
|
||||||
RLAPI void ResumeAudioStream(AudioStream stream); // Resume audio stream
|
RLAPI void ResumeAudioStream(AudioStream stream); // Resume audio stream
|
||||||
RLAPI bool IsAudioStreamPlaying(AudioStream stream); // Check if audio stream is playing
|
RLAPI bool IsAudioStreamPlaying(AudioStream stream); // Check if audio stream is playing
|
||||||
RLAPI void StopAudioStream(AudioStream stream); // Stop audio stream
|
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 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 SetAudioStreamPitch(AudioStream stream, float pitch); // Set pitch for audio stream (1.0 is base level)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,42 @@ func LoadWave(fileName string) Wave {
|
||||||
|
|
||||||
// LoadWaveEx - Load wave data from float array data (32bit)
|
// LoadWaveEx - Load wave data from float array data (32bit)
|
||||||
func LoadWaveEx(data []byte, sampleCount int32, sampleRate int32, sampleSize int32, channels int32) Wave {
|
func LoadWaveEx(data []byte, sampleCount int32, sampleRate int32, sampleSize int32, channels int32) Wave {
|
||||||
return newWaveFromPointer(unsafe.Pointer(js.Global.Get("Module").Call("_LoadWaveEx", data, sampleCount, sampleRate, sampleSize, channels).Unsafe()))
|
defer func() {
|
||||||
|
e := recover()
|
||||||
|
|
||||||
|
if e == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if e, ok := e.(*js.Error); ok {
|
||||||
|
println(e)
|
||||||
|
} else {
|
||||||
|
panic(e)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
w := Wave{}
|
||||||
|
wav := *(*[unsafe.Sizeof(w)]byte)(unsafe.Pointer(&w))
|
||||||
|
|
||||||
|
//// Call C from JavaScript
|
||||||
|
//var result = Module.ccall('c_add', // name of C function
|
||||||
|
//'number', // return type
|
||||||
|
//['number', 'number'], // argument types
|
||||||
|
//[10, 20]); // arguments
|
||||||
|
|
||||||
|
println(wav)
|
||||||
|
|
||||||
|
//js.Global.Get("Module").Call("_LoadWaveEx", wav, data, sampleCount, sampleRate, sampleSize, channels)
|
||||||
|
|
||||||
|
ww := js.Global.Get("Module").Call("ccall", "LoadWaveEx", "number",
|
||||||
|
[]string{"array", "number", "number", "number", "number"},
|
||||||
|
[]interface{}{data, sampleCount, sampleRate, sampleSize, channels}).Uint64()
|
||||||
|
|
||||||
|
www := newWaveFromPointer(unsafe.Pointer(&ww))
|
||||||
|
println(www)
|
||||||
|
|
||||||
|
return www
|
||||||
|
//return newWaveFromPointer(unsafe.Pointer(wav.Unsafe()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadSound - Load sound to memory
|
// LoadSound - Load sound to memory
|
||||||
|
@ -47,7 +82,10 @@ func LoadSound(fileName string) Sound {
|
||||||
|
|
||||||
// LoadSoundFromWave - Load sound to memory from wave data
|
// LoadSoundFromWave - Load sound to memory from wave data
|
||||||
func LoadSoundFromWave(wave Wave) Sound {
|
func LoadSoundFromWave(wave Wave) Sound {
|
||||||
return newSoundFromPointer(unsafe.Pointer(js.Global.Get("Module").Call("_LoadSoundFromWave", wave).Unsafe()))
|
s := js.MakeWrapper(Sound{})
|
||||||
|
js.Global.Get("Module").Call("_LoadSoundFromWave", wave, s)
|
||||||
|
return s.Interface().(Sound)
|
||||||
|
//return newSoundFromPointer(unsafe.Pointer())
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateSound - Update sound buffer with new data
|
// UpdateSound - Update sound buffer with new data
|
||||||
|
|
|
@ -227,21 +227,31 @@ RMDEF float Clamp(float value, float min, float max)
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Vector with components value 0.0f
|
// Vector with components value 0.0f
|
||||||
RMDEF Vector2 Vector2Zero(void) { return (Vector2){ 0.0f, 0.0f }; }
|
RMDEF Vector2 Vector2Zero(void)
|
||||||
|
{
|
||||||
|
Vector2 tmp = {0.0f, 0.0f};
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
// Vector with components value 1.0f
|
// Vector with components value 1.0f
|
||||||
RMDEF Vector2 Vector2One(void) { return (Vector2){ 1.0f, 1.0f }; }
|
RMDEF Vector2 Vector2One(void)
|
||||||
|
{
|
||||||
|
Vector2 tmp = {1.0f, 1.0f};
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
// Add two vectors (v1 + v2)
|
// Add two vectors (v1 + v2)
|
||||||
RMDEF Vector2 Vector2Add(Vector2 v1, Vector2 v2)
|
RMDEF Vector2 Vector2Add(Vector2 v1, Vector2 v2)
|
||||||
{
|
{
|
||||||
return (Vector2){ v1.x + v2.x, v1.y + v2.y };
|
Vector2 tmp = { v1.x + v2.x, v1.y + v2.y };
|
||||||
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Subtract two vectors (v1 - v2)
|
// Subtract two vectors (v1 - v2)
|
||||||
RMDEF Vector2 Vector2Subtract(Vector2 v1, Vector2 v2)
|
RMDEF Vector2 Vector2Subtract(Vector2 v1, Vector2 v2)
|
||||||
{
|
{
|
||||||
return (Vector2){ v1.x - v2.x, v1.y - v2.y };
|
Vector2 tmp = { v1.x - v2.x, v1.y - v2.y };
|
||||||
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate vector length
|
// Calculate vector length
|
||||||
|
@ -289,7 +299,8 @@ RMDEF void Vector2Negate(Vector2 *v)
|
||||||
// Divide vector by a float value
|
// Divide vector by a float value
|
||||||
RMDEF void Vector2Divide(Vector2 *v, float div)
|
RMDEF void Vector2Divide(Vector2 *v, float div)
|
||||||
{
|
{
|
||||||
*v = (Vector2){v->x/div, v->y/div};
|
Vector2 tmp = {v->x/div, v->y/div};
|
||||||
|
*v = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normalize provided vector
|
// Normalize provided vector
|
||||||
|
@ -303,21 +314,31 @@ RMDEF void Vector2Normalize(Vector2 *v)
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Vector with components value 0.0f
|
// Vector with components value 0.0f
|
||||||
RMDEF Vector3 Vector3Zero(void) { return (Vector3){ 0.0f, 0.0f, 0.0f }; }
|
RMDEF Vector3 Vector3Zero(void)
|
||||||
|
{
|
||||||
|
Vector3 tmp = { 0.0f, 0.0f, 0.0f };
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
// Vector with components value 1.0f
|
// Vector with components value 1.0f
|
||||||
RMDEF Vector3 Vector3One(void) { return (Vector3){ 1.0f, 1.0f, 1.0f }; }
|
RMDEF Vector3 Vector3One(void)
|
||||||
|
{
|
||||||
|
Vector3 tmp = { 1.0f, 1.0f, 1.0f };
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
// Add two vectors
|
// Add two vectors
|
||||||
RMDEF Vector3 Vector3Add(Vector3 v1, Vector3 v2)
|
RMDEF Vector3 Vector3Add(Vector3 v1, Vector3 v2)
|
||||||
{
|
{
|
||||||
return (Vector3){ v1.x + v2.x, v1.y + v2.y, v1.z + v2.z };
|
Vector3 tmp = { v1.x + v2.x, v1.y + v2.y, v1.z + v2.z };
|
||||||
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Substract two vectors
|
// Substract two vectors
|
||||||
RMDEF Vector3 Vector3Subtract(Vector3 v1, Vector3 v2)
|
RMDEF Vector3 Vector3Subtract(Vector3 v1, Vector3 v2)
|
||||||
{
|
{
|
||||||
return (Vector3){ v1.x - v2.x, v1.y - v2.y, v1.z - v2.z };
|
Vector3 tmp = { v1.x - v2.x, v1.y - v2.y, v1.z - v2.z };
|
||||||
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Multiply vector by scalar
|
// Multiply vector by scalar
|
||||||
|
@ -365,12 +386,14 @@ RMDEF Vector3 Vector3Perpendicular(Vector3 v)
|
||||||
if (fabsf(v.y) < min)
|
if (fabsf(v.y) < min)
|
||||||
{
|
{
|
||||||
min = fabsf(v.y);
|
min = fabsf(v.y);
|
||||||
cardinalAxis = (Vector3){0.0f, 1.0f, 0.0f};
|
Vector3 tmp = {0.0f, 1.0f, 0.0f};
|
||||||
|
cardinalAxis = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fabsf(v.z) < min)
|
if (fabsf(v.z) < min)
|
||||||
{
|
{
|
||||||
cardinalAxis = (Vector3){0.0f, 0.0f, 1.0f};
|
Vector3 tmp = {0.0f, 0.0f, 1.0f};
|
||||||
|
cardinalAxis = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = Vector3CrossProduct(v, cardinalAxis);
|
result = Vector3CrossProduct(v, cardinalAxis);
|
||||||
|
@ -740,8 +763,6 @@ RMDEF Matrix MatrixRotate(Vector3 axis, float angle)
|
||||||
{
|
{
|
||||||
Matrix result;
|
Matrix result;
|
||||||
|
|
||||||
Matrix mat = MatrixIdentity();
|
|
||||||
|
|
||||||
float x = axis.x, y = axis.y, z = axis.z;
|
float x = axis.x, y = axis.y, z = axis.z;
|
||||||
|
|
||||||
float length = sqrtf(x*x + y*y + z*z);
|
float length = sqrtf(x*x + y*y + z*z);
|
||||||
|
@ -758,33 +779,25 @@ RMDEF Matrix MatrixRotate(Vector3 axis, float angle)
|
||||||
float cosres = cosf(angle);
|
float cosres = cosf(angle);
|
||||||
float t = 1.0f - cosres;
|
float t = 1.0f - cosres;
|
||||||
|
|
||||||
// Cache some matrix values (speed optimization)
|
result.m0 = x*x*t + cosres;
|
||||||
float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3;
|
result.m1 = y*x*t + z*sinres;
|
||||||
float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7;
|
result.m2 = z*x*t - y*sinres;
|
||||||
float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11;
|
result.m3 = 0.0f;
|
||||||
|
|
||||||
// Construct the elements of the rotation matrix
|
result.m4 = x*y*t - z*sinres;
|
||||||
float b00 = x*x*t + cosres, b01 = y*x*t + z*sinres, b02 = z*x*t - y*sinres;
|
result.m5 = y*y*t + cosres;
|
||||||
float b10 = x*y*t - z*sinres, b11 = y*y*t + cosres, b12 = z*y*t + x*sinres;
|
result.m6 = z*y*t + x*sinres;
|
||||||
float b20 = x*z*t + y*sinres, b21 = y*z*t - x*sinres, b22 = z*z*t + cosres;
|
result.m7 = 0.0f;
|
||||||
|
|
||||||
// Perform rotation-specific matrix multiplication
|
result.m8 = x*z*t + y*sinres;
|
||||||
result.m0 = a00*b00 + a10*b01 + a20*b02;
|
result.m9 = y*z*t - x*sinres;
|
||||||
result.m1 = a01*b00 + a11*b01 + a21*b02;
|
result.m10 = z*z*t + cosres;
|
||||||
result.m2 = a02*b00 + a12*b01 + a22*b02;
|
result.m11 = 0.0f;
|
||||||
result.m3 = a03*b00 + a13*b01 + a23*b02;
|
|
||||||
result.m4 = a00*b10 + a10*b11 + a20*b12;
|
result.m12 = 0.0f;
|
||||||
result.m5 = a01*b10 + a11*b11 + a21*b12;
|
result.m13 = 0.0f;
|
||||||
result.m6 = a02*b10 + a12*b11 + a22*b12;
|
result.m14 = 0.0f;
|
||||||
result.m7 = a03*b10 + a13*b11 + a23*b12;
|
result.m15 = 1.0f;
|
||||||
result.m8 = a00*b20 + a10*b21 + a20*b22;
|
|
||||||
result.m9 = a01*b20 + a11*b21 + a21*b22;
|
|
||||||
result.m10 = a02*b20 + a12*b21 + a22*b22;
|
|
||||||
result.m11 = a03*b20 + a13*b21 + a23*b22;
|
|
||||||
result.m12 = mat.m12;
|
|
||||||
result.m13 = mat.m13;
|
|
||||||
result.m14 = mat.m14;
|
|
||||||
result.m15 = mat.m15;
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1011,7 +1024,8 @@ RMDEF float *MatrixToFloat(Matrix mat)
|
||||||
// Returns identity quaternion
|
// Returns identity quaternion
|
||||||
RMDEF Quaternion QuaternionIdentity(void)
|
RMDEF Quaternion QuaternionIdentity(void)
|
||||||
{
|
{
|
||||||
return (Quaternion){ 0.0f, 0.0f, 0.0f, 1.0f };
|
Quaternion q = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||||
|
return q;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Computes the length of a quaternion
|
// Computes the length of a quaternion
|
||||||
|
|
453
raylib/rlgl.c
453
raylib/rlgl.c
|
@ -1,5 +1,3 @@
|
||||||
// +build !js
|
|
||||||
|
|
||||||
/**********************************************************************************************
|
/**********************************************************************************************
|
||||||
*
|
*
|
||||||
* rlgl - raylib OpenGL abstraction layer
|
* rlgl - raylib OpenGL abstraction layer
|
||||||
|
@ -37,7 +35,7 @@
|
||||||
*
|
*
|
||||||
* LICENSE: zlib/libpng
|
* LICENSE: zlib/libpng
|
||||||
*
|
*
|
||||||
* Copyright (c) 2014-2017 Ramon Santamaria (@raysan5)
|
* Copyright (c) 2014-2018 Ramon Santamaria (@raysan5)
|
||||||
*
|
*
|
||||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
* 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.
|
* will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
@ -76,8 +74,24 @@
|
||||||
#if defined(GRAPHICS_API_OPENGL_11)
|
#if defined(GRAPHICS_API_OPENGL_11)
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
#include <OpenGL/gl.h> // OpenGL 1.1 library for OSX
|
#include <OpenGL/gl.h> // OpenGL 1.1 library for OSX
|
||||||
|
#include <OpenGL/glext.h>
|
||||||
#else
|
#else
|
||||||
#include <GL/gl.h> // OpenGL 1.1 library
|
#if defined(_MSC_VER) // Using MSVC compiler, requires some additional definitions
|
||||||
|
// APIENTRY for OpenGL function pointer declarations is required
|
||||||
|
#ifndef APIENTRY
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define APIENTRY __stdcall
|
||||||
|
#else
|
||||||
|
#define APIENTRY
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
// WINGDIAPI definition. Some Windows OpenGL headers need it
|
||||||
|
#if !defined(WINGDIAPI) && defined(_WIN32)
|
||||||
|
#define WINGDIAPI __declspec(dllimport)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <GL/gl.h> // OpenGL 1.1 library
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -88,6 +102,7 @@
|
||||||
#if defined(GRAPHICS_API_OPENGL_33)
|
#if defined(GRAPHICS_API_OPENGL_33)
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
#include <OpenGL/gl3.h> // OpenGL 3 library for OSX
|
#include <OpenGL/gl3.h> // OpenGL 3 library for OSX
|
||||||
|
#include <OpenGL/gl3ext.h>
|
||||||
#else
|
#else
|
||||||
#define GLAD_IMPLEMENTATION
|
#define GLAD_IMPLEMENTATION
|
||||||
#if defined(RLGL_STANDALONE)
|
#if defined(RLGL_STANDALONE)
|
||||||
|
@ -112,6 +127,7 @@
|
||||||
#include "shader_distortion.h" // Distortion shader to be embedded
|
#include "shader_distortion.h" // Distortion shader to be embedded
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Defines and Macros
|
// Defines and Macros
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
@ -272,6 +288,7 @@ static bool useTempBuffer = false;
|
||||||
// Shaders
|
// Shaders
|
||||||
static unsigned int defaultVShaderId; // Default vertex shader id (used by default shader program)
|
static unsigned int defaultVShaderId; // Default vertex shader id (used by default shader program)
|
||||||
static unsigned int defaultFShaderId; // Default fragment shader Id (used by default shader program)
|
static unsigned int defaultFShaderId; // Default fragment shader Id (used by default shader program)
|
||||||
|
|
||||||
static Shader defaultShader; // Basic shader, support vertex color and diffuse texture
|
static Shader defaultShader; // Basic shader, support vertex color and diffuse texture
|
||||||
static Shader currentShader; // Shader to be used on rendering (by default, defaultShader)
|
static Shader currentShader; // Shader to be used on rendering (by default, defaultShader)
|
||||||
|
|
||||||
|
@ -309,6 +326,8 @@ static PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArrays;
|
||||||
//static PFNGLISVERTEXARRAYOESPROC glIsVertexArray; // NOTE: Fails in WebGL, omitted
|
//static PFNGLISVERTEXARRAYOESPROC glIsVertexArray; // NOTE: Fails in WebGL, omitted
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static bool debugMarkerSupported = false;
|
||||||
|
|
||||||
// Compressed textures support flags
|
// Compressed textures support flags
|
||||||
static bool texCompDXTSupported = false; // DDS texture compression support
|
static bool texCompDXTSupported = false; // DDS texture compression support
|
||||||
static bool texNPOTSupported = false; // NPOT textures full support
|
static bool texNPOTSupported = false; // NPOT textures full support
|
||||||
|
@ -327,8 +346,6 @@ static int screenHeight; // Default framebuffer height
|
||||||
// Module specific Functions Declaration
|
// Module specific Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
static void LoadTextureCompressed(unsigned char *data, int width, int height, int compressedFormat, int mipmapCount);
|
|
||||||
|
|
||||||
static unsigned int CompileShader(const char *shaderStr, int type); // Compile custom shader and return shader id
|
static unsigned int CompileShader(const char *shaderStr, int type); // Compile custom shader and return shader id
|
||||||
static unsigned int LoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId); // Load custom shader program
|
static unsigned int LoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId); // Load custom shader program
|
||||||
|
|
||||||
|
@ -344,6 +361,9 @@ static void UnloadBuffersDefault(void); // Unload default internal buffers v
|
||||||
static void GenDrawCube(void); // Generate and draw cube
|
static void GenDrawCube(void); // Generate and draw cube
|
||||||
static void GenDrawQuad(void); // Generate and draw quad
|
static void GenDrawQuad(void); // Generate and draw quad
|
||||||
|
|
||||||
|
// Get OpenGL internal formats and data type from raylib PixelFormat
|
||||||
|
static void GetGlFormats(int format, int *glInternalFormat, int *glFormat, int *glType);
|
||||||
|
|
||||||
#if defined(SUPPORT_VR_SIMULATOR)
|
#if defined(SUPPORT_VR_SIMULATOR)
|
||||||
static void SetStereoConfig(VrDeviceInfo info); // Configure stereo rendering (including distortion shader) with HMD device parameters
|
static void SetStereoConfig(VrDeviceInfo info); // Configure stereo rendering (including distortion shader) with HMD device parameters
|
||||||
static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView); // Set internal projection and modelview matrix depending on eye
|
static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView); // Set internal projection and modelview matrix depending on eye
|
||||||
|
@ -414,7 +434,7 @@ void rlPushMatrix(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
stack[stackCounter] = *currentMatrix;
|
stack[stackCounter] = *currentMatrix;
|
||||||
rlLoadIdentity();
|
rlLoadIdentity(); // TODO: Review matrix stack logic!
|
||||||
stackCounter++;
|
stackCounter++;
|
||||||
|
|
||||||
if (currentMatrixMode == RL_MODELVIEW) useTempBuffer = true;
|
if (currentMatrixMode == RL_MODELVIEW) useTempBuffer = true;
|
||||||
|
@ -644,6 +664,14 @@ void rlEnd(void)
|
||||||
// as well as depth buffer bit-depth (16bit or 24bit or 32bit)
|
// as well as depth buffer bit-depth (16bit or 24bit or 32bit)
|
||||||
// Correct increment formula would be: depthInc = (zfar - znear)/pow(2, bits)
|
// Correct increment formula would be: depthInc = (zfar - znear)/pow(2, bits)
|
||||||
currentDepth += (1.0f/20000.0f);
|
currentDepth += (1.0f/20000.0f);
|
||||||
|
|
||||||
|
// TODO: Verify internal buffers limits
|
||||||
|
// NOTE: Before launching draw, verify no matrix are left in the stack!
|
||||||
|
// NOTE: Probably a lines/triangles margin should be left, rlEnd could be called
|
||||||
|
// after an undetermined number of triangles buffered (check shapes::DrawPoly())
|
||||||
|
if ((lines.vCounter/2 >= MAX_LINES_BATCH - 2) ||
|
||||||
|
(triangles.vCounter/3 >= MAX_TRIANGLES_BATCH - 16) ||
|
||||||
|
(quads.vCounter/4 >= MAX_QUADS_BATCH - 2)) rlglDraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define one vertex (position)
|
// Define one vertex (position)
|
||||||
|
@ -1109,7 +1137,7 @@ void rlglInit(int width, int height)
|
||||||
if (strcmp(extList[i], (const char *)"GL_OES_texture_npot") == 0) texNPOTSupported = true;
|
if (strcmp(extList[i], (const char *)"GL_OES_texture_npot") == 0) texNPOTSupported = true;
|
||||||
|
|
||||||
// Check texture float support
|
// Check texture float support
|
||||||
if (strcmp(extList[i], (const char *)"OES_texture_float") == 0) texFloatSupported = true;
|
if (strcmp(extList[i], (const char *)"GL_OES_texture_float") == 0) texFloatSupported = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// DDS texture compression support
|
// DDS texture compression support
|
||||||
|
@ -1139,10 +1167,13 @@ void rlglInit(int width, int height)
|
||||||
|
|
||||||
// Clamp mirror wrap mode supported
|
// Clamp mirror wrap mode supported
|
||||||
if (strcmp(extList[i], (const char *)"GL_EXT_texture_mirror_clamp") == 0) texClampMirrorSupported = true;
|
if (strcmp(extList[i], (const char *)"GL_EXT_texture_mirror_clamp") == 0) texClampMirrorSupported = true;
|
||||||
|
|
||||||
|
// Debug marker support
|
||||||
|
if(strcmp(extList[i], (const char *)"GL_EXT_debug_marker") == 0) debugMarkerSupported = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#if defined(_MSC_VER)
|
||||||
free(extList);
|
//free(extList);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
|
@ -1162,6 +1193,8 @@ void rlglInit(int width, int height)
|
||||||
if (texAnisotropicFilterSupported) TraceLog(LOG_INFO, "[EXTENSION] Anisotropic textures filtering supported (max: %.0fX)", maxAnisotropicLevel);
|
if (texAnisotropicFilterSupported) TraceLog(LOG_INFO, "[EXTENSION] Anisotropic textures filtering supported (max: %.0fX)", maxAnisotropicLevel);
|
||||||
if (texClampMirrorSupported) TraceLog(LOG_INFO, "[EXTENSION] Clamp mirror wrap texture mode supported");
|
if (texClampMirrorSupported) TraceLog(LOG_INFO, "[EXTENSION] Clamp mirror wrap texture mode supported");
|
||||||
|
|
||||||
|
if (debugMarkerSupported) TraceLog(LOG_INFO, "[EXTENSION] Debug Marker supported");
|
||||||
|
|
||||||
// Initialize buffers, default shaders and default textures
|
// Initialize buffers, default shaders and default textures
|
||||||
//----------------------------------------------------------
|
//----------------------------------------------------------
|
||||||
|
|
||||||
|
@ -1287,6 +1320,14 @@ int rlGetVersion(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set debug marker
|
||||||
|
void rlSetDebugMarker(const char *text)
|
||||||
|
{
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_33)
|
||||||
|
if (debugMarkerSupported) glInsertEventMarkerEXT(0, text);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// Load OpenGL extensions
|
// Load OpenGL extensions
|
||||||
// NOTE: External loader function could be passed as a pointer
|
// NOTE: External loader function could be passed as a pointer
|
||||||
void rlLoadExtensions(void *loader)
|
void rlLoadExtensions(void *loader)
|
||||||
|
@ -1381,6 +1422,8 @@ unsigned int rlLoadTexture(void *data, int width, int height, int format, int mi
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
|
|
||||||
glGenTextures(1, &id); // Generate Pointer to the texture
|
glGenTextures(1, &id); // Generate Pointer to the texture
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
|
@ -1388,94 +1431,50 @@ unsigned int rlLoadTexture(void *data, int width, int height, int format, int mi
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, id);
|
glBindTexture(GL_TEXTURE_2D, id);
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_21) || defined(GRAPHICS_API_OPENGL_ES2)
|
int mipWidth = width;
|
||||||
// NOTE: on OpenGL ES 2.0 (WebGL), internalFormat must match format and options allowed are: GL_LUMINANCE, GL_RGB, GL_RGBA
|
int mipHeight = height;
|
||||||
switch (format)
|
int mipOffset = 0; // Mipmap data offset
|
||||||
|
|
||||||
|
TraceLog(LOG_DEBUG, "Load texture from data memory address: 0x%x", data);
|
||||||
|
|
||||||
|
// Load the different mipmap levels
|
||||||
|
for (int i = 0; i < mipmapCount; i++)
|
||||||
{
|
{
|
||||||
case UNCOMPRESSED_GRAYSCALE: glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
|
unsigned int mipSize = GetPixelDataSize(mipWidth, mipHeight, format);
|
||||||
case UNCOMPRESSED_GRAY_ALPHA: glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
|
|
||||||
case UNCOMPRESSED_R5G6B5: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (unsigned short *)data); break;
|
int glInternalFormat, glFormat, glType;
|
||||||
case UNCOMPRESSED_R8G8B8: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
|
GetGlFormats(format, &glInternalFormat, &glFormat, &glType);
|
||||||
case UNCOMPRESSED_R5G5B5A1: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break;
|
|
||||||
case UNCOMPRESSED_R4G4B4A4: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break;
|
TraceLog(LOG_DEBUG, "Load mipmap level %i (%i x %i), size: %i, offset: %i", i, mipWidth, mipHeight, mipSize, mipOffset);
|
||||||
case UNCOMPRESSED_R8G8B8A8: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_21)
|
if (glInternalFormat != -1)
|
||||||
case COMPRESSED_DXT1_RGB: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, mipmapCount); break;
|
|
||||||
case COMPRESSED_DXT1_RGBA: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, mipmapCount); break;
|
|
||||||
case COMPRESSED_DXT3_RGBA: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, mipmapCount); break;
|
|
||||||
case COMPRESSED_DXT5_RGBA: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, mipmapCount); break;
|
|
||||||
#endif
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_ES2)
|
|
||||||
case UNCOMPRESSED_R32G32B32: if (texFloatSupported) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_FLOAT, (float *)data); break; // NOTE: Requires extension OES_texture_float
|
|
||||||
case COMPRESSED_DXT1_RGB: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, mipmapCount); break;
|
|
||||||
case COMPRESSED_DXT1_RGBA: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, mipmapCount); break;
|
|
||||||
case COMPRESSED_DXT3_RGBA: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, mipmapCount); break; // NOTE: Not supported by WebGL
|
|
||||||
case COMPRESSED_DXT5_RGBA: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, mipmapCount); break; // NOTE: Not supported by WebGL
|
|
||||||
case COMPRESSED_ETC1_RGB: if (texCompETC1Supported) LoadTextureCompressed((unsigned char *)data, width, height, GL_ETC1_RGB8_OES, mipmapCount); break; // NOTE: Requires OpenGL ES 2.0 or OpenGL 4.3
|
|
||||||
case COMPRESSED_ETC2_RGB: if (texCompETC2Supported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGB8_ETC2, mipmapCount); break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3
|
|
||||||
case COMPRESSED_ETC2_EAC_RGBA: if (texCompETC2Supported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA8_ETC2_EAC, mipmapCount); break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3
|
|
||||||
case COMPRESSED_PVRT_RGB: if (texCompPVRTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, mipmapCount); break; // NOTE: Requires PowerVR GPU
|
|
||||||
case COMPRESSED_PVRT_RGBA: if (texCompPVRTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, mipmapCount); break; // NOTE: Requires PowerVR GPU
|
|
||||||
case COMPRESSED_ASTC_4x4_RGBA: if (texCompASTCSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_ASTC_4x4_KHR, mipmapCount); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3
|
|
||||||
case COMPRESSED_ASTC_8x8_RGBA: if (texCompASTCSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_ASTC_8x8_KHR, mipmapCount); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3
|
|
||||||
#endif
|
|
||||||
default: TraceLog(LOG_WARNING, "Texture format not supported"); break;
|
|
||||||
}
|
|
||||||
#elif defined(GRAPHICS_API_OPENGL_33)
|
|
||||||
// NOTE: We define internal (GPU) format as GL_RGBA8 (probably BGRA8 in practice, driver takes care)
|
|
||||||
// NOTE: On embedded systems, we let the driver choose the best internal format
|
|
||||||
|
|
||||||
// Support for multiple color modes (16bit color modes and grayscale)
|
|
||||||
// (sized)internalFormat format type
|
|
||||||
// GL_R GL_RED GL_UNSIGNED_BYTE
|
|
||||||
// GL_RGB565 GL_RGB GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5
|
|
||||||
// GL_RGB5_A1 GL_RGBA GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_5_5_1
|
|
||||||
// GL_RGBA4 GL_RGBA GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_4_4_4_4
|
|
||||||
// GL_RGBA8 GL_RGBA GL_UNSIGNED_BYTE
|
|
||||||
// GL_RGB8 GL_RGB GL_UNSIGNED_BYTE
|
|
||||||
|
|
||||||
switch (format)
|
|
||||||
{
|
|
||||||
case UNCOMPRESSED_GRAYSCALE:
|
|
||||||
{
|
{
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, (unsigned char *)data);
|
if (format < COMPRESSED_DXT1_RGB) glTexImage2D(GL_TEXTURE_2D, i, glInternalFormat, mipWidth, mipHeight, 0, glFormat, glType, (unsigned char *)data + mipOffset);
|
||||||
|
else glCompressedTexImage2D(GL_TEXTURE_2D, i, glInternalFormat, mipWidth, mipHeight, 0, mipSize, (unsigned char *)data + mipOffset);
|
||||||
// With swizzleMask we define how a one channel texture will be mapped to RGBA
|
|
||||||
// Required GL >= 3.3 or EXT_texture_swizzle/ARB_texture_swizzle
|
#if defined(GRAPHICS_API_OPENGL_33)
|
||||||
GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_ONE };
|
if (format == UNCOMPRESSED_GRAYSCALE)
|
||||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
{
|
||||||
|
GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_ONE };
|
||||||
TraceLog(LOG_INFO, "[TEX ID %i] Grayscale texture loaded and swizzled", id);
|
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||||
} break;
|
}
|
||||||
case UNCOMPRESSED_GRAY_ALPHA:
|
else if (format == UNCOMPRESSED_GRAY_ALPHA)
|
||||||
{
|
{
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RG8, width, height, 0, GL_RG, GL_UNSIGNED_BYTE, (unsigned char *)data);
|
GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_GREEN };
|
||||||
|
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||||
GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_GREEN };
|
}
|
||||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
#endif
|
||||||
} break;
|
}
|
||||||
|
|
||||||
case UNCOMPRESSED_R5G6B5: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (unsigned short *)data); break;
|
mipWidth /= 2;
|
||||||
case UNCOMPRESSED_R8G8B8: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
|
mipHeight /= 2;
|
||||||
case UNCOMPRESSED_R5G5B5A1: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5_A1, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break;
|
mipOffset += mipSize;
|
||||||
case UNCOMPRESSED_R4G4B4A4: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA4, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break;
|
|
||||||
case UNCOMPRESSED_R8G8B8A8: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
|
// Security check for NPOT textures
|
||||||
case UNCOMPRESSED_R32G32B32: if (texFloatSupported) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, height, 0, GL_RGB, GL_FLOAT, (float *)data); break;
|
if (mipWidth < 1) mipWidth = 1;
|
||||||
case COMPRESSED_DXT1_RGB: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, mipmapCount); break;
|
if (mipHeight < 1) mipHeight = 1;
|
||||||
case COMPRESSED_DXT1_RGBA: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, mipmapCount); break;
|
|
||||||
case COMPRESSED_DXT3_RGBA: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, mipmapCount); break;
|
|
||||||
case COMPRESSED_DXT5_RGBA: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, mipmapCount); break;
|
|
||||||
case COMPRESSED_ETC1_RGB: if (texCompETC1Supported) LoadTextureCompressed((unsigned char *)data, width, height, GL_ETC1_RGB8_OES, mipmapCount); break; // NOTE: Requires OpenGL ES 2.0 or OpenGL 4.3
|
|
||||||
case COMPRESSED_ETC2_RGB: if (texCompETC2Supported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGB8_ETC2, mipmapCount); break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3
|
|
||||||
case COMPRESSED_ETC2_EAC_RGBA: if (texCompETC2Supported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA8_ETC2_EAC, mipmapCount); break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3
|
|
||||||
case COMPRESSED_PVRT_RGB: if (texCompPVRTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, mipmapCount); break; // NOTE: Requires PowerVR GPU
|
|
||||||
case COMPRESSED_PVRT_RGBA: if (texCompPVRTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, mipmapCount); break; // NOTE: Requires PowerVR GPU
|
|
||||||
case COMPRESSED_ASTC_4x4_RGBA: if (texCompASTCSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_ASTC_4x4_KHR, mipmapCount); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3
|
|
||||||
case COMPRESSED_ASTC_8x8_RGBA: if (texCompASTCSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_ASTC_8x8_KHR, mipmapCount); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3
|
|
||||||
default: TraceLog(LOG_WARNING, "Texture format not recognized"); break;
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// Texture parameters configuration
|
// Texture parameters configuration
|
||||||
// NOTE: glTexParameteri does NOT affect texture uploading, just the way it's used
|
// NOTE: glTexParameteri does NOT affect texture uploading, just the way it's used
|
||||||
|
@ -1504,8 +1503,9 @@ unsigned int rlLoadTexture(void *data, int width, int height, int format, int mi
|
||||||
#if defined(GRAPHICS_API_OPENGL_33)
|
#if defined(GRAPHICS_API_OPENGL_33)
|
||||||
if (mipmapCount > 1)
|
if (mipmapCount > 1)
|
||||||
{
|
{
|
||||||
|
// Activate Trilinear filtering if mipmaps are available
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
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 (must be available)
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1516,7 +1516,7 @@ unsigned int rlLoadTexture(void *data, int width, int height, int format, int mi
|
||||||
// Unbind current texture
|
// Unbind current texture
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
if (id > 0) TraceLog(LOG_INFO, "[TEX ID %i] Texture created successfully (%ix%i)", id, width, height);
|
if (id > 0) TraceLog(LOG_INFO, "[TEX ID %i] Texture created successfully (%ix%i - %i mipmaps)", id, width, height, mipmapCount);
|
||||||
else TraceLog(LOG_WARNING, "Texture could not be created");
|
else TraceLog(LOG_WARNING, "Texture could not be created");
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
|
@ -1526,33 +1526,15 @@ unsigned int rlLoadTexture(void *data, int width, int height, int format, int mi
|
||||||
void rlUpdateTexture(unsigned int id, int width, int height, int format, const void *data)
|
void rlUpdateTexture(unsigned int id, int width, int height, int format, const void *data)
|
||||||
{
|
{
|
||||||
glBindTexture(GL_TEXTURE_2D, id);
|
glBindTexture(GL_TEXTURE_2D, id);
|
||||||
|
|
||||||
|
int glInternalFormat, glFormat, glType;
|
||||||
|
GetGlFormats(format, &glInternalFormat, &glFormat, &glType);
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_33)
|
if ((glInternalFormat != -1) && (format < COMPRESSED_DXT1_RGB))
|
||||||
switch (format)
|
|
||||||
{
|
{
|
||||||
case UNCOMPRESSED_GRAYSCALE: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, glFormat, glType, (unsigned char *)data);
|
||||||
case UNCOMPRESSED_GRAY_ALPHA: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RG, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
|
|
||||||
case UNCOMPRESSED_R5G6B5: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (unsigned short *)data); break;
|
|
||||||
case UNCOMPRESSED_R8G8B8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
|
|
||||||
case UNCOMPRESSED_R5G5B5A1: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break;
|
|
||||||
case UNCOMPRESSED_R4G4B4A4: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break;
|
|
||||||
case UNCOMPRESSED_R8G8B8A8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
|
|
||||||
default: TraceLog(LOG_WARNING, "Texture format updating not supported"); break;
|
|
||||||
}
|
}
|
||||||
#elif defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_ES2)
|
else TraceLog(LOG_WARNING, "Texture format updating not supported");
|
||||||
// NOTE: on OpenGL ES 2.0 (WebGL), internalFormat must match format and options allowed are: GL_LUMINANCE, GL_RGB, GL_RGBA
|
|
||||||
switch (format)
|
|
||||||
{
|
|
||||||
case UNCOMPRESSED_GRAYSCALE: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
|
|
||||||
case UNCOMPRESSED_GRAY_ALPHA: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
|
|
||||||
case UNCOMPRESSED_R5G6B5: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (unsigned short *)data); break;
|
|
||||||
case UNCOMPRESSED_R8G8B8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
|
|
||||||
case UNCOMPRESSED_R5G5B5A1: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break;
|
|
||||||
case UNCOMPRESSED_R4G4B4A4: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break;
|
|
||||||
case UNCOMPRESSED_R8G8B8A8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
|
|
||||||
default: TraceLog(LOG_WARNING, "Texture format updating not supported"); break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unload texture from GPU memory
|
// Unload texture from GPU memory
|
||||||
|
@ -1687,7 +1669,7 @@ void rlGenerateMipmaps(Texture2D *texture)
|
||||||
// Load the mipmaps
|
// Load the mipmaps
|
||||||
for (int level = 1; level < mipmapCount; level++)
|
for (int level = 1; level < mipmapCount; level++)
|
||||||
{
|
{
|
||||||
glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA8, mipWidth, mipHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, data + offset);
|
glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA8, mipWidth, mipHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data + offset);
|
||||||
|
|
||||||
size = mipWidth*mipHeight*4;
|
size = mipWidth*mipHeight*4;
|
||||||
offset += size;
|
offset += size;
|
||||||
|
@ -2170,44 +2152,28 @@ void *rlReadTexturePixels(Texture2D texture)
|
||||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &format);
|
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &format);
|
||||||
// Other texture info: GL_TEXTURE_RED_SIZE, GL_TEXTURE_GREEN_SIZE, GL_TEXTURE_BLUE_SIZE, GL_TEXTURE_ALPHA_SIZE
|
// Other texture info: GL_TEXTURE_RED_SIZE, GL_TEXTURE_GREEN_SIZE, GL_TEXTURE_BLUE_SIZE, GL_TEXTURE_ALPHA_SIZE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int glFormat = 0, glType = 0;
|
|
||||||
|
|
||||||
unsigned int size = texture.width*texture.height;
|
|
||||||
|
|
||||||
// NOTE: GL_LUMINANCE and GL_LUMINANCE_ALPHA are removed since OpenGL 3.1
|
|
||||||
// Must be replaced by GL_RED and GL_RG on Core OpenGL 3.3
|
|
||||||
|
|
||||||
switch (texture.format)
|
|
||||||
{
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_11)
|
|
||||||
case UNCOMPRESSED_GRAYSCALE: pixels = (unsigned char *)malloc(size); glFormat = GL_LUMINANCE; glType = GL_UNSIGNED_BYTE; break; // 8 bit per pixel (no alpha)
|
|
||||||
case UNCOMPRESSED_GRAY_ALPHA: pixels = (unsigned char *)malloc(size*2); glFormat = GL_LUMINANCE_ALPHA; glType = GL_UNSIGNED_BYTE; break; // 16 bpp (2 channels)
|
|
||||||
#elif defined(GRAPHICS_API_OPENGL_33)
|
|
||||||
case UNCOMPRESSED_GRAYSCALE: pixels = (unsigned char *)malloc(size); glFormat = GL_RED; glType = GL_UNSIGNED_BYTE; break;
|
|
||||||
case UNCOMPRESSED_GRAY_ALPHA: pixels = (unsigned char *)malloc(size*2); glFormat = GL_RG; glType = GL_UNSIGNED_BYTE; break;
|
|
||||||
#endif
|
|
||||||
case UNCOMPRESSED_R5G6B5: pixels = (unsigned short *)malloc(size); glFormat = GL_RGB; glType = GL_UNSIGNED_SHORT_5_6_5; break; // 16 bpp
|
|
||||||
case UNCOMPRESSED_R8G8B8: pixels = (unsigned char *)malloc(size*3); glFormat = GL_RGB; glType = GL_UNSIGNED_BYTE; break; // 24 bpp
|
|
||||||
case UNCOMPRESSED_R5G5B5A1: pixels = (unsigned short *)malloc(size); glFormat = GL_RGBA; glType = GL_UNSIGNED_SHORT_5_5_5_1; break; // 16 bpp (1 bit alpha)
|
|
||||||
case UNCOMPRESSED_R4G4B4A4: pixels = (unsigned short *)malloc(size); glFormat = GL_RGBA; glType = GL_UNSIGNED_SHORT_4_4_4_4; break; // 16 bpp (4 bit alpha)
|
|
||||||
case UNCOMPRESSED_R8G8B8A8: pixels = (unsigned char *)malloc(size*4); glFormat = GL_RGBA; glType = GL_UNSIGNED_BYTE; break; // 32 bpp
|
|
||||||
default: TraceLog(LOG_WARNING, "Texture data retrieval, format not suported"); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: Each row written to or read from by OpenGL pixel operations like glGetTexImage are aligned to a 4 byte boundary by default, which may add some padding.
|
// NOTE: Each row written to or read from by OpenGL pixel operations like glGetTexImage are aligned to a 4 byte boundary by default, which may add some padding.
|
||||||
// Use glPixelStorei to modify padding with the GL_[UN]PACK_ALIGNMENT setting.
|
// Use glPixelStorei to modify padding with the GL_[UN]PACK_ALIGNMENT setting.
|
||||||
// GL_PACK_ALIGNMENT affects operations that read from OpenGL memory (glReadPixels, glGetTexImage, etc.)
|
// GL_PACK_ALIGNMENT affects operations that read from OpenGL memory (glReadPixels, glGetTexImage, etc.)
|
||||||
// GL_UNPACK_ALIGNMENT affects operations that write to OpenGL memory (glTexImage, etc.)
|
// GL_UNPACK_ALIGNMENT affects operations that write to OpenGL memory (glTexImage, etc.)
|
||||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||||
|
|
||||||
glGetTexImage(GL_TEXTURE_2D, 0, glFormat, glType, pixels);
|
int glInternalFormat, glFormat, glType;
|
||||||
|
GetGlFormats(texture.format, &glInternalFormat, &glFormat, &glType);
|
||||||
|
unsigned int size = GetPixelDataSize(texture.width, texture.height, texture.format);
|
||||||
|
|
||||||
|
if ((glInternalFormat != -1) && (texture.format < COMPRESSED_DXT1_RGB))
|
||||||
|
{
|
||||||
|
pixels = (unsigned char *)malloc(size);
|
||||||
|
glGetTexImage(GL_TEXTURE_2D, 0, glFormat, glType, pixels);
|
||||||
|
}
|
||||||
|
else TraceLog(LOG_WARNING, "Texture data retrieval not suported for pixel format");
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
|
|
||||||
RenderTexture2D fbo = rlLoadRenderTexture(texture.width, texture.height);
|
RenderTexture2D fbo = rlLoadRenderTexture(texture.width, texture.height);
|
||||||
|
|
||||||
// NOTE: Two possible Options:
|
// NOTE: Two possible Options:
|
||||||
|
@ -2358,46 +2324,57 @@ char *LoadText(const char *fileName)
|
||||||
|
|
||||||
// Load shader from files and bind default locations
|
// Load shader from files and bind default locations
|
||||||
// NOTE: If shader string is NULL, using default vertex/fragment shaders
|
// NOTE: If shader string is NULL, using default vertex/fragment shaders
|
||||||
Shader LoadShader(char *vsFileName, char *fsFileName)
|
Shader LoadShader(const char *vsFileName, const char *fsFileName)
|
||||||
{
|
{
|
||||||
Shader shader = { 0 };
|
Shader shader = { 0 };
|
||||||
|
|
||||||
|
char *vShaderStr = NULL;
|
||||||
|
char *fShaderStr = NULL;
|
||||||
|
|
||||||
|
if (vsFileName != NULL) vShaderStr = LoadText(vsFileName);
|
||||||
|
if (fsFileName != NULL) fShaderStr = LoadText(fsFileName);
|
||||||
|
|
||||||
|
shader = LoadShaderCode(vShaderStr, fShaderStr);
|
||||||
|
|
||||||
|
if (vShaderStr != NULL) free(vShaderStr);
|
||||||
|
if (fShaderStr != NULL) free(fShaderStr);
|
||||||
|
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load shader from code strings
|
||||||
|
// NOTE: If shader string is NULL, using default vertex/fragment shaders
|
||||||
|
Shader LoadShaderCode(char *vsCode, char *fsCode)
|
||||||
|
{
|
||||||
|
Shader shader = { 0 };
|
||||||
|
|
||||||
// NOTE: All locations must be reseted to -1 (no location)
|
// NOTE: All locations must be reseted to -1 (no location)
|
||||||
for (int i = 0; i < MAX_SHADER_LOCATIONS; i++) shader.locs[i] = -1;
|
for (int i = 0; i < MAX_SHADER_LOCATIONS; i++) shader.locs[i] = -1;
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
|
||||||
|
|
||||||
unsigned int vertexShaderId, fragmentShaderId;
|
|
||||||
|
|
||||||
if (vsFileName == NULL) vertexShaderId = defaultVShaderId;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char *vShaderStr = LoadText(vsFileName);
|
|
||||||
vertexShaderId = CompileShader(vShaderStr, GL_VERTEX_SHADER);
|
|
||||||
free(vShaderStr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fsFileName == NULL) fragmentShaderId = defaultVShaderId;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char* fShaderStr = LoadText(fsFileName);
|
|
||||||
fragmentShaderId = CompileShader(fShaderStr, GL_FRAGMENT_SHADER);
|
|
||||||
free(fShaderStr);
|
|
||||||
}
|
|
||||||
|
|
||||||
shader.id = LoadShaderProgram(vertexShaderId, fragmentShaderId);
|
|
||||||
|
|
||||||
if (vertexShaderId != defaultVShaderId) glDeleteShader(vertexShaderId);
|
|
||||||
if (fragmentShaderId != defaultFShaderId) glDeleteShader(fragmentShaderId);
|
|
||||||
|
|
||||||
if (shader.id == 0)
|
|
||||||
{
|
|
||||||
TraceLog(LOG_WARNING, "Custom shader could not be loaded");
|
|
||||||
shader = defaultShader;
|
|
||||||
}
|
|
||||||
|
|
||||||
// After shader loading, we TRY to set default location names
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
if (shader.id > 0) SetShaderDefaultLocations(&shader);
|
unsigned int vertexShaderId = defaultVShaderId;
|
||||||
|
unsigned int fragmentShaderId = defaultFShaderId;
|
||||||
|
|
||||||
|
if (vsCode != NULL) vertexShaderId = CompileShader(vsCode, GL_VERTEX_SHADER);
|
||||||
|
if (fsCode != NULL) fragmentShaderId = CompileShader(fsCode, GL_FRAGMENT_SHADER);
|
||||||
|
|
||||||
|
if ((vertexShaderId == defaultVShaderId) && (fragmentShaderId == defaultFShaderId)) shader = defaultShader;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
shader.id = LoadShaderProgram(vertexShaderId, fragmentShaderId);
|
||||||
|
|
||||||
|
if (vertexShaderId != defaultVShaderId) glDeleteShader(vertexShaderId);
|
||||||
|
if (fragmentShaderId != defaultFShaderId) glDeleteShader(fragmentShaderId);
|
||||||
|
|
||||||
|
if (shader.id == 0)
|
||||||
|
{
|
||||||
|
TraceLog(LOG_WARNING, "Custom shader could not be loaded");
|
||||||
|
shader = defaultShader;
|
||||||
|
}
|
||||||
|
|
||||||
|
// After shader loading, we TRY to set default location names
|
||||||
|
if (shader.id > 0) SetShaderDefaultLocations(&shader);
|
||||||
|
}
|
||||||
|
|
||||||
// Get available shader uniforms
|
// Get available shader uniforms
|
||||||
// NOTE: This information is useful for debug...
|
// NOTE: This information is useful for debug...
|
||||||
|
@ -2423,7 +2400,7 @@ Shader LoadShader(char *vsFileName, char *fsFileName)
|
||||||
TraceLog(LOG_DEBUG, "[SHDR ID %i] Active uniform [%s] set at location: %i", shader.id, name, location);
|
TraceLog(LOG_DEBUG, "[SHDR ID %i] Active uniform [%s] set at location: %i", shader.id, name, location);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return shader;
|
return shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2530,6 +2507,19 @@ void SetMatrixModelview(Matrix view)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return internal modelview matrix
|
||||||
|
Matrix GetMatrixModelview()
|
||||||
|
{
|
||||||
|
Matrix matrix = MatrixIdentity();
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_11)
|
||||||
|
float mat[16];
|
||||||
|
glGetFloatv(GL_MODELVIEW_MATRIX, mat);
|
||||||
|
#else
|
||||||
|
matrix = modelview;
|
||||||
|
#endif
|
||||||
|
return matrix;
|
||||||
|
}
|
||||||
|
|
||||||
// Generate cubemap texture from HDR texture
|
// Generate cubemap texture from HDR texture
|
||||||
// TODO: OpenGL ES 2.0 does not support GL_RGB16F texture format, neither GL_DEPTH_COMPONENT24
|
// TODO: OpenGL ES 2.0 does not support GL_RGB16F texture format, neither GL_DEPTH_COMPONENT24
|
||||||
Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size)
|
Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size)
|
||||||
|
@ -2975,9 +2965,11 @@ bool IsVrSimulatorReady(void)
|
||||||
// TODO: Review VR system to be more flexible, move distortion shader to user side
|
// TODO: Review VR system to be more flexible, move distortion shader to user side
|
||||||
void SetVrDistortionShader(Shader shader)
|
void SetVrDistortionShader(Shader shader)
|
||||||
{
|
{
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
vrConfig.distortionShader = shader;
|
vrConfig.distortionShader = shader;
|
||||||
|
|
||||||
//SetStereoConfig(info); // TODO: Must be reviewed to set new distortion shader uniform values...
|
//SetStereoConfig(info); // TODO: Must be reviewed to set new distortion shader uniform values...
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable/Disable VR experience (device or simulator)
|
// Enable/Disable VR experience (device or simulator)
|
||||||
|
@ -3108,42 +3100,6 @@ void EndVrDrawing(void)
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
// Convert image data to OpenGL texture (returns OpenGL valid Id)
|
|
||||||
// NOTE: Expected compressed image data and POT image
|
|
||||||
static void LoadTextureCompressed(unsigned char *data, int width, int height, int compressedFormat, int mipmapCount)
|
|
||||||
{
|
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
|
||||||
|
|
||||||
int blockSize = 0; // Bytes every block
|
|
||||||
int offset = 0;
|
|
||||||
|
|
||||||
if ((compressedFormat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT) ||
|
|
||||||
(compressedFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_ES2)
|
|
||||||
(compressedFormat == GL_ETC1_RGB8_OES) ||
|
|
||||||
#endif
|
|
||||||
(compressedFormat == GL_COMPRESSED_RGB8_ETC2)) blockSize = 8;
|
|
||||||
else blockSize = 16;
|
|
||||||
|
|
||||||
// Load the mipmap levels
|
|
||||||
for (int level = 0; level < mipmapCount && (width || height); level++)
|
|
||||||
{
|
|
||||||
unsigned int size = 0;
|
|
||||||
|
|
||||||
size = ((width + 3)/4)*((height + 3)/4)*blockSize;
|
|
||||||
|
|
||||||
glCompressedTexImage2D(GL_TEXTURE_2D, level, compressedFormat, width, height, 0, size, data + offset);
|
|
||||||
|
|
||||||
offset += size;
|
|
||||||
width /= 2;
|
|
||||||
height /= 2;
|
|
||||||
|
|
||||||
// Security check for NPOT textures
|
|
||||||
if (width < 1) width = 1;
|
|
||||||
if (height < 1) height = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compile custom shader and return shader id
|
// Compile custom shader and return shader id
|
||||||
static unsigned int CompileShader(const char *shaderStr, int type)
|
static unsigned int CompileShader(const char *shaderStr, int type)
|
||||||
{
|
{
|
||||||
|
@ -3161,7 +3117,7 @@ static unsigned int CompileShader(const char *shaderStr, int type)
|
||||||
int length;
|
int length;
|
||||||
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
|
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#if defined(_MSC_VER)
|
||||||
char *log = malloc(maxLength);
|
char *log = malloc(maxLength);
|
||||||
#else
|
#else
|
||||||
char log[maxLength];
|
char log[maxLength];
|
||||||
|
@ -3170,7 +3126,7 @@ static unsigned int CompileShader(const char *shaderStr, int type)
|
||||||
|
|
||||||
TraceLog(LOG_INFO, "%s", log);
|
TraceLog(LOG_INFO, "%s", log);
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#if defined(_MSC_VER)
|
||||||
free(log);
|
free(log);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -3377,6 +3333,7 @@ static void UnloadShaderDefault(void)
|
||||||
glDetachShader(defaultShader.id, defaultFShaderId);
|
glDetachShader(defaultShader.id, defaultFShaderId);
|
||||||
glDeleteShader(defaultVShaderId);
|
glDeleteShader(defaultVShaderId);
|
||||||
glDeleteShader(defaultFShaderId);
|
glDeleteShader(defaultFShaderId);
|
||||||
|
|
||||||
glDeleteProgram(defaultShader.id);
|
glDeleteProgram(defaultShader.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3958,6 +3915,58 @@ static void GenDrawCube(void)
|
||||||
glDeleteVertexArrays(1, &cubeVAO);
|
glDeleteVertexArrays(1, &cubeVAO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get OpenGL internal formats and data type from raylib PixelFormat
|
||||||
|
static void GetGlFormats(int format, int *glInternalFormat, int *glFormat, int *glType)
|
||||||
|
{
|
||||||
|
*glInternalFormat = -1;
|
||||||
|
*glFormat = -1;
|
||||||
|
*glType = -1;
|
||||||
|
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_21) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
|
// NOTE: on OpenGL ES 2.0 (WebGL), internalFormat must match format and options allowed are: GL_LUMINANCE, GL_RGB, GL_RGBA
|
||||||
|
case UNCOMPRESSED_GRAYSCALE: *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_UNSIGNED_BYTE; break;
|
||||||
|
case UNCOMPRESSED_GRAY_ALPHA: *glInternalFormat = GL_LUMINANCE_ALPHA; *glFormat = GL_LUMINANCE_ALPHA; *glType = GL_UNSIGNED_BYTE; break;
|
||||||
|
case UNCOMPRESSED_R5G6B5: *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_UNSIGNED_SHORT_5_6_5; break;
|
||||||
|
case UNCOMPRESSED_R8G8B8: *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_UNSIGNED_BYTE; break;
|
||||||
|
case UNCOMPRESSED_R5G5B5A1: *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_5_5_5_1; break;
|
||||||
|
case UNCOMPRESSED_R4G4B4A4: *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_4_4_4_4; break;
|
||||||
|
case UNCOMPRESSED_R8G8B8A8: *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_BYTE; break;
|
||||||
|
#if !defined(GRAPHICS_API_OPENGL_11)
|
||||||
|
case UNCOMPRESSED_R32: if (texFloatSupported) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
|
||||||
|
case UNCOMPRESSED_R32G32B32: if (texFloatSupported) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
|
||||||
|
case UNCOMPRESSED_R32G32B32A32: if (texFloatSupported) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
|
||||||
|
#endif
|
||||||
|
#elif defined(GRAPHICS_API_OPENGL_33)
|
||||||
|
case UNCOMPRESSED_GRAYSCALE: *glInternalFormat = GL_R8; *glFormat = GL_RED; *glType = GL_UNSIGNED_BYTE; break;
|
||||||
|
case UNCOMPRESSED_GRAY_ALPHA: *glInternalFormat = GL_RG8; *glFormat = GL_RG; *glType = GL_UNSIGNED_BYTE; break;
|
||||||
|
case UNCOMPRESSED_R5G6B5: *glInternalFormat = GL_RGB565; *glFormat = GL_RGB; *glType = GL_UNSIGNED_SHORT_5_6_5; break;
|
||||||
|
case UNCOMPRESSED_R8G8B8: *glInternalFormat = GL_RGB8; *glFormat = GL_RGB; *glType = GL_UNSIGNED_BYTE; break;
|
||||||
|
case UNCOMPRESSED_R5G5B5A1: *glInternalFormat = GL_RGB5_A1; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_5_5_5_1; break;
|
||||||
|
case UNCOMPRESSED_R4G4B4A4: *glInternalFormat = GL_RGBA4; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_4_4_4_4; break;
|
||||||
|
case UNCOMPRESSED_R8G8B8A8: *glInternalFormat = GL_RGBA8; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_BYTE; break;
|
||||||
|
case UNCOMPRESSED_R32: if (texFloatSupported) *glInternalFormat = GL_R32F; *glFormat = GL_RED; *glType = GL_FLOAT; break;
|
||||||
|
case UNCOMPRESSED_R32G32B32: if (texFloatSupported) *glInternalFormat = GL_RGB32F; *glFormat = GL_RGB; *glType = GL_FLOAT; break;
|
||||||
|
case UNCOMPRESSED_R32G32B32A32: if (texFloatSupported) *glInternalFormat = GL_RGBA32F; *glFormat = GL_RGBA; *glType = GL_FLOAT; break;
|
||||||
|
#endif
|
||||||
|
#if !defined(GRAPHICS_API_OPENGL_11)
|
||||||
|
case COMPRESSED_DXT1_RGB: if (texCompDXTSupported) *glInternalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; break;
|
||||||
|
case COMPRESSED_DXT1_RGBA: if (texCompDXTSupported) *glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; break;
|
||||||
|
case COMPRESSED_DXT3_RGBA: if (texCompDXTSupported) *glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break;
|
||||||
|
case COMPRESSED_DXT5_RGBA: if (texCompDXTSupported) *glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break;
|
||||||
|
case COMPRESSED_ETC1_RGB: if (texCompETC1Supported) *glInternalFormat = GL_ETC1_RGB8_OES; break; // NOTE: Requires OpenGL ES 2.0 or OpenGL 4.3
|
||||||
|
case COMPRESSED_ETC2_RGB: if (texCompETC2Supported) *glInternalFormat = GL_COMPRESSED_RGB8_ETC2; break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3
|
||||||
|
case COMPRESSED_ETC2_EAC_RGBA: if (texCompETC2Supported) *glInternalFormat = GL_COMPRESSED_RGBA8_ETC2_EAC; break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3
|
||||||
|
case COMPRESSED_PVRT_RGB: if (texCompPVRTSupported) *glInternalFormat = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; break; // NOTE: Requires PowerVR GPU
|
||||||
|
case COMPRESSED_PVRT_RGBA: if (texCompPVRTSupported) *glInternalFormat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; break; // NOTE: Requires PowerVR GPU
|
||||||
|
case COMPRESSED_ASTC_4x4_RGBA: if (texCompASTCSupported) *glInternalFormat = GL_COMPRESSED_RGBA_ASTC_4x4_KHR; break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3
|
||||||
|
case COMPRESSED_ASTC_8x8_RGBA: if (texCompASTCSupported) *glInternalFormat = GL_COMPRESSED_RGBA_ASTC_8x8_KHR; break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3
|
||||||
|
#endif
|
||||||
|
default: TraceLog(LOG_WARNING, "Texture format not supported"); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(SUPPORT_VR_SIMULATOR)
|
#if defined(SUPPORT_VR_SIMULATOR)
|
||||||
// Configure stereo rendering (including distortion shader) with HMD device parameters
|
// Configure stereo rendering (including distortion shader) with HMD device parameters
|
||||||
// NOTE: It modifies the global variable: VrStereoConfig vrConfig
|
// NOTE: It modifies the global variable: VrStereoConfig vrConfig
|
||||||
|
|
|
@ -169,7 +169,7 @@ typedef unsigned char byte;
|
||||||
int width; // Texture base width
|
int width; // Texture base width
|
||||||
int height; // Texture base height
|
int height; // Texture base height
|
||||||
int mipmaps; // Mipmap levels, 1 by default
|
int mipmaps; // Mipmap levels, 1 by default
|
||||||
int format; // Data format (TextureFormat)
|
int format; // Data format (PixelFormat)
|
||||||
} Texture2D;
|
} Texture2D;
|
||||||
|
|
||||||
// RenderTexture2D type, for texture rendering
|
// RenderTexture2D type, for texture rendering
|
||||||
|
@ -259,7 +259,9 @@ typedef unsigned char byte;
|
||||||
UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha)
|
UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha)
|
||||||
UNCOMPRESSED_R4G4B4A4, // 16 bpp (4 bit alpha)
|
UNCOMPRESSED_R4G4B4A4, // 16 bpp (4 bit alpha)
|
||||||
UNCOMPRESSED_R8G8B8A8, // 32 bpp
|
UNCOMPRESSED_R8G8B8A8, // 32 bpp
|
||||||
UNCOMPRESSED_R32G32B32, // 32 bit per channel (float) - HDR
|
UNCOMPRESSED_R32, // 32 bpp (1 channel - float)
|
||||||
|
UNCOMPRESSED_R32G32B32, // 32*3 bpp (3 channels - float)
|
||||||
|
UNCOMPRESSED_R32G32B32A32, // 32*4 bpp (4 channels - float)
|
||||||
COMPRESSED_DXT1_RGB, // 4 bpp (no alpha)
|
COMPRESSED_DXT1_RGB, // 4 bpp (no alpha)
|
||||||
COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha)
|
COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha)
|
||||||
COMPRESSED_DXT3_RGBA, // 8 bpp
|
COMPRESSED_DXT3_RGBA, // 8 bpp
|
||||||
|
@ -271,7 +273,7 @@ typedef unsigned char byte;
|
||||||
COMPRESSED_PVRT_RGBA, // 4 bpp
|
COMPRESSED_PVRT_RGBA, // 4 bpp
|
||||||
COMPRESSED_ASTC_4x4_RGBA, // 8 bpp
|
COMPRESSED_ASTC_4x4_RGBA, // 8 bpp
|
||||||
COMPRESSED_ASTC_8x8_RGBA // 2 bpp
|
COMPRESSED_ASTC_8x8_RGBA // 2 bpp
|
||||||
} TextureFormat;
|
} PixelFormat;
|
||||||
|
|
||||||
// Texture parameters: filter mode
|
// Texture parameters: filter mode
|
||||||
// NOTE 1: Filtering considers mipmaps if available in the texture
|
// NOTE 1: Filtering considers mipmaps if available in the texture
|
||||||
|
@ -422,6 +424,7 @@ void rlglClose(void); // De-inititialize rlgl (buffers
|
||||||
void rlglDraw(void); // Update and Draw default buffers (lines, triangles, quads)
|
void rlglDraw(void); // Update and Draw default buffers (lines, triangles, quads)
|
||||||
|
|
||||||
int rlGetVersion(void); // Returns current OpenGL version
|
int rlGetVersion(void); // Returns current OpenGL version
|
||||||
|
void rlSetDebugMarker(const char *text); // Set debug marker for analysis
|
||||||
void rlLoadExtensions(void *loader); // Load OpenGL extensions
|
void rlLoadExtensions(void *loader); // Load OpenGL extensions
|
||||||
Vector3 rlUnproject(Vector3 source, Matrix proj, Matrix view); // Get world coordinates from screen coordinates
|
Vector3 rlUnproject(Vector3 source, Matrix proj, Matrix view); // Get world coordinates from screen coordinates
|
||||||
|
|
||||||
|
@ -456,11 +459,13 @@ Texture2D GetTextureDefault(void); // Get default texture
|
||||||
|
|
||||||
// Shader configuration functions
|
// Shader configuration functions
|
||||||
int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location
|
int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location
|
||||||
void SetShaderValue(Shader shader, int uniformLoc, float *value, int size); // Set shader uniform value (float)
|
void SetShaderValue(Shader shader, int uniformLoc, const float *value, int size); // Set shader uniform value (float)
|
||||||
void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size); // Set shader uniform value (int)
|
void SetShaderValuei(Shader shader, int uniformLoc, const int *value, int size); // Set shader uniform value (int)
|
||||||
void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // Set shader uniform value (matrix 4x4)
|
void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // Set shader uniform value (matrix 4x4)
|
||||||
void SetMatrixProjection(Matrix proj); // Set a custom projection matrix (replaces internal projection matrix)
|
void SetMatrixProjection(Matrix proj); // Set a custom projection matrix (replaces internal projection matrix)
|
||||||
void SetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix)
|
void SetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix)
|
||||||
|
Matrix GetMatrixModelview(); // Get internal modelview matrix
|
||||||
|
|
||||||
|
|
||||||
// Texture maps generation (PBR)
|
// Texture maps generation (PBR)
|
||||||
// NOTE: Required shaders should be provided
|
// NOTE: Required shaders should be provided
|
||||||
|
|
|
@ -40,6 +40,20 @@ func LoadShader(vsFileName string, fsFileName string) Shader {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadShaderCode - Load shader from code strings and bind default locations
|
||||||
|
func LoadShaderCode(vsCode string, fsCode string) Shader {
|
||||||
|
cvsCode := C.CString(vsCode)
|
||||||
|
defer C.free(unsafe.Pointer(cvsCode))
|
||||||
|
|
||||||
|
cfsCode := C.CString(fsCode)
|
||||||
|
defer C.free(unsafe.Pointer(cfsCode))
|
||||||
|
|
||||||
|
ret := C.LoadShaderCode(cvsCode, cfsCode)
|
||||||
|
v := newShaderFromPointer(unsafe.Pointer(&ret))
|
||||||
|
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
// UnloadShader - Unload a custom shader from memory
|
// UnloadShader - Unload a custom shader from memory
|
||||||
func UnloadShader(shader Shader) {
|
func UnloadShader(shader Shader) {
|
||||||
cshader := shader.cptr()
|
cshader := shader.cptr()
|
||||||
|
|
197
raylib/shapes.c
197
raylib/shapes.c
|
@ -1,5 +1,3 @@
|
||||||
// +build !js
|
|
||||||
|
|
||||||
/**********************************************************************************************
|
/**********************************************************************************************
|
||||||
*
|
*
|
||||||
* raylib.shapes - Basic functions to draw 2d Shapes and check collisions
|
* raylib.shapes - Basic functions to draw 2d Shapes and check collisions
|
||||||
|
@ -12,10 +10,14 @@
|
||||||
* #define SUPPORT_TRIANGLES_ONLY
|
* #define SUPPORT_TRIANGLES_ONLY
|
||||||
* Draw shapes using only TRIANGLES, vertex are accumulated in TRIANGLES arrays
|
* Draw shapes using only TRIANGLES, vertex are accumulated in TRIANGLES arrays
|
||||||
*
|
*
|
||||||
|
* #define USE_DEFAULT_FONT_TEXTURE
|
||||||
|
* Draw rectangle shapes using font texture white character instead of default white texture
|
||||||
|
* Allows drawing rectangles and text with a single draw call, very useful for GUI systems!
|
||||||
|
*
|
||||||
*
|
*
|
||||||
* LICENSE: zlib/libpng
|
* LICENSE: zlib/libpng
|
||||||
*
|
*
|
||||||
* Copyright (c) 2014-2017 Ramon Santamaria (@raysan5)
|
* Copyright (c) 2014-2018 Ramon Santamaria (@raysan5)
|
||||||
*
|
*
|
||||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
* 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.
|
* will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
@ -34,6 +36,8 @@
|
||||||
*
|
*
|
||||||
**********************************************************************************************/
|
**********************************************************************************************/
|
||||||
|
|
||||||
|
#define USE_DEFAULT_FONT_TEXTURE
|
||||||
|
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
|
|
||||||
#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2
|
#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2
|
||||||
|
@ -247,6 +251,78 @@ void DrawRectangle(int posX, int posY, int width, int height, Color color)
|
||||||
DrawRectangleV(position, size, color);
|
DrawRectangleV(position, size, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw a color-filled rectangle (Vector version)
|
||||||
|
// NOTE: On OpenGL 3.3 and ES2 we use QUADS to avoid drawing order issues (view rlglDraw)
|
||||||
|
void DrawRectangleV(Vector2 position, Vector2 size, Color color)
|
||||||
|
{
|
||||||
|
if (rlGetVersion() == OPENGL_11)
|
||||||
|
{
|
||||||
|
rlBegin(RL_TRIANGLES);
|
||||||
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
|
rlVertex2i(position.x, position.y);
|
||||||
|
rlVertex2i(position.x, position.y + size.y);
|
||||||
|
rlVertex2i(position.x + size.x, position.y + size.y);
|
||||||
|
|
||||||
|
rlVertex2i(position.x, position.y);
|
||||||
|
rlVertex2i(position.x + size.x, position.y + size.y);
|
||||||
|
rlVertex2i(position.x + size.x, position.y);
|
||||||
|
rlEnd();
|
||||||
|
}
|
||||||
|
else if ((rlGetVersion() == OPENGL_21) || (rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20))
|
||||||
|
{
|
||||||
|
#if defined(USE_DEFAULT_FONT_TEXTURE)
|
||||||
|
// Draw rectangle using font texture white character
|
||||||
|
rlEnableTexture(GetDefaultFont().texture.id);
|
||||||
|
|
||||||
|
rlBegin(RL_QUADS);
|
||||||
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
rlNormal3f(0.0f, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
// NOTE: Default raylib font character 95 is a white square
|
||||||
|
rlTexCoord2f((float)GetDefaultFont().chars[95].rec.x/GetDefaultFont().texture.width,
|
||||||
|
(float)GetDefaultFont().chars[95].rec.y/GetDefaultFont().texture.height);
|
||||||
|
rlVertex2f(position.x, position.y);
|
||||||
|
|
||||||
|
rlTexCoord2f((float)GetDefaultFont().chars[95].rec.x/GetDefaultFont().texture.width,
|
||||||
|
(float)(GetDefaultFont().chars[95].rec.y + GetDefaultFont().chars[95].rec.height)/GetDefaultFont().texture.height);
|
||||||
|
rlVertex2f(position.x, position.y + size.y);
|
||||||
|
|
||||||
|
rlTexCoord2f((float)(GetDefaultFont().chars[95].rec.x + GetDefaultFont().chars[95].rec.width)/GetDefaultFont().texture.width,
|
||||||
|
(float)(GetDefaultFont().chars[95].rec.y + GetDefaultFont().chars[95].rec.height)/GetDefaultFont().texture.height);
|
||||||
|
rlVertex2f(position.x + size.x, position.y + size.y);
|
||||||
|
|
||||||
|
rlTexCoord2f((float)(GetDefaultFont().chars[95].rec.x + GetDefaultFont().chars[95].rec.width)/GetDefaultFont().texture.width,
|
||||||
|
(float)GetDefaultFont().chars[95].rec.y/GetDefaultFont().texture.height);
|
||||||
|
rlVertex2f(position.x + size.x, position.y);
|
||||||
|
rlEnd();
|
||||||
|
|
||||||
|
rlDisableTexture();
|
||||||
|
#else
|
||||||
|
rlEnableTexture(GetTextureDefault().id); // Default white texture
|
||||||
|
|
||||||
|
rlBegin(RL_QUADS);
|
||||||
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
rlNormal3f(0.0f, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
rlTexCoord2f(0.0f, 0.0f);
|
||||||
|
rlVertex2f(position.x, position.y);
|
||||||
|
|
||||||
|
rlTexCoord2f(0.0f, 1.0f);
|
||||||
|
rlVertex2f(position.x, position.y + size.y);
|
||||||
|
|
||||||
|
rlTexCoord2f(1.0f, 1.0f);
|
||||||
|
rlVertex2f(position.x + size.x, position.y + size.y);
|
||||||
|
|
||||||
|
rlTexCoord2f(1.0f, 0.0f);
|
||||||
|
rlVertex2f(position.x + size.x, position.y);
|
||||||
|
rlEnd();
|
||||||
|
|
||||||
|
rlDisableTexture();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Draw a color-filled rectangle
|
// Draw a color-filled rectangle
|
||||||
void DrawRectangleRec(Rectangle rec, Color color)
|
void DrawRectangleRec(Rectangle rec, Color color)
|
||||||
{
|
{
|
||||||
|
@ -294,6 +370,37 @@ void DrawRectangleGradientH(int posX, int posY, int width, int height, Color col
|
||||||
// NOTE: Colors refer to corners, starting at top-lef corner and counter-clockwise
|
// NOTE: Colors refer to corners, starting at top-lef corner and counter-clockwise
|
||||||
void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4)
|
void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4)
|
||||||
{
|
{
|
||||||
|
#if defined(USE_DEFAULT_FONT_TEXTURE)
|
||||||
|
// Draw rectangle using font texture white character
|
||||||
|
rlEnableTexture(GetDefaultFont().texture.id);
|
||||||
|
|
||||||
|
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((float)GetDefaultFont().chars[95].rec.x/GetDefaultFont().texture.width,
|
||||||
|
(float)GetDefaultFont().chars[95].rec.y/GetDefaultFont().texture.height);
|
||||||
|
rlVertex2f(rec.x, rec.y);
|
||||||
|
|
||||||
|
rlColor4ub(col2.r, col2.g, col2.b, col2.a);
|
||||||
|
rlTexCoord2f((float)GetDefaultFont().chars[95].rec.x/GetDefaultFont().texture.width,
|
||||||
|
(float)(GetDefaultFont().chars[95].rec.y + GetDefaultFont().chars[95].rec.height)/GetDefaultFont().texture.height);
|
||||||
|
rlVertex2f(rec.x, rec.y + rec.height);
|
||||||
|
|
||||||
|
rlColor4ub(col3.r, col3.g, col3.b, col3.a);
|
||||||
|
rlTexCoord2f((float)(GetDefaultFont().chars[95].rec.x + GetDefaultFont().chars[95].rec.width)/GetDefaultFont().texture.width,
|
||||||
|
(float)(GetDefaultFont().chars[95].rec.y + GetDefaultFont().chars[95].rec.height)/GetDefaultFont().texture.height);
|
||||||
|
rlVertex2f(rec.x + rec.width, rec.y + rec.height);
|
||||||
|
|
||||||
|
rlColor4ub(col4.r, col4.g, col4.b, col4.a);
|
||||||
|
rlTexCoord2f((float)(GetDefaultFont().chars[95].rec.x + GetDefaultFont().chars[95].rec.width)/GetDefaultFont().texture.width,
|
||||||
|
(float)GetDefaultFont().chars[95].rec.y/GetDefaultFont().texture.height);
|
||||||
|
rlVertex2f(rec.x + rec.width, rec.y);
|
||||||
|
rlEnd();
|
||||||
|
|
||||||
|
rlDisableTexture();
|
||||||
|
#else
|
||||||
rlEnableTexture(GetTextureDefault().id); // Default white texture
|
rlEnableTexture(GetTextureDefault().id); // Default white texture
|
||||||
|
|
||||||
rlBegin(RL_QUADS);
|
rlBegin(RL_QUADS);
|
||||||
|
@ -315,70 +422,9 @@ void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3,
|
||||||
rlTexCoord2f(1.0f, 0.0f);
|
rlTexCoord2f(1.0f, 0.0f);
|
||||||
rlVertex2f(rec.x + rec.width, rec.y);
|
rlVertex2f(rec.x + rec.width, rec.y);
|
||||||
rlEnd();
|
rlEnd();
|
||||||
|
|
||||||
// Draw rectangle using font texture white character
|
|
||||||
/*
|
|
||||||
rlTexCoord2f((float)GetDefaultFont().chars[95].rec.x/GetDefaultFont().texture.width,
|
|
||||||
(float)GetDefaultFont().chars[95].rec.y/GetDefaultFont().texture.height);
|
|
||||||
rlVertex2f(rec.x, rec.y);
|
|
||||||
|
|
||||||
rlTexCoord2f((float)GetDefaultFont().chars[95].rec.x/GetDefaultFont().texture.width,
|
|
||||||
(float)(GetDefaultFont().chars[95].rec.y + GetDefaultFont().chars[95].rec.height)/GetDefaultFont().texture.height);
|
|
||||||
rlVertex2f(rec.x, rec.y + rec.height);
|
|
||||||
|
|
||||||
rlTexCoord2f((float)(GetDefaultFont().chars[95].rec.x + GetDefaultFont().chars[95].rec.width)/GetDefaultFont().texture.width,
|
|
||||||
(float)(GetDefaultFont().chars[95].rec.y + GetDefaultFont().chars[95].rec.height)/GetDefaultFont().texture.height);
|
|
||||||
rlVertex2f(rec.x + rec.width, rec.y + rec.height);
|
|
||||||
|
|
||||||
rlTexCoord2f((float)(GetDefaultFont().chars[95].rec.x + GetDefaultFont().chars[95].rec.width)/GetDefaultFont().texture.width,
|
|
||||||
(float)GetDefaultFont().chars[95].rec.y/GetDefaultFont().texture.height);
|
|
||||||
rlVertex2f(rec.x + rec.width, rec.y);
|
|
||||||
*/
|
|
||||||
|
|
||||||
rlDisableTexture();
|
rlDisableTexture();
|
||||||
}
|
#endif
|
||||||
|
|
||||||
// Draw a color-filled rectangle (Vector version)
|
|
||||||
// NOTE: On OpenGL 3.3 and ES2 we use QUADS to avoid drawing order issues (view rlglDraw)
|
|
||||||
void DrawRectangleV(Vector2 position, Vector2 size, Color color)
|
|
||||||
{
|
|
||||||
if (rlGetVersion() == OPENGL_11)
|
|
||||||
{
|
|
||||||
rlBegin(RL_TRIANGLES);
|
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
||||||
|
|
||||||
rlVertex2i(position.x, position.y);
|
|
||||||
rlVertex2i(position.x, position.y + size.y);
|
|
||||||
rlVertex2i(position.x + size.x, position.y + size.y);
|
|
||||||
|
|
||||||
rlVertex2i(position.x, position.y);
|
|
||||||
rlVertex2i(position.x + size.x, position.y + size.y);
|
|
||||||
rlVertex2i(position.x + size.x, position.y);
|
|
||||||
rlEnd();
|
|
||||||
}
|
|
||||||
else if ((rlGetVersion() == OPENGL_21) || (rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20))
|
|
||||||
{
|
|
||||||
rlEnableTexture(GetTextureDefault().id); // Default white texture
|
|
||||||
|
|
||||||
rlBegin(RL_QUADS);
|
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
||||||
rlNormal3f(0.0f, 0.0f, 1.0f);
|
|
||||||
|
|
||||||
rlTexCoord2f(0.0f, 0.0f);
|
|
||||||
rlVertex2f(position.x, position.y);
|
|
||||||
|
|
||||||
rlTexCoord2f(0.0f, 1.0f);
|
|
||||||
rlVertex2f(position.x, position.y + size.y);
|
|
||||||
|
|
||||||
rlTexCoord2f(1.0f, 1.0f);
|
|
||||||
rlVertex2f(position.x + size.x, position.y + size.y);
|
|
||||||
|
|
||||||
rlTexCoord2f(1.0f, 0.0f);
|
|
||||||
rlVertex2f(position.x + size.x, position.y);
|
|
||||||
rlEnd();
|
|
||||||
|
|
||||||
rlDisableTexture();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw rectangle outline
|
// Draw rectangle outline
|
||||||
|
@ -411,12 +457,19 @@ void DrawRectangleLines(int posX, int posY, int width, int height, Color color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw rectangle using text character (char: 127)
|
// Draw rectangle outline with extended parameters
|
||||||
// NOTE: Useful to avoid changing to default white texture
|
void DrawRectangleLinesEx(Rectangle rec, int lineThick, Color color)
|
||||||
void DrawRectangleT(int posX, int posY, int width, int height, Color color)
|
{
|
||||||
{
|
if (lineThick > rec.width || lineThick > rec.height)
|
||||||
DrawTexturePro(GetDefaultFont().texture, GetDefaultFont().chars[95].rec,
|
{
|
||||||
(Rectangle){ posX, posY, width, height }, (Vector2){ 0, 0 }, 0.0f, color);
|
if(rec.width > rec.height) lineThick = rec.height/2;
|
||||||
|
else if (rec.width < rec.height) lineThick = rec.width/2;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawRectangle(rec.x, rec.y, rec.width, lineThick, color);
|
||||||
|
DrawRectangle(rec.x - lineThick + rec.width, rec.y + lineThick, lineThick, rec.height - lineThick*2, color);
|
||||||
|
DrawRectangle(rec.x, rec.y + rec.height - lineThick, rec.width, lineThick, color);
|
||||||
|
DrawRectangle(rec.x, rec.y + lineThick, lineThick, rec.height - lineThick*2, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a triangle
|
// Draw a triangle
|
||||||
|
|
|
@ -172,14 +172,12 @@ func DrawRectangleLines(posX, posY, width, height int32, color Color) {
|
||||||
C.DrawRectangleLines(cposX, cposY, cwidth, cheight, *ccolor)
|
C.DrawRectangleLines(cposX, cposY, cwidth, cheight, *ccolor)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DrawRectangleT - Draw rectangle using text character
|
// DrawRectangleLinesEx - Draw rectangle outline with extended parameters
|
||||||
func DrawRectangleT(posX, posY, width, height int32, color Color) {
|
func DrawRectangleLinesEx(rec Rectangle, lineThick int32, color Color) {
|
||||||
cposX := (C.int)(posX)
|
crec := rec.cptr()
|
||||||
cposY := (C.int)(posY)
|
clineThick := (C.int)(lineThick)
|
||||||
cwidth := (C.int)(width)
|
|
||||||
cheight := (C.int)(height)
|
|
||||||
ccolor := color.cptr()
|
ccolor := color.cptr()
|
||||||
C.DrawRectangleT(cposX, cposY, cwidth, cheight, *ccolor)
|
C.DrawRectangleLinesEx(*crec, clineThick, *ccolor)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DrawTriangle - Draw a color-filled triangle
|
// DrawTriangle - Draw a color-filled triangle
|
||||||
|
|
159
raylib/text.c
159
raylib/text.c
|
@ -1,5 +1,3 @@
|
||||||
// +build !js
|
|
||||||
|
|
||||||
/**********************************************************************************************
|
/**********************************************************************************************
|
||||||
*
|
*
|
||||||
* raylib.text - Basic functions to load SpriteFonts and draw Text
|
* raylib.text - Basic functions to load SpriteFonts and draw Text
|
||||||
|
@ -19,7 +17,7 @@
|
||||||
*
|
*
|
||||||
* LICENSE: zlib/libpng
|
* LICENSE: zlib/libpng
|
||||||
*
|
*
|
||||||
* Copyright (c) 2014-2017 Ramon Santamaria (@raysan5)
|
* Copyright (c) 2014-2018 Ramon Santamaria (@raysan5)
|
||||||
*
|
*
|
||||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
* 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.
|
* will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
@ -68,8 +66,8 @@
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Defines and Macros
|
// Defines and Macros
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
#define MAX_FORMATTEXT_LENGTH 64
|
#define MAX_FORMATTEXT_LENGTH 256
|
||||||
#define MAX_SUBTEXT_LENGTH 64
|
#define MAX_SUBTEXT_LENGTH 256
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Types and Structures Definition
|
// Types and Structures Definition
|
||||||
|
@ -92,11 +90,9 @@ static SpriteFont defaultFont; // Default font provided by raylib
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module specific Functions Declaration
|
// Module specific Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
static int GetCharIndex(SpriteFont font, int letter);
|
|
||||||
|
|
||||||
static SpriteFont LoadImageFont(Image image, Color key, int firstChar); // Load a Image font file (XNA style)
|
static SpriteFont LoadImageFont(Image image, Color key, int firstChar); // Load a Image font file (XNA style)
|
||||||
#if defined(SUPPORT_FILEFORMAT_FNT)
|
#if defined(SUPPORT_FILEFORMAT_FNT)
|
||||||
static SpriteFont LoadBMFont(const char *fileName); // Load a BMFont file (AngelCode font file)
|
static SpriteFont LoadBMFont(const char *fileName); // Load a BMFont file (AngelCode font file)
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_TTF)
|
#if defined(SUPPORT_FILEFORMAT_TTF)
|
||||||
static SpriteFont LoadTTF(const char *fileName, int fontSize, int charsCount, int *fontChars); // Load spritefont from TTF data
|
static SpriteFont LoadTTF(const char *fileName, int fontSize, int charsCount, int *fontChars); // Load spritefont from TTF data
|
||||||
|
@ -290,40 +286,14 @@ SpriteFont LoadSpriteFont(const char *fileName)
|
||||||
|
|
||||||
SpriteFont spriteFont = { 0 };
|
SpriteFont spriteFont = { 0 };
|
||||||
|
|
||||||
// Check file extension
|
|
||||||
if (IsFileExtension(fileName, ".rres"))
|
|
||||||
{
|
|
||||||
// TODO: Read multiple resource blocks from file (RRES_FONT_IMAGE, RRES_FONT_CHARDATA)
|
|
||||||
RRES rres = LoadResource(fileName, 0);
|
|
||||||
|
|
||||||
// Load sprite font texture
|
|
||||||
if (rres[0].type == RRES_TYPE_FONT_IMAGE)
|
|
||||||
{
|
|
||||||
// NOTE: Parameters for RRES_FONT_IMAGE type are: width, height, format, mipmaps
|
|
||||||
Image image = LoadImagePro(rres[0].data, rres[0].param1, rres[0].param2, rres[0].param3);
|
|
||||||
spriteFont.texture = LoadTextureFromImage(image);
|
|
||||||
UnloadImage(image);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load sprite characters data
|
|
||||||
if (rres[1].type == RRES_TYPE_FONT_CHARDATA)
|
|
||||||
{
|
|
||||||
// NOTE: Parameters for RRES_FONT_CHARDATA type are: fontSize, charsCount
|
|
||||||
spriteFont.baseSize = rres[1].param1;
|
|
||||||
spriteFont.charsCount = rres[1].param2;
|
|
||||||
spriteFont.chars = rres[1].data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Do not free rres.data memory (chars info data!)
|
|
||||||
//UnloadResource(rres[0]);
|
|
||||||
}
|
|
||||||
#if defined(SUPPORT_FILEFORMAT_TTF)
|
#if defined(SUPPORT_FILEFORMAT_TTF)
|
||||||
else if (IsFileExtension(fileName, ".ttf")) spriteFont = LoadSpriteFontEx(fileName, DEFAULT_TTF_FONTSIZE, 0, NULL);
|
if (IsFileExtension(fileName, ".ttf")) spriteFont = LoadSpriteFontEx(fileName, DEFAULT_TTF_FONTSIZE, 0, NULL);
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_FNT)
|
#if defined(SUPPORT_FILEFORMAT_FNT)
|
||||||
else if (IsFileExtension(fileName, ".fnt")) spriteFont = LoadBMFont(fileName);
|
if (IsFileExtension(fileName, ".fnt")) spriteFont = LoadBMFont(fileName);
|
||||||
#endif
|
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
Image image = LoadImage(fileName);
|
Image image = LoadImage(fileName);
|
||||||
if (image.data != NULL) spriteFont = LoadImageFont(image, MAGENTA, DEFAULT_FIRST_CHAR);
|
if (image.data != NULL) spriteFont = LoadImageFont(image, MAGENTA, DEFAULT_FIRST_CHAR);
|
||||||
|
@ -346,21 +316,20 @@ SpriteFont LoadSpriteFont(const char *fileName)
|
||||||
SpriteFont LoadSpriteFontEx(const char *fileName, int fontSize, int charsCount, int *fontChars)
|
SpriteFont LoadSpriteFontEx(const char *fileName, int fontSize, int charsCount, int *fontChars)
|
||||||
{
|
{
|
||||||
SpriteFont spriteFont = { 0 };
|
SpriteFont spriteFont = { 0 };
|
||||||
|
int totalChars = 95; // Default charset [32..126]
|
||||||
|
|
||||||
#if defined(SUPPORT_FILEFORMAT_TTF)
|
#if defined(SUPPORT_FILEFORMAT_TTF)
|
||||||
if (IsFileExtension(fileName, ".ttf"))
|
if (IsFileExtension(fileName, ".ttf"))
|
||||||
{
|
{
|
||||||
if ((fontChars == NULL) || (charsCount == 0))
|
if (charsCount != 0) totalChars = charsCount;
|
||||||
|
|
||||||
|
if (fontChars == NULL)
|
||||||
{
|
{
|
||||||
int totalChars = 95; // Default charset [32..126]
|
fontChars = (int *)malloc(totalChars*sizeof(int));
|
||||||
|
for (int i = 0; i < totalChars; i++) fontChars[i] = i + 32; // Default first character: SPACE[32]
|
||||||
int *defaultFontChars = (int *)malloc(totalChars*sizeof(int));
|
|
||||||
|
|
||||||
for (int i = 0; i < totalChars; i++) defaultFontChars[i] = i + 32; // Default first character: SPACE[32]
|
|
||||||
|
|
||||||
spriteFont = LoadTTF(fileName, fontSize, totalChars, defaultFontChars);
|
|
||||||
}
|
}
|
||||||
else spriteFont = LoadTTF(fileName, fontSize, charsCount, fontChars);
|
|
||||||
|
spriteFont = LoadTTF(fileName, fontSize, totalChars, fontChars);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -374,13 +343,13 @@ SpriteFont LoadSpriteFontEx(const char *fileName, int fontSize, int charsCount,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unload SpriteFont from GPU memory (VRAM)
|
// Unload SpriteFont from GPU memory (VRAM)
|
||||||
void UnloadSpriteFont(SpriteFont spriteFont)
|
void UnloadSpriteFont(SpriteFont font)
|
||||||
{
|
{
|
||||||
// NOTE: Make sure spriteFont is not default font (fallback)
|
// NOTE: Make sure spriteFont is not default font (fallback)
|
||||||
if (spriteFont.texture.id != GetDefaultFont().texture.id)
|
if (font.texture.id != GetDefaultFont().texture.id)
|
||||||
{
|
{
|
||||||
UnloadTexture(spriteFont.texture);
|
UnloadTexture(font.texture);
|
||||||
free(spriteFont.chars);
|
free(font.chars);
|
||||||
|
|
||||||
TraceLog(LOG_DEBUG, "Unloaded sprite font data");
|
TraceLog(LOG_DEBUG, "Unloaded sprite font data");
|
||||||
}
|
}
|
||||||
|
@ -406,7 +375,7 @@ void DrawText(const char *text, int posX, int posY, int fontSize, Color color)
|
||||||
|
|
||||||
// Draw text using SpriteFont
|
// Draw text using SpriteFont
|
||||||
// NOTE: chars spacing is NOT proportional to fontSize
|
// NOTE: chars spacing is NOT proportional to fontSize
|
||||||
void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float fontSize, int spacing, Color tint)
|
void DrawTextEx(SpriteFont font, const char *text, Vector2 position, float fontSize, int spacing, Color tint)
|
||||||
{
|
{
|
||||||
int length = strlen(text);
|
int length = strlen(text);
|
||||||
int textOffsetX = 0; // Offset between characters
|
int textOffsetX = 0; // Offset between characters
|
||||||
|
@ -416,7 +385,7 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float
|
||||||
unsigned char letter; // Current character
|
unsigned char letter; // Current character
|
||||||
int index; // Index position in sprite font
|
int index; // Index position in sprite font
|
||||||
|
|
||||||
scaleFactor = fontSize/spriteFont.baseSize;
|
scaleFactor = fontSize/font.baseSize;
|
||||||
|
|
||||||
// NOTE: Some ugly hacks are made to support Latin-1 Extended characters directly
|
// NOTE: Some ugly hacks are made to support Latin-1 Extended characters directly
|
||||||
// written in C code files (codified by default as UTF-8)
|
// written in C code files (codified by default as UTF-8)
|
||||||
|
@ -426,7 +395,7 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float
|
||||||
if ((unsigned char)text[i] == '\n')
|
if ((unsigned char)text[i] == '\n')
|
||||||
{
|
{
|
||||||
// NOTE: Fixed line spacing of 1.5 lines
|
// NOTE: Fixed line spacing of 1.5 lines
|
||||||
textOffsetY += (int)((spriteFont.baseSize + spriteFont.baseSize/2)*scaleFactor);
|
textOffsetY += (int)((font.baseSize + font.baseSize/2)*scaleFactor);
|
||||||
textOffsetX = 0;
|
textOffsetX = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -435,26 +404,29 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float
|
||||||
{
|
{
|
||||||
// Support UTF-8 encoded values from [0xc2 0x80] -> [0xc2 0xbf](¿)
|
// Support UTF-8 encoded values from [0xc2 0x80] -> [0xc2 0xbf](¿)
|
||||||
letter = (unsigned char)text[i + 1];
|
letter = (unsigned char)text[i + 1];
|
||||||
index = GetCharIndex(spriteFont, (int)letter);
|
index = GetGlyphIndex(font, (int)letter);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
else if ((unsigned char)text[i] == 0xc3) // UTF-8 encoding identification HACK!
|
else if ((unsigned char)text[i] == 0xc3) // UTF-8 encoding identification HACK!
|
||||||
{
|
{
|
||||||
// Support UTF-8 encoded values from [0xc3 0x80](À) -> [0xc3 0xbf](ÿ)
|
// Support UTF-8 encoded values from [0xc3 0x80](À) -> [0xc3 0xbf](ÿ)
|
||||||
letter = (unsigned char)text[i + 1];
|
letter = (unsigned char)text[i + 1];
|
||||||
index = GetCharIndex(spriteFont, (int)letter + 64);
|
index = GetGlyphIndex(font, (int)letter + 64);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
else index = GetCharIndex(spriteFont, (unsigned char)text[i]);
|
else index = GetGlyphIndex(font, (unsigned char)text[i]);
|
||||||
|
|
||||||
|
if ((unsigned char)text[i] != ' ')
|
||||||
|
{
|
||||||
|
DrawTexturePro(font.texture, font.chars[index].rec,
|
||||||
|
(Rectangle){ position.x + textOffsetX + font.chars[index].offsetX*scaleFactor,
|
||||||
|
position.y + textOffsetY + font.chars[index].offsetY*scaleFactor,
|
||||||
|
font.chars[index].rec.width*scaleFactor,
|
||||||
|
font.chars[index].rec.height*scaleFactor }, (Vector2){ 0, 0 }, 0.0f, tint);
|
||||||
|
}
|
||||||
|
|
||||||
DrawTexturePro(spriteFont.texture, spriteFont.chars[index].rec,
|
if (font.chars[index].advanceX == 0) textOffsetX += (int)(font.chars[index].rec.width*scaleFactor + spacing);
|
||||||
(Rectangle){ position.x + textOffsetX + spriteFont.chars[index].offsetX*scaleFactor,
|
else textOffsetX += (int)(font.chars[index].advanceX*scaleFactor + spacing);
|
||||||
position.y + textOffsetY + spriteFont.chars[index].offsetY*scaleFactor,
|
|
||||||
spriteFont.chars[index].rec.width*scaleFactor,
|
|
||||||
spriteFont.chars[index].rec.height*scaleFactor }, (Vector2){ 0, 0 }, 0.0f, tint);
|
|
||||||
|
|
||||||
if (spriteFont.chars[index].advanceX == 0) textOffsetX += (int)(spriteFont.chars[index].rec.width*scaleFactor + spacing);
|
|
||||||
else textOffsetX += (int)(spriteFont.chars[index].advanceX*scaleFactor + spacing);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -516,7 +488,7 @@ int MeasureText(const char *text, int fontSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Measure string size for SpriteFont
|
// Measure string size for SpriteFont
|
||||||
Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, float fontSize, int spacing)
|
Vector2 MeasureTextEx(SpriteFont font, const char *text, float fontSize, int spacing)
|
||||||
{
|
{
|
||||||
int len = strlen(text);
|
int len = strlen(text);
|
||||||
int tempLen = 0; // Used to count longer text line num chars
|
int tempLen = 0; // Used to count longer text line num chars
|
||||||
|
@ -525,8 +497,8 @@ Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, float fontSize, i
|
||||||
float textWidth = 0;
|
float textWidth = 0;
|
||||||
float tempTextWidth = 0; // Used to count longer text line width
|
float tempTextWidth = 0; // Used to count longer text line width
|
||||||
|
|
||||||
float textHeight = (float)spriteFont.baseSize;
|
float textHeight = (float)font.baseSize;
|
||||||
float scaleFactor = fontSize/(float)spriteFont.baseSize;
|
float scaleFactor = fontSize/(float)font.baseSize;
|
||||||
|
|
||||||
for (int i = 0; i < len; i++)
|
for (int i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
|
@ -534,17 +506,17 @@ Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, float fontSize, i
|
||||||
|
|
||||||
if (text[i] != '\n')
|
if (text[i] != '\n')
|
||||||
{
|
{
|
||||||
int index = GetCharIndex(spriteFont, (int)text[i]);
|
int index = GetGlyphIndex(font, (int)text[i]);
|
||||||
|
|
||||||
if (spriteFont.chars[index].advanceX != 0) textWidth += spriteFont.chars[index].advanceX;
|
if (font.chars[index].advanceX != 0) textWidth += font.chars[index].advanceX;
|
||||||
else textWidth += (spriteFont.chars[index].rec.width + spriteFont.chars[index].offsetX);
|
else textWidth += (font.chars[index].rec.width + font.chars[index].offsetX);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
|
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
|
||||||
lenCounter = 0;
|
lenCounter = 0;
|
||||||
textWidth = 0;
|
textWidth = 0;
|
||||||
textHeight += ((float)spriteFont.baseSize*1.5f); // NOTE: Fixed line spacing of 1.5 lines
|
textHeight += ((float)font.baseSize*1.5f); // NOTE: Fixed line spacing of 1.5 lines
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tempLen < lenCounter) tempLen = lenCounter;
|
if (tempLen < lenCounter) tempLen = lenCounter;
|
||||||
|
@ -559,6 +531,28 @@ Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, float fontSize, i
|
||||||
return vec;
|
return vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns index position for a unicode character on spritefont
|
||||||
|
int GetGlyphIndex(SpriteFont font, int character)
|
||||||
|
{
|
||||||
|
#define UNORDERED_CHARSET
|
||||||
|
#if defined(UNORDERED_CHARSET)
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < font.charsCount; i++)
|
||||||
|
{
|
||||||
|
if (font.chars[i].value == character)
|
||||||
|
{
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return index;
|
||||||
|
#else
|
||||||
|
return (character - 32);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// Shows current FPS on top-left corner
|
// Shows current FPS on top-left corner
|
||||||
// NOTE: Uses default font
|
// NOTE: Uses default font
|
||||||
void DrawFPS(int posX, int posY)
|
void DrawFPS(int posX, int posY)
|
||||||
|
@ -585,27 +579,6 @@ void DrawFPS(int posX, int posY)
|
||||||
// Module specific Functions Definition
|
// Module specific Functions Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
static int GetCharIndex(SpriteFont font, int letter)
|
|
||||||
{
|
|
||||||
#define UNORDERED_CHARSET
|
|
||||||
#if defined(UNORDERED_CHARSET)
|
|
||||||
int index = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < font.charsCount; i++)
|
|
||||||
{
|
|
||||||
if (font.chars[i].value == letter)
|
|
||||||
{
|
|
||||||
index = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return index;
|
|
||||||
#else
|
|
||||||
return (letter - 32);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load an Image font file (XNA style)
|
// Load an Image font file (XNA style)
|
||||||
static SpriteFont LoadImageFont(Image image, Color key, int firstChar)
|
static SpriteFont LoadImageFont(Image image, Color key, int firstChar)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
// +build !js
|
|
||||||
|
|
||||||
/**********************************************************************************************
|
/**********************************************************************************************
|
||||||
*
|
*
|
||||||
* raylib.textures - Basic functions to load and draw Textures (2d)
|
* raylib.textures - Basic functions to load and draw Textures (2d)
|
||||||
|
@ -36,7 +34,7 @@
|
||||||
*
|
*
|
||||||
* LICENSE: zlib/libpng
|
* LICENSE: zlib/libpng
|
||||||
*
|
*
|
||||||
* Copyright (c) 2014-2017 Ramon Santamaria (@raysan5)
|
* Copyright (c) 2014-2018 Ramon Santamaria (@raysan5)
|
||||||
*
|
*
|
||||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
* 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.
|
* will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
@ -169,18 +167,7 @@ Image LoadImage(const char *fileName)
|
||||||
{
|
{
|
||||||
Image image = { 0 };
|
Image image = { 0 };
|
||||||
|
|
||||||
if (IsFileExtension(fileName, ".rres"))
|
if ((IsFileExtension(fileName, ".png"))
|
||||||
{
|
|
||||||
RRES rres = LoadResource(fileName, 0);
|
|
||||||
|
|
||||||
// NOTE: Parameters for RRES_TYPE_IMAGE are: width, height, format, mipmaps
|
|
||||||
|
|
||||||
if (rres[0].type == RRES_TYPE_IMAGE) image = LoadImagePro(rres[0].data, rres[0].param1, rres[0].param2, rres[0].param3);
|
|
||||||
else TraceLog(LOG_WARNING, "[%s] Resource file does not contain image data", fileName);
|
|
||||||
|
|
||||||
UnloadResource(rres);
|
|
||||||
}
|
|
||||||
else if ((IsFileExtension(fileName, ".png"))
|
|
||||||
#if defined(SUPPORT_FILEFORMAT_BMP)
|
#if defined(SUPPORT_FILEFORMAT_BMP)
|
||||||
|| (IsFileExtension(fileName, ".bmp"))
|
|| (IsFileExtension(fileName, ".bmp"))
|
||||||
#endif
|
#endif
|
||||||
|
@ -239,11 +226,12 @@ Image LoadImage(const char *fileName)
|
||||||
|
|
||||||
image.mipmaps = 1;
|
image.mipmaps = 1;
|
||||||
|
|
||||||
if (imgBpp == 3) image.format = UNCOMPRESSED_R32G32B32;
|
if (imgBpp == 1) image.format = UNCOMPRESSED_R32;
|
||||||
|
else if (imgBpp == 3) image.format = UNCOMPRESSED_R32G32B32;
|
||||||
|
else if (imgBpp == 4) image.format = UNCOMPRESSED_R32G32B32A32;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// TODO: Support different number of channels at 32 bit float
|
TraceLog(LOG_WARNING, "[%s] Image fileformat not supported", fileName);
|
||||||
TraceLog(LOG_WARNING, "[%s] Image fileformat not supported (only 3 channel 32 bit floats)", fileName);
|
|
||||||
UnloadImage(image);
|
UnloadImage(image);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -330,20 +318,9 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int
|
||||||
{
|
{
|
||||||
if (headerSize > 0) fseek(rawFile, headerSize, SEEK_SET);
|
if (headerSize > 0) fseek(rawFile, headerSize, SEEK_SET);
|
||||||
|
|
||||||
unsigned int size = width*height;
|
unsigned int size = GetPixelDataSize(width, height, format);
|
||||||
|
|
||||||
switch (format)
|
image.data = malloc(size); // Allocate required memory in bytes
|
||||||
{
|
|
||||||
case UNCOMPRESSED_GRAYSCALE: image.data = (unsigned char *)malloc(size); break; // 8 bit per pixel (no alpha)
|
|
||||||
case UNCOMPRESSED_GRAY_ALPHA: image.data = (unsigned char *)malloc(size*2); size *= 2; break; // 16 bpp (2 channels)
|
|
||||||
case UNCOMPRESSED_R5G6B5: image.data = (unsigned short *)malloc(size); break; // 16 bpp
|
|
||||||
case UNCOMPRESSED_R8G8B8: image.data = (unsigned char *)malloc(size*3); size *= 3; break; // 24 bpp
|
|
||||||
case UNCOMPRESSED_R5G5B5A1: image.data = (unsigned short *)malloc(size); break; // 16 bpp (1 bit alpha)
|
|
||||||
case UNCOMPRESSED_R4G4B4A4: image.data = (unsigned short *)malloc(size); break; // 16 bpp (4 bit alpha)
|
|
||||||
case UNCOMPRESSED_R8G8B8A8: image.data = (unsigned char *)malloc(size*4); size *= 4; break; // 32 bpp
|
|
||||||
case UNCOMPRESSED_R32G32B32: image.data = (float *)malloc(size*12); size *= 12; break; // 4 byte per channel (12 byte)
|
|
||||||
default: TraceLog(LOG_WARNING, "Image format not suported"); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: fread() returns num read elements instead of bytes,
|
// NOTE: fread() returns num read elements instead of bytes,
|
||||||
// to get bytes we need to read (1 byte size, elements) instead of (x byte size, 1 element)
|
// to get bytes we need to read (1 byte size, elements) instead of (x byte size, 1 element)
|
||||||
|
@ -399,8 +376,6 @@ Texture2D LoadTextureFromImage(Image image)
|
||||||
texture.height = image.height;
|
texture.height = image.height;
|
||||||
texture.mipmaps = image.mipmaps;
|
texture.mipmaps = image.mipmaps;
|
||||||
texture.format = image.format;
|
texture.format = image.format;
|
||||||
|
|
||||||
TraceLog(LOG_DEBUG, "[TEX ID %i] Parameters: %ix%i, %i mips, format %i", texture.id, texture.width, texture.height, texture.mipmaps, texture.format);
|
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
@ -440,24 +415,22 @@ void UnloadRenderTexture(RenderTexture2D target)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get pixel data from image in the form of Color struct array
|
// Get pixel data from image in the form of Color struct array
|
||||||
|
// TODO: Support float pixel data retrieval
|
||||||
Color *GetImageData(Image image)
|
Color *GetImageData(Image image)
|
||||||
{
|
{
|
||||||
Color *pixels = (Color *)malloc(image.width*image.height*sizeof(Color));
|
Color *pixels = (Color *)malloc(image.width*image.height*sizeof(Color));
|
||||||
|
|
||||||
int k = 0;
|
for (int i = 0, k = 0; i < image.width*image.height; i++)
|
||||||
|
|
||||||
for (int i = 0; i < image.width*image.height; i++)
|
|
||||||
{
|
{
|
||||||
switch (image.format)
|
switch (image.format)
|
||||||
{
|
{
|
||||||
case UNCOMPRESSED_GRAYSCALE:
|
case UNCOMPRESSED_GRAYSCALE:
|
||||||
{
|
{
|
||||||
pixels[i].r = ((unsigned char *)image.data)[k];
|
pixels[i].r = ((unsigned char *)image.data)[i];
|
||||||
pixels[i].g = ((unsigned char *)image.data)[k];
|
pixels[i].g = ((unsigned char *)image.data)[i];
|
||||||
pixels[i].b = ((unsigned char *)image.data)[k];
|
pixels[i].b = ((unsigned char *)image.data)[i];
|
||||||
pixels[i].a = 255;
|
pixels[i].a = 255;
|
||||||
|
|
||||||
k++;
|
|
||||||
} break;
|
} break;
|
||||||
case UNCOMPRESSED_GRAY_ALPHA:
|
case UNCOMPRESSED_GRAY_ALPHA:
|
||||||
{
|
{
|
||||||
|
@ -470,36 +443,33 @@ Color *GetImageData(Image image)
|
||||||
} break;
|
} break;
|
||||||
case UNCOMPRESSED_R5G5B5A1:
|
case UNCOMPRESSED_R5G5B5A1:
|
||||||
{
|
{
|
||||||
unsigned short pixel = ((unsigned short *)image.data)[k];
|
unsigned short pixel = ((unsigned short *)image.data)[i];
|
||||||
|
|
||||||
pixels[i].r = (unsigned char)((float)((pixel & 0b1111100000000000) >> 11)*(255/31));
|
pixels[i].r = (unsigned char)((float)((pixel & 0b1111100000000000) >> 11)*(255/31));
|
||||||
pixels[i].g = (unsigned char)((float)((pixel & 0b0000011111000000) >> 6)*(255/31));
|
pixels[i].g = (unsigned char)((float)((pixel & 0b0000011111000000) >> 6)*(255/31));
|
||||||
pixels[i].b = (unsigned char)((float)((pixel & 0b0000000000111110) >> 1)*(255/31));
|
pixels[i].b = (unsigned char)((float)((pixel & 0b0000000000111110) >> 1)*(255/31));
|
||||||
pixels[i].a = (unsigned char)((pixel & 0b0000000000000001)*255);
|
pixels[i].a = (unsigned char)((pixel & 0b0000000000000001)*255);
|
||||||
|
|
||||||
k++;
|
|
||||||
} break;
|
} break;
|
||||||
case UNCOMPRESSED_R5G6B5:
|
case UNCOMPRESSED_R5G6B5:
|
||||||
{
|
{
|
||||||
unsigned short pixel = ((unsigned short *)image.data)[k];
|
unsigned short pixel = ((unsigned short *)image.data)[i];
|
||||||
|
|
||||||
pixels[i].r = (unsigned char)((float)((pixel & 0b1111100000000000) >> 11)*(255/31));
|
pixels[i].r = (unsigned char)((float)((pixel & 0b1111100000000000) >> 11)*(255/31));
|
||||||
pixels[i].g = (unsigned char)((float)((pixel & 0b0000011111100000) >> 5)*(255/63));
|
pixels[i].g = (unsigned char)((float)((pixel & 0b0000011111100000) >> 5)*(255/63));
|
||||||
pixels[i].b = (unsigned char)((float)(pixel & 0b0000000000011111)*(255/31));
|
pixels[i].b = (unsigned char)((float)(pixel & 0b0000000000011111)*(255/31));
|
||||||
pixels[i].a = 255;
|
pixels[i].a = 255;
|
||||||
|
|
||||||
k++;
|
|
||||||
} break;
|
} break;
|
||||||
case UNCOMPRESSED_R4G4B4A4:
|
case UNCOMPRESSED_R4G4B4A4:
|
||||||
{
|
{
|
||||||
unsigned short pixel = ((unsigned short *)image.data)[k];
|
unsigned short pixel = ((unsigned short *)image.data)[i];
|
||||||
|
|
||||||
pixels[i].r = (unsigned char)((float)((pixel & 0b1111000000000000) >> 12)*(255/15));
|
pixels[i].r = (unsigned char)((float)((pixel & 0b1111000000000000) >> 12)*(255/15));
|
||||||
pixels[i].g = (unsigned char)((float)((pixel & 0b0000111100000000) >> 8)*(255/15));
|
pixels[i].g = (unsigned char)((float)((pixel & 0b0000111100000000) >> 8)*(255/15));
|
||||||
pixels[i].b = (unsigned char)((float)((pixel & 0b0000000011110000) >> 4)*(255/15));
|
pixels[i].b = (unsigned char)((float)((pixel & 0b0000000011110000) >> 4)*(255/15));
|
||||||
pixels[i].a = (unsigned char)((float)(pixel & 0b0000000000001111)*(255/15));
|
pixels[i].a = (unsigned char)((float)(pixel & 0b0000000000001111)*(255/15));
|
||||||
|
|
||||||
k++;
|
|
||||||
} break;
|
} break;
|
||||||
case UNCOMPRESSED_R8G8B8A8:
|
case UNCOMPRESSED_R8G8B8A8:
|
||||||
{
|
{
|
||||||
|
@ -526,6 +496,44 @@ Color *GetImageData(Image image)
|
||||||
return pixels;
|
return pixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get pixel data size in bytes (image or texture)
|
||||||
|
// NOTE: Size depends on pixel format
|
||||||
|
int GetPixelDataSize(int width, int height, int format)
|
||||||
|
{
|
||||||
|
int dataSize = 0; // Size in bytes
|
||||||
|
int bpp = 0; // Bits per pixel
|
||||||
|
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case UNCOMPRESSED_GRAYSCALE: bpp = 8; break;
|
||||||
|
case UNCOMPRESSED_GRAY_ALPHA:
|
||||||
|
case UNCOMPRESSED_R5G6B5:
|
||||||
|
case UNCOMPRESSED_R5G5B5A1:
|
||||||
|
case UNCOMPRESSED_R4G4B4A4: bpp = 16; break;
|
||||||
|
case UNCOMPRESSED_R8G8B8A8: bpp = 32; break;
|
||||||
|
case UNCOMPRESSED_R8G8B8: bpp = 24; break;
|
||||||
|
case UNCOMPRESSED_R32: bpp = 32; break;
|
||||||
|
case UNCOMPRESSED_R32G32B32: bpp = 32*3; break;
|
||||||
|
case UNCOMPRESSED_R32G32B32A32: bpp = 32*4; break;
|
||||||
|
case COMPRESSED_DXT1_RGB:
|
||||||
|
case COMPRESSED_DXT1_RGBA:
|
||||||
|
case COMPRESSED_ETC1_RGB:
|
||||||
|
case COMPRESSED_ETC2_RGB:
|
||||||
|
case COMPRESSED_PVRT_RGB:
|
||||||
|
case COMPRESSED_PVRT_RGBA: bpp = 4; break;
|
||||||
|
case COMPRESSED_DXT3_RGBA:
|
||||||
|
case COMPRESSED_DXT5_RGBA:
|
||||||
|
case COMPRESSED_ETC2_EAC_RGBA:
|
||||||
|
case COMPRESSED_ASTC_4x4_RGBA: bpp = 8; break;
|
||||||
|
case COMPRESSED_ASTC_8x8_RGBA: bpp = 2; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dataSize = width*height*bpp/8; // Total data size in bytes
|
||||||
|
|
||||||
|
return dataSize;
|
||||||
|
}
|
||||||
|
|
||||||
// Get pixel data from GPU texture and return an Image
|
// Get pixel data from GPU texture and return an Image
|
||||||
// NOTE: Compressed texture formats not supported
|
// NOTE: Compressed texture formats not supported
|
||||||
Image GetTextureData(Texture2D texture)
|
Image GetTextureData(Texture2D texture)
|
||||||
|
@ -565,10 +573,11 @@ void UpdateTexture(Texture2D texture, const void *pixels)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save image to a PNG file
|
// Save image to a PNG file
|
||||||
void SaveImageAs(const char* fileName, Image image)
|
void SaveImageAs(const char *fileName, Image image)
|
||||||
{
|
{
|
||||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI)
|
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI)
|
||||||
unsigned char* imgData = (unsigned char*)GetImageData(image); // this works since Color is just a container for the RGBA values
|
// NOTE: Getting Color array as RGBA unsigned char values
|
||||||
|
unsigned char *imgData = (unsigned char *)GetImageData(image);
|
||||||
SavePNG(fileName, imgData, image.width, image.height, 4);
|
SavePNG(fileName, imgData, image.width, image.height, 4);
|
||||||
free(imgData);
|
free(imgData);
|
||||||
|
|
||||||
|
@ -576,6 +585,88 @@ void SaveImageAs(const char* fileName, Image image)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy an image to a new image
|
||||||
|
Image ImageCopy(Image image)
|
||||||
|
{
|
||||||
|
Image newImage = { 0 };
|
||||||
|
|
||||||
|
int width = image.width;
|
||||||
|
int height = image.height;
|
||||||
|
int size = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < image.mipmaps; i++)
|
||||||
|
{
|
||||||
|
size += GetPixelDataSize(width, height, image.format);
|
||||||
|
|
||||||
|
width /= 2;
|
||||||
|
height /= 2;
|
||||||
|
|
||||||
|
// Security check for NPOT textures
|
||||||
|
if (width < 1) width = 1;
|
||||||
|
if (height < 1) height = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
newImage.data = malloc(size);
|
||||||
|
|
||||||
|
if (newImage.data != NULL)
|
||||||
|
{
|
||||||
|
// NOTE: Size must be provided in bytes
|
||||||
|
memcpy(newImage.data, image.data, size);
|
||||||
|
|
||||||
|
newImage.width = image.width;
|
||||||
|
newImage.height = image.height;
|
||||||
|
newImage.mipmaps = image.mipmaps;
|
||||||
|
newImage.format = image.format;
|
||||||
|
}
|
||||||
|
|
||||||
|
return newImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert image to POT (power-of-two)
|
||||||
|
// NOTE: It could be useful on OpenGL ES 2.0 (RPI, HTML5)
|
||||||
|
void ImageToPOT(Image *image, Color fillColor)
|
||||||
|
{
|
||||||
|
Color *pixels = GetImageData(*image); // Get pixels data
|
||||||
|
|
||||||
|
// Calculate next power-of-two values
|
||||||
|
// NOTE: Just add the required amount of pixels at the right and bottom sides of image...
|
||||||
|
int potWidth = (int)powf(2, ceilf(logf((float)image->width)/logf(2)));
|
||||||
|
int potHeight = (int)powf(2, ceilf(logf((float)image->height)/logf(2)));
|
||||||
|
|
||||||
|
// Check if POT texture generation is required (if texture is not already POT)
|
||||||
|
if ((potWidth != image->width) || (potHeight != image->height))
|
||||||
|
{
|
||||||
|
Color *pixelsPOT = NULL;
|
||||||
|
|
||||||
|
// Generate POT array from NPOT data
|
||||||
|
pixelsPOT = (Color *)malloc(potWidth*potHeight*sizeof(Color));
|
||||||
|
|
||||||
|
for (int j = 0; j < potHeight; j++)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < potWidth; i++)
|
||||||
|
{
|
||||||
|
if ((j < image->height) && (i < image->width)) pixelsPOT[j*potWidth + i] = pixels[j*image->width + i];
|
||||||
|
else pixelsPOT[j*potWidth + i] = fillColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TraceLog(LOG_WARNING, "Image converted to POT: (%ix%i) -> (%ix%i)", image->width, image->height, potWidth, potHeight);
|
||||||
|
|
||||||
|
free(pixels); // Free pixels data
|
||||||
|
free(image->data); // Free old image data
|
||||||
|
|
||||||
|
int format = image->format; // Store image data format to reconvert later
|
||||||
|
|
||||||
|
// TODO: Image width and height changes... do we want to store new values or keep the old ones?
|
||||||
|
// NOTE: Issues when using image.width and image.height for sprite animations...
|
||||||
|
*image = LoadImageEx(pixelsPOT, potWidth, potHeight);
|
||||||
|
|
||||||
|
free(pixelsPOT); // Free POT pixels data
|
||||||
|
|
||||||
|
ImageFormat(image, format); // Reconvert image to previous format
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Convert image data to desired format
|
// Convert image data to desired format
|
||||||
void ImageFormat(Image *image, int newFormat)
|
void ImageFormat(Image *image, int newFormat)
|
||||||
{
|
{
|
||||||
|
@ -585,7 +676,7 @@ void ImageFormat(Image *image, int newFormat)
|
||||||
{
|
{
|
||||||
Color *pixels = GetImageData(*image);
|
Color *pixels = GetImageData(*image);
|
||||||
|
|
||||||
free(image->data);
|
free(image->data); // WARNING! We loose mipmaps data --> Regenerated at the end...
|
||||||
|
|
||||||
image->format = newFormat;
|
image->format = newFormat;
|
||||||
|
|
||||||
|
@ -607,11 +698,10 @@ void ImageFormat(Image *image, int newFormat)
|
||||||
{
|
{
|
||||||
image->data = (unsigned char *)malloc(image->width*image->height*2*sizeof(unsigned char));
|
image->data = (unsigned char *)malloc(image->width*image->height*2*sizeof(unsigned char));
|
||||||
|
|
||||||
for (int i = 0; i < image->width*image->height*2; i += 2)
|
for (int i = 0; i < image->width*image->height*2; i += 2, k++)
|
||||||
{
|
{
|
||||||
((unsigned char *)image->data)[i] = (unsigned char)((float)pixels[k].r*0.299f + (float)pixels[k].g*0.587f + (float)pixels[k].b*0.114f);
|
((unsigned char *)image->data)[i] = (unsigned char)((float)pixels[k].r*0.299f + (float)pixels[k].g*0.587f + (float)pixels[k].b*0.114f);
|
||||||
((unsigned char *)image->data)[i + 1] = pixels[k].a;
|
((unsigned char *)image->data)[i + 1] = pixels[k].a;
|
||||||
k++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
@ -637,12 +727,11 @@ void ImageFormat(Image *image, int newFormat)
|
||||||
{
|
{
|
||||||
image->data = (unsigned char *)malloc(image->width*image->height*3*sizeof(unsigned char));
|
image->data = (unsigned char *)malloc(image->width*image->height*3*sizeof(unsigned char));
|
||||||
|
|
||||||
for (int i = 0; i < image->width*image->height*3; i += 3)
|
for (int i = 0; i < image->width*image->height*3; i += 3, k++)
|
||||||
{
|
{
|
||||||
((unsigned char *)image->data)[i] = pixels[k].r;
|
((unsigned char *)image->data)[i] = pixels[k].r;
|
||||||
((unsigned char *)image->data)[i + 1] = pixels[k].g;
|
((unsigned char *)image->data)[i + 1] = pixels[k].g;
|
||||||
((unsigned char *)image->data)[i + 2] = pixels[k].b;
|
((unsigned char *)image->data)[i + 2] = pixels[k].b;
|
||||||
k++;
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case UNCOMPRESSED_R5G5B5A1:
|
case UNCOMPRESSED_R5G5B5A1:
|
||||||
|
@ -691,19 +780,58 @@ void ImageFormat(Image *image, int newFormat)
|
||||||
{
|
{
|
||||||
image->data = (unsigned char *)malloc(image->width*image->height*4*sizeof(unsigned char));
|
image->data = (unsigned char *)malloc(image->width*image->height*4*sizeof(unsigned char));
|
||||||
|
|
||||||
for (int i = 0; i < image->width*image->height*4; i += 4)
|
for (int i = 0; i < image->width*image->height*3; i += 3, k++)
|
||||||
{
|
{
|
||||||
((unsigned char *)image->data)[i] = pixels[k].r;
|
((unsigned char *)image->data)[i] = pixels[k].r;
|
||||||
((unsigned char *)image->data)[i + 1] = pixels[k].g;
|
((unsigned char *)image->data)[i + 1] = pixels[k].g;
|
||||||
((unsigned char *)image->data)[i + 2] = pixels[k].b;
|
((unsigned char *)image->data)[i + 2] = pixels[k].b;
|
||||||
((unsigned char *)image->data)[i + 3] = pixels[k].a;
|
((unsigned char *)image->data)[i + 3] = pixels[k].a;
|
||||||
k++;
|
}
|
||||||
|
} break;
|
||||||
|
case UNCOMPRESSED_R32:
|
||||||
|
{
|
||||||
|
image->data = (float *)malloc(image->width*image->height*sizeof(float));
|
||||||
|
|
||||||
|
for (int i = 0; i < image->width*image->height; i++)
|
||||||
|
{
|
||||||
|
((float *)image->data)[i] = (float)((float)pixels[i].r*0.299f/255.0f + (float)pixels[i].g*0.587f/255.0f + (float)pixels[i].b*0.114f/255.0f);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case UNCOMPRESSED_R32G32B32:
|
||||||
|
{
|
||||||
|
image->data = (float *)malloc(image->width*image->height*3*sizeof(float));
|
||||||
|
|
||||||
|
for (int i = 0; i < image->width*image->height*3; i += 3, k++)
|
||||||
|
{
|
||||||
|
((float *)image->data)[i] = (float)pixels[k].r/255.0f;
|
||||||
|
((float *)image->data)[i + 1] = (float)pixels[k].g/255.0f;
|
||||||
|
((float *)image->data)[i + 2] = (float)pixels[k].b/255.0f;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case UNCOMPRESSED_R32G32B32A32:
|
||||||
|
{
|
||||||
|
image->data = (float *)malloc(image->width*image->height*4*sizeof(float));
|
||||||
|
|
||||||
|
for (int i = 0; i < image->width*image->height*4; i += 4, k++)
|
||||||
|
{
|
||||||
|
((float *)image->data)[i] = (float)pixels[k].r/255.0f;
|
||||||
|
((float *)image->data)[i + 1] = (float)pixels[k].g/255.0f;
|
||||||
|
((float *)image->data)[i + 2] = (float)pixels[k].b/255.0f;
|
||||||
|
((float *)image->data)[i + 3] = (float)pixels[k].a/255.0f;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(pixels);
|
free(pixels);
|
||||||
|
|
||||||
|
// In case original image had mipmaps, generate mipmaps for formated image
|
||||||
|
// NOTE: Original mipmaps are replaced by new ones, if custom mipmaps were used, they are lost
|
||||||
|
if (image->mipmaps > 1)
|
||||||
|
{
|
||||||
|
image->mipmaps = 1;
|
||||||
|
ImageMipmaps(image);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else TraceLog(LOG_WARNING, "Image data format is compressed, can not be converted");
|
else TraceLog(LOG_WARNING, "Image data format is compressed, can not be converted");
|
||||||
}
|
}
|
||||||
|
@ -755,99 +883,92 @@ void ImageAlphaMask(Image *image, Image alphaMask)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert image to POT (power-of-two)
|
// Clear alpha channel to desired color
|
||||||
// NOTE: It could be useful on OpenGL ES 2.0 (RPI, HTML5)
|
// NOTE: Threshold defines the alpha limit, 0.0f to 1.0f
|
||||||
void ImageToPOT(Image *image, Color fillColor)
|
void ImageAlphaClear(Image *image, Color color, float threshold)
|
||||||
{
|
{
|
||||||
Color *pixels = GetImageData(*image); // Get pixels data
|
Color *pixels = GetImageData(*image);
|
||||||
|
|
||||||
|
for (int i = 0; i < image->width*image->height; i++) if (pixels[i].a <= (unsigned char)(threshold*255.0f)) pixels[i] = color;
|
||||||
|
|
||||||
// Calculate next power-of-two values
|
UnloadImage(*image);
|
||||||
// NOTE: Just add the required amount of pixels at the right and bottom sides of image...
|
|
||||||
int potWidth = (int)powf(2, ceilf(logf((float)image->width)/logf(2)));
|
int prevFormat = image->format;
|
||||||
int potHeight = (int)powf(2, ceilf(logf((float)image->height)/logf(2)));
|
*image = LoadImageEx(pixels, image->width, image->height);
|
||||||
|
|
||||||
// Check if POT texture generation is required (if texture is not already POT)
|
ImageFormat(image, prevFormat);
|
||||||
if ((potWidth != image->width) || (potHeight != image->height))
|
|
||||||
{
|
|
||||||
Color *pixelsPOT = NULL;
|
|
||||||
|
|
||||||
// Generate POT array from NPOT data
|
|
||||||
pixelsPOT = (Color *)malloc(potWidth*potHeight*sizeof(Color));
|
|
||||||
|
|
||||||
for (int j = 0; j < potHeight; j++)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < potWidth; i++)
|
|
||||||
{
|
|
||||||
if ((j < image->height) && (i < image->width)) pixelsPOT[j*potWidth + i] = pixels[j*image->width + i];
|
|
||||||
else pixelsPOT[j*potWidth + i] = fillColor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TraceLog(LOG_WARNING, "Image converted to POT: (%ix%i) -> (%ix%i)", image->width, image->height, potWidth, potHeight);
|
|
||||||
|
|
||||||
free(pixels); // Free pixels data
|
|
||||||
free(image->data); // Free old image data
|
|
||||||
|
|
||||||
int format = image->format; // Store image data format to reconvert later
|
|
||||||
|
|
||||||
// TODO: Image width and height changes... do we want to store new values or keep the old ones?
|
|
||||||
// NOTE: Issues when using image.width and image.height for sprite animations...
|
|
||||||
*image = LoadImageEx(pixelsPOT, potWidth, potHeight);
|
|
||||||
|
|
||||||
free(pixelsPOT); // Free POT pixels data
|
|
||||||
|
|
||||||
ImageFormat(image, format); // Reconvert image to previous format
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Crop image depending on alpha value
|
||||||
|
void ImageAlphaCrop(Image *image, float threshold)
|
||||||
|
{
|
||||||
|
Rectangle crop = { 0 };
|
||||||
|
|
||||||
|
Color *pixels = GetImageData(*image);
|
||||||
|
|
||||||
|
int minx = 0;
|
||||||
|
int miny = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < image->width*image->height; i++)
|
||||||
|
{
|
||||||
|
if (pixels[i].a > (unsigned char)(threshold*255.0f))
|
||||||
|
{
|
||||||
|
minx = i%image->width;
|
||||||
|
miny = -(-((i/image->width) + 1) + 1);
|
||||||
|
|
||||||
|
if (crop.y == 0) crop.y = miny;
|
||||||
|
|
||||||
|
if (crop.x == 0) crop.x = minx;
|
||||||
|
else if (minx < crop.x) crop.x = minx;
|
||||||
|
|
||||||
|
if (crop.width == 0) crop.width = minx;
|
||||||
|
else if (crop.width < minx) crop.width = minx;
|
||||||
|
|
||||||
|
if (crop.height == 0) crop.height = miny;
|
||||||
|
else if (crop.height < miny) crop.height = miny;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
crop.width -= (crop.x - 1);
|
||||||
|
crop.height -= (crop.y - 1);
|
||||||
|
|
||||||
|
TraceLog(LOG_INFO, "Crop rectangle: (%i, %i, %i, %i)", crop.x, crop.y, crop.width, crop.height);
|
||||||
|
|
||||||
|
free(pixels);
|
||||||
|
|
||||||
|
// NOTE: Added this weird check to avoid additional 1px crop to
|
||||||
|
// image data that has already been cropped...
|
||||||
|
if ((crop.x != 1) &&
|
||||||
|
(crop.y != 1) &&
|
||||||
|
(crop.width != image->width - 1) &&
|
||||||
|
(crop.height != image->height - 1)) ImageCrop(image, crop);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Premultiply alpha channel
|
||||||
|
void ImageAlphaPremultiply(Image *image)
|
||||||
|
{
|
||||||
|
float alpha = 0.0f;
|
||||||
|
Color *pixels = GetImageData(*image);
|
||||||
|
|
||||||
|
for (int i = 0; i < image->width*image->height; i++)
|
||||||
|
{
|
||||||
|
alpha = (float)pixels[i].a/255.0f;
|
||||||
|
pixels[i].r = (unsigned char)((float)pixels[i].r*alpha);
|
||||||
|
pixels[i].g = (unsigned char)((float)pixels[i].g*alpha);
|
||||||
|
pixels[i].b = (unsigned char)((float)pixels[i].b*alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
UnloadImage(*image);
|
||||||
|
|
||||||
|
int prevFormat = image->format;
|
||||||
|
*image = LoadImageEx(pixels, image->width, image->height);
|
||||||
|
|
||||||
|
ImageFormat(image, prevFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(SUPPORT_IMAGE_MANIPULATION)
|
#if defined(SUPPORT_IMAGE_MANIPULATION)
|
||||||
// Copy an image to a new image
|
|
||||||
Image ImageCopy(Image image)
|
|
||||||
{
|
|
||||||
Image newImage = { 0 };
|
|
||||||
|
|
||||||
int byteSize = image.width*image.height;
|
|
||||||
|
|
||||||
switch (image.format)
|
|
||||||
{
|
|
||||||
case UNCOMPRESSED_GRAYSCALE: break; // 8 bpp (1 byte)
|
|
||||||
case UNCOMPRESSED_GRAY_ALPHA: // 16 bpp
|
|
||||||
case UNCOMPRESSED_R5G6B5: // 16 bpp
|
|
||||||
case UNCOMPRESSED_R5G5B5A1: // 16 bpp
|
|
||||||
case UNCOMPRESSED_R4G4B4A4: byteSize *= 2; break; // 16 bpp (2 bytes)
|
|
||||||
case UNCOMPRESSED_R8G8B8: byteSize *= 3; break; // 24 bpp (3 bytes)
|
|
||||||
case UNCOMPRESSED_R8G8B8A8: byteSize *= 4; break; // 32 bpp (4 bytes)
|
|
||||||
case UNCOMPRESSED_R32G32B32: byteSize *= 12; break; // 4 byte per channel (12 bytes)
|
|
||||||
case COMPRESSED_DXT3_RGBA:
|
|
||||||
case COMPRESSED_DXT5_RGBA:
|
|
||||||
case COMPRESSED_ETC2_EAC_RGBA:
|
|
||||||
case COMPRESSED_ASTC_4x4_RGBA: break; // 8 bpp (1 byte)
|
|
||||||
case COMPRESSED_DXT1_RGB:
|
|
||||||
case COMPRESSED_DXT1_RGBA:
|
|
||||||
case COMPRESSED_ETC1_RGB:
|
|
||||||
case COMPRESSED_ETC2_RGB:
|
|
||||||
case COMPRESSED_PVRT_RGB:
|
|
||||||
case COMPRESSED_PVRT_RGBA: byteSize /= 2; break; // 4 bpp
|
|
||||||
case COMPRESSED_ASTC_8x8_RGBA: byteSize /= 4; break;// 2 bpp
|
|
||||||
default: TraceLog(LOG_WARNING, "Image format not recognized"); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
newImage.data = malloc(byteSize);
|
|
||||||
|
|
||||||
if (newImage.data != NULL)
|
|
||||||
{
|
|
||||||
// NOTE: Size must be provided in bytes
|
|
||||||
memcpy(newImage.data, image.data, byteSize);
|
|
||||||
|
|
||||||
newImage.width = image.width;
|
|
||||||
newImage.height = image.height;
|
|
||||||
newImage.mipmaps = image.mipmaps;
|
|
||||||
newImage.format = image.format;
|
|
||||||
}
|
|
||||||
|
|
||||||
return newImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Crop an image to area defined by a rectangle
|
// Crop an image to area defined by a rectangle
|
||||||
// NOTE: Security checks are performed in case rectangle goes out of bounds
|
// NOTE: Security checks are performed in case rectangle goes out of bounds
|
||||||
void ImageCrop(Image *image, Rectangle crop)
|
void ImageCrop(Image *image, Rectangle crop)
|
||||||
|
@ -955,6 +1076,190 @@ void ImageResizeNN(Image *image,int newWidth,int newHeight)
|
||||||
free(pixels);
|
free(pixels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate all mipmap levels for a provided image
|
||||||
|
// NOTE 1: Supports POT and NPOT images
|
||||||
|
// NOTE 2: image.data is scaled to include mipmap levels
|
||||||
|
// NOTE 3: Mipmaps format is the same as base image
|
||||||
|
void ImageMipmaps(Image *image)
|
||||||
|
{
|
||||||
|
int mipCount = 1; // Required mipmap levels count (including base level)
|
||||||
|
int mipWidth = image->width; // Base image width
|
||||||
|
int mipHeight = image->height; // Base image height
|
||||||
|
int mipSize = GetPixelDataSize(mipWidth, mipHeight, image->format); // Image data size (in bytes)
|
||||||
|
|
||||||
|
// Count mipmap levels required
|
||||||
|
while ((mipWidth != 1) || (mipHeight != 1))
|
||||||
|
{
|
||||||
|
if (mipWidth != 1) mipWidth /= 2;
|
||||||
|
if (mipHeight != 1) mipHeight /= 2;
|
||||||
|
|
||||||
|
// Security check for NPOT textures
|
||||||
|
if (mipWidth < 1) mipWidth = 1;
|
||||||
|
if (mipHeight < 1) mipHeight = 1;
|
||||||
|
|
||||||
|
TraceLog(LOG_DEBUG, "Next mipmap level: %i x %i - current size %i", mipWidth, mipHeight, mipSize);
|
||||||
|
|
||||||
|
mipCount++;
|
||||||
|
mipSize += GetPixelDataSize(mipWidth, mipHeight, image->format); // Add mipmap size (in bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
TraceLog(LOG_DEBUG, "Mipmaps available: %i - Mipmaps required: %i", image->mipmaps, mipCount);
|
||||||
|
TraceLog(LOG_DEBUG, "Mipmaps total size required: %i", mipSize);
|
||||||
|
TraceLog(LOG_DEBUG, "Image data memory start address: 0x%x", image->data);
|
||||||
|
|
||||||
|
if (image->mipmaps < mipCount)
|
||||||
|
{
|
||||||
|
void *temp = realloc(image->data, mipSize);
|
||||||
|
|
||||||
|
if (temp != NULL)
|
||||||
|
{
|
||||||
|
image->data = temp; // Assign new pointer (new size) to store mipmaps data
|
||||||
|
TraceLog(LOG_DEBUG, "Image data memory point reallocated: 0x%x", temp);
|
||||||
|
}
|
||||||
|
else TraceLog(LOG_WARNING, "Mipmaps required memory could not be allocated");
|
||||||
|
|
||||||
|
// Pointer to allocated memory point where store next mipmap level data
|
||||||
|
unsigned char *nextmip = (unsigned char *)image->data + GetPixelDataSize(image->width, image->height, image->format);
|
||||||
|
|
||||||
|
mipWidth = image->width/2;
|
||||||
|
mipHeight = image->height/2;
|
||||||
|
mipSize = GetPixelDataSize(mipWidth, mipHeight, image->format);
|
||||||
|
Image imCopy = ImageCopy(*image);
|
||||||
|
|
||||||
|
for (int i = 1; i < mipCount; i++)
|
||||||
|
{
|
||||||
|
TraceLog(LOG_DEBUG, "Gen mipmap level: %i (%i x %i) - size: %i - offset: 0x%x", i, mipWidth, mipHeight, mipSize, nextmip);
|
||||||
|
|
||||||
|
ImageResize(&imCopy, mipWidth, mipHeight); // Uses internally Mitchell cubic downscale filter
|
||||||
|
|
||||||
|
memcpy(nextmip, imCopy.data, mipSize);
|
||||||
|
nextmip += mipSize;
|
||||||
|
image->mipmaps++;
|
||||||
|
|
||||||
|
mipWidth /= 2;
|
||||||
|
mipHeight /= 2;
|
||||||
|
|
||||||
|
// Security check for NPOT textures
|
||||||
|
if (mipWidth < 1) mipWidth = 1;
|
||||||
|
if (mipHeight < 1) mipHeight = 1;
|
||||||
|
|
||||||
|
mipSize = GetPixelDataSize(mipWidth, mipHeight, image->format);
|
||||||
|
}
|
||||||
|
|
||||||
|
UnloadImage(imCopy);
|
||||||
|
}
|
||||||
|
else TraceLog(LOG_WARNING, "Image mipmaps already available");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dither image data to 16bpp or lower (Floyd-Steinberg dithering)
|
||||||
|
// NOTE: In case selected bpp do not represent an known 16bit format,
|
||||||
|
// dithered data is stored in the LSB part of the unsigned short
|
||||||
|
void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp)
|
||||||
|
{
|
||||||
|
if (image->format >= COMPRESSED_DXT1_RGB)
|
||||||
|
{
|
||||||
|
TraceLog(LOG_WARNING, "Compressed data formats can not be dithered");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rBpp+gBpp+bBpp+aBpp) > 16)
|
||||||
|
{
|
||||||
|
TraceLog(LOG_WARNING, "Unsupported dithering bpps (%ibpp), only 16bpp or lower modes supported", (rBpp+gBpp+bBpp+aBpp));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Color *pixels = GetImageData(*image);
|
||||||
|
|
||||||
|
free(image->data); // free old image data
|
||||||
|
|
||||||
|
if ((image->format != UNCOMPRESSED_R8G8B8) && (image->format != UNCOMPRESSED_R8G8B8A8))
|
||||||
|
{
|
||||||
|
TraceLog(LOG_WARNING, "Image format is already 16bpp or lower, dithering could have no effect");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define new image format, check if desired bpp match internal known format
|
||||||
|
if ((rBpp == 5) && (gBpp == 6) && (bBpp == 5) && (aBpp == 0)) image->format = UNCOMPRESSED_R5G6B5;
|
||||||
|
else if ((rBpp == 5) && (gBpp == 5) && (bBpp == 5) && (aBpp == 1)) image->format = UNCOMPRESSED_R5G5B5A1;
|
||||||
|
else if ((rBpp == 4) && (gBpp == 4) && (bBpp == 4) && (aBpp == 4)) image->format = UNCOMPRESSED_R4G4B4A4;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
image->format = 0;
|
||||||
|
TraceLog(LOG_WARNING, "Unsupported dithered OpenGL internal format: %ibpp (R%iG%iB%iA%i)", (rBpp+gBpp+bBpp+aBpp), rBpp, gBpp, bBpp, aBpp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: We will store the dithered data as unsigned short (16bpp)
|
||||||
|
image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short));
|
||||||
|
|
||||||
|
Color oldPixel = WHITE;
|
||||||
|
Color newPixel = WHITE;
|
||||||
|
|
||||||
|
int rError, gError, bError;
|
||||||
|
unsigned short rPixel, gPixel, bPixel, aPixel; // Used for 16bit pixel composition
|
||||||
|
|
||||||
|
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||||
|
|
||||||
|
for (int y = 0; y < image->height; y++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < image->width; x++)
|
||||||
|
{
|
||||||
|
oldPixel = pixels[y*image->width + x];
|
||||||
|
|
||||||
|
// NOTE: New pixel obtained by bits truncate, it would be better to round values (check ImageFormat())
|
||||||
|
newPixel.r = oldPixel.r >> (8 - rBpp); // R bits
|
||||||
|
newPixel.g = oldPixel.g >> (8 - gBpp); // G bits
|
||||||
|
newPixel.b = oldPixel.b >> (8 - bBpp); // B bits
|
||||||
|
newPixel.a = oldPixel.a >> (8 - aBpp); // A bits (not used on dithering)
|
||||||
|
|
||||||
|
// NOTE: Error must be computed between new and old pixel but using same number of bits!
|
||||||
|
// We want to know how much color precision we have lost...
|
||||||
|
rError = (int)oldPixel.r - (int)(newPixel.r << (8 - rBpp));
|
||||||
|
gError = (int)oldPixel.g - (int)(newPixel.g << (8 - gBpp));
|
||||||
|
bError = (int)oldPixel.b - (int)(newPixel.b << (8 - bBpp));
|
||||||
|
|
||||||
|
pixels[y*image->width + x] = newPixel;
|
||||||
|
|
||||||
|
// NOTE: Some cases are out of the array and should be ignored
|
||||||
|
if (x < (image->width - 1))
|
||||||
|
{
|
||||||
|
pixels[y*image->width + x+1].r = MIN((int)pixels[y*image->width + x+1].r + (int)((float)rError*7.0f/16), 0xff);
|
||||||
|
pixels[y*image->width + x+1].g = MIN((int)pixels[y*image->width + x+1].g + (int)((float)gError*7.0f/16), 0xff);
|
||||||
|
pixels[y*image->width + x+1].b = MIN((int)pixels[y*image->width + x+1].b + (int)((float)bError*7.0f/16), 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((x > 0) && (y < (image->height - 1)))
|
||||||
|
{
|
||||||
|
pixels[(y+1)*image->width + x-1].r = MIN((int)pixels[(y+1)*image->width + x-1].r + (int)((float)rError*3.0f/16), 0xff);
|
||||||
|
pixels[(y+1)*image->width + x-1].g = MIN((int)pixels[(y+1)*image->width + x-1].g + (int)((float)gError*3.0f/16), 0xff);
|
||||||
|
pixels[(y+1)*image->width + x-1].b = MIN((int)pixels[(y+1)*image->width + x-1].b + (int)((float)bError*3.0f/16), 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y < (image->height - 1))
|
||||||
|
{
|
||||||
|
pixels[(y+1)*image->width + x].r = MIN((int)pixels[(y+1)*image->width + x].r + (int)((float)rError*5.0f/16), 0xff);
|
||||||
|
pixels[(y+1)*image->width + x].g = MIN((int)pixels[(y+1)*image->width + x].g + (int)((float)gError*5.0f/16), 0xff);
|
||||||
|
pixels[(y+1)*image->width + x].b = MIN((int)pixels[(y+1)*image->width + x].b + (int)((float)bError*5.0f/16), 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((x < (image->width - 1)) && (y < (image->height - 1)))
|
||||||
|
{
|
||||||
|
pixels[(y+1)*image->width + x+1].r = MIN((int)pixels[(y+1)*image->width + x+1].r + (int)((float)rError*1.0f/16), 0xff);
|
||||||
|
pixels[(y+1)*image->width + x+1].g = MIN((int)pixels[(y+1)*image->width + x+1].g + (int)((float)gError*1.0f/16), 0xff);
|
||||||
|
pixels[(y+1)*image->width + x+1].b = MIN((int)pixels[(y+1)*image->width + x+1].b + (int)((float)bError*1.0f/16), 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
rPixel = (unsigned short)newPixel.r;
|
||||||
|
gPixel = (unsigned short)newPixel.g;
|
||||||
|
bPixel = (unsigned short)newPixel.b;
|
||||||
|
aPixel = (unsigned short)newPixel.a;
|
||||||
|
|
||||||
|
((unsigned short *)image->data)[y*image->width + x] = (rPixel << (gBpp + bBpp + aBpp)) | (gPixel << (bBpp + aBpp)) | (bPixel << aBpp) | aPixel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(pixels);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Draw an image (source) within an image (destination)
|
// Draw an image (source) within an image (destination)
|
||||||
// TODO: Feel this function could be simplified...
|
// TODO: Feel this function could be simplified...
|
||||||
void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec)
|
void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec)
|
||||||
|
@ -1069,29 +1374,59 @@ Image ImageTextEx(SpriteFont font, const char *text, float fontSize, int spacing
|
||||||
{
|
{
|
||||||
int length = strlen(text);
|
int length = strlen(text);
|
||||||
int posX = 0;
|
int posX = 0;
|
||||||
|
int index; // Index position in sprite font
|
||||||
|
unsigned char character; // Current character
|
||||||
|
|
||||||
|
// TODO: ISSUE: Measured text size does not seem to be correct... issue on ImageDraw()
|
||||||
Vector2 imSize = MeasureTextEx(font, text, font.baseSize, spacing);
|
Vector2 imSize = MeasureTextEx(font, text, font.baseSize, spacing);
|
||||||
|
|
||||||
TraceLog(LOG_WARNING, "Text Image size: %f, %f", imSize.x, imSize.y);
|
TraceLog(LOG_DEBUG, "Text Image size: %f, %f", imSize.x, imSize.y);
|
||||||
|
|
||||||
// NOTE: glGetTexImage() not available in OpenGL ES
|
// NOTE: glGetTexImage() not available in OpenGL ES
|
||||||
|
// TODO: This is horrible, retrieving font texture from GPU!!!
|
||||||
|
// Define ImageFont struct? or include Image spritefont in SpriteFont struct?
|
||||||
Image imFont = GetTextureData(font.texture);
|
Image imFont = GetTextureData(font.texture);
|
||||||
|
|
||||||
ImageFormat(&imFont, UNCOMPRESSED_R8G8B8A8); // Convert to 32 bit for color tint
|
ImageColorTint(&imFont, tint); // Apply color tint to font
|
||||||
ImageColorTint(&imFont, tint); // Apply color tint to font
|
|
||||||
|
|
||||||
// Create image to store text
|
// Create image to store text
|
||||||
Image imText = GenImageColor((int)imSize.x, (int)imSize.y, BLANK);
|
Image imText = GenImageColor((int)imSize.x, (int)imSize.y, BLANK);
|
||||||
|
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
CharInfo letter = font.chars[(int)text[i] - 32];
|
if ((unsigned char)text[i] == '\n')
|
||||||
|
{
|
||||||
ImageDraw(&imText, imFont, letter.rec, (Rectangle){ posX + letter.offsetX,
|
// TODO: Support line break
|
||||||
letter.offsetY, letter.rec.width, letter.rec.height });
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((unsigned char)text[i] == 0xc2) // UTF-8 encoding identification HACK!
|
||||||
|
{
|
||||||
|
// Support UTF-8 encoded values from [0xc2 0x80] -> [0xc2 0xbf](¿)
|
||||||
|
character = (unsigned char)text[i + 1];
|
||||||
|
index = GetGlyphIndex(font, (int)character);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else if ((unsigned char)text[i] == 0xc3) // UTF-8 encoding identification HACK!
|
||||||
|
{
|
||||||
|
// Support UTF-8 encoded values from [0xc3 0x80](À) -> [0xc3 0xbf](ÿ)
|
||||||
|
character = (unsigned char)text[i + 1];
|
||||||
|
index = GetGlyphIndex(font, (int)character + 64);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else index = GetGlyphIndex(font, (unsigned char)text[i]);
|
||||||
|
|
||||||
if (letter.advanceX == 0) posX += letter.rec.width + spacing;
|
CharInfo letter = font.chars[index];
|
||||||
else posX += letter.advanceX + spacing;
|
|
||||||
|
if ((unsigned char)text[i] != ' ')
|
||||||
|
{
|
||||||
|
ImageDraw(&imText, imFont, letter.rec, (Rectangle){ posX + letter.offsetX,
|
||||||
|
letter.offsetY, letter.rec.width, letter.rec.height });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (letter.advanceX == 0) posX += letter.rec.width + spacing;
|
||||||
|
else posX += letter.advanceX + spacing;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UnloadImage(imFont);
|
UnloadImage(imFont);
|
||||||
|
@ -1100,7 +1435,7 @@ Image ImageTextEx(SpriteFont font, const char *text, float fontSize, int spacing
|
||||||
if (fontSize > imSize.y)
|
if (fontSize > imSize.y)
|
||||||
{
|
{
|
||||||
float scaleFactor = fontSize/imSize.y;
|
float scaleFactor = fontSize/imSize.y;
|
||||||
TraceLog(LOG_INFO, "Scalefactor: %f", scaleFactor);
|
TraceLog(LOG_INFO, "Image text scaled by factor: %f", scaleFactor);
|
||||||
|
|
||||||
// Using nearest-neighbor scaling algorithm for default font
|
// Using nearest-neighbor scaling algorithm for default font
|
||||||
if (font.texture.id == GetDefaultFont().texture.id) ImageResizeNN(&imText, (int)(imSize.x*scaleFactor), (int)(imSize.y*scaleFactor));
|
if (font.texture.id == GetDefaultFont().texture.id) ImageResizeNN(&imText, (int)(imSize.x*scaleFactor), (int)(imSize.y*scaleFactor));
|
||||||
|
@ -1178,115 +1513,6 @@ void ImageFlipHorizontal(Image *image)
|
||||||
image->data = processed.data;
|
image->data = processed.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dither image data to 16bpp or lower (Floyd-Steinberg dithering)
|
|
||||||
// NOTE: In case selected bpp do not represent an known 16bit format,
|
|
||||||
// dithered data is stored in the LSB part of the unsigned short
|
|
||||||
void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp)
|
|
||||||
{
|
|
||||||
if (image->format >= COMPRESSED_DXT1_RGB)
|
|
||||||
{
|
|
||||||
TraceLog(LOG_WARNING, "Compressed data formats can not be dithered");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((rBpp+gBpp+bBpp+aBpp) > 16)
|
|
||||||
{
|
|
||||||
TraceLog(LOG_WARNING, "Unsupported dithering bpps (%ibpp), only 16bpp or lower modes supported", (rBpp+gBpp+bBpp+aBpp));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Color *pixels = GetImageData(*image);
|
|
||||||
|
|
||||||
free(image->data); // free old image data
|
|
||||||
|
|
||||||
if ((image->format != UNCOMPRESSED_R8G8B8) && (image->format != UNCOMPRESSED_R8G8B8A8))
|
|
||||||
{
|
|
||||||
TraceLog(LOG_WARNING, "Image format is already 16bpp or lower, dithering could have no effect");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Define new image format, check if desired bpp match internal known format
|
|
||||||
if ((rBpp == 5) && (gBpp == 6) && (bBpp == 5) && (aBpp == 0)) image->format = UNCOMPRESSED_R5G6B5;
|
|
||||||
else if ((rBpp == 5) && (gBpp == 5) && (bBpp == 5) && (aBpp == 1)) image->format = UNCOMPRESSED_R5G5B5A1;
|
|
||||||
else if ((rBpp == 4) && (gBpp == 4) && (bBpp == 4) && (aBpp == 4)) image->format = UNCOMPRESSED_R4G4B4A4;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
image->format = 0;
|
|
||||||
TraceLog(LOG_WARNING, "Unsupported dithered OpenGL internal format: %ibpp (R%iG%iB%iA%i)", (rBpp+gBpp+bBpp+aBpp), rBpp, gBpp, bBpp, aBpp);
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: We will store the dithered data as unsigned short (16bpp)
|
|
||||||
image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short));
|
|
||||||
|
|
||||||
Color oldPixel = WHITE;
|
|
||||||
Color newPixel = WHITE;
|
|
||||||
|
|
||||||
int rError, gError, bError;
|
|
||||||
unsigned short rPixel, gPixel, bPixel, aPixel; // Used for 16bit pixel composition
|
|
||||||
|
|
||||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
|
||||||
|
|
||||||
for (int y = 0; y < image->height; y++)
|
|
||||||
{
|
|
||||||
for (int x = 0; x < image->width; x++)
|
|
||||||
{
|
|
||||||
oldPixel = pixels[y*image->width + x];
|
|
||||||
|
|
||||||
// NOTE: New pixel obtained by bits truncate, it would be better to round values (check ImageFormat())
|
|
||||||
newPixel.r = oldPixel.r >> (8 - rBpp); // R bits
|
|
||||||
newPixel.g = oldPixel.g >> (8 - gBpp); // G bits
|
|
||||||
newPixel.b = oldPixel.b >> (8 - bBpp); // B bits
|
|
||||||
newPixel.a = oldPixel.a >> (8 - aBpp); // A bits (not used on dithering)
|
|
||||||
|
|
||||||
// NOTE: Error must be computed between new and old pixel but using same number of bits!
|
|
||||||
// We want to know how much color precision we have lost...
|
|
||||||
rError = (int)oldPixel.r - (int)(newPixel.r << (8 - rBpp));
|
|
||||||
gError = (int)oldPixel.g - (int)(newPixel.g << (8 - gBpp));
|
|
||||||
bError = (int)oldPixel.b - (int)(newPixel.b << (8 - bBpp));
|
|
||||||
|
|
||||||
pixels[y*image->width + x] = newPixel;
|
|
||||||
|
|
||||||
// NOTE: Some cases are out of the array and should be ignored
|
|
||||||
if (x < (image->width - 1))
|
|
||||||
{
|
|
||||||
pixels[y*image->width + x+1].r = MIN((int)pixels[y*image->width + x+1].r + (int)((float)rError*7.0f/16), 0xff);
|
|
||||||
pixels[y*image->width + x+1].g = MIN((int)pixels[y*image->width + x+1].g + (int)((float)gError*7.0f/16), 0xff);
|
|
||||||
pixels[y*image->width + x+1].b = MIN((int)pixels[y*image->width + x+1].b + (int)((float)bError*7.0f/16), 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((x > 0) && (y < (image->height - 1)))
|
|
||||||
{
|
|
||||||
pixels[(y+1)*image->width + x-1].r = MIN((int)pixels[(y+1)*image->width + x-1].r + (int)((float)rError*3.0f/16), 0xff);
|
|
||||||
pixels[(y+1)*image->width + x-1].g = MIN((int)pixels[(y+1)*image->width + x-1].g + (int)((float)gError*3.0f/16), 0xff);
|
|
||||||
pixels[(y+1)*image->width + x-1].b = MIN((int)pixels[(y+1)*image->width + x-1].b + (int)((float)bError*3.0f/16), 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (y < (image->height - 1))
|
|
||||||
{
|
|
||||||
pixels[(y+1)*image->width + x].r = MIN((int)pixels[(y+1)*image->width + x].r + (int)((float)rError*5.0f/16), 0xff);
|
|
||||||
pixels[(y+1)*image->width + x].g = MIN((int)pixels[(y+1)*image->width + x].g + (int)((float)gError*5.0f/16), 0xff);
|
|
||||||
pixels[(y+1)*image->width + x].b = MIN((int)pixels[(y+1)*image->width + x].b + (int)((float)bError*5.0f/16), 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((x < (image->width - 1)) && (y < (image->height - 1)))
|
|
||||||
{
|
|
||||||
pixels[(y+1)*image->width + x+1].r = MIN((int)pixels[(y+1)*image->width + x+1].r + (int)((float)rError*1.0f/16), 0xff);
|
|
||||||
pixels[(y+1)*image->width + x+1].g = MIN((int)pixels[(y+1)*image->width + x+1].g + (int)((float)gError*1.0f/16), 0xff);
|
|
||||||
pixels[(y+1)*image->width + x+1].b = MIN((int)pixels[(y+1)*image->width + x+1].b + (int)((float)bError*1.0f/16), 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
rPixel = (unsigned short)newPixel.r;
|
|
||||||
gPixel = (unsigned short)newPixel.g;
|
|
||||||
bPixel = (unsigned short)newPixel.b;
|
|
||||||
aPixel = (unsigned short)newPixel.a;
|
|
||||||
|
|
||||||
((unsigned short *)image->data)[y*image->width + x] = (rPixel << (gBpp + bBpp + aBpp)) | (gPixel << (bBpp + aBpp)) | (bPixel << aBpp) | aPixel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(pixels);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Modify image color: tint
|
// Modify image color: tint
|
||||||
void ImageColorTint(Image *image, Color color)
|
void ImageColorTint(Image *image, Color color)
|
||||||
{
|
{
|
||||||
|
@ -1576,7 +1802,7 @@ Image GenImageWhiteNoise(int width, int height, float factor)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate image: perlin noise
|
// Generate image: perlin noise
|
||||||
Image GenImagePerlinNoise(int width, int height, float scale)
|
Image GenImagePerlinNoise(int width, int height, int offsetX, int offsetY, float scale)
|
||||||
{
|
{
|
||||||
Color *pixels = (Color *)malloc(width*height*sizeof(Color));
|
Color *pixels = (Color *)malloc(width*height*sizeof(Color));
|
||||||
|
|
||||||
|
@ -1584,13 +1810,18 @@ Image GenImagePerlinNoise(int width, int height, float scale)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < width; x++)
|
for (int x = 0; x < width; x++)
|
||||||
{
|
{
|
||||||
float nx = (float)x*scale/(float)width;
|
float nx = (float)(x + offsetX)*scale/(float)width;
|
||||||
float ny = (float)y*scale/(float)height;
|
float ny = (float)(y + offsetY)*scale/(float)height;
|
||||||
|
|
||||||
// we need to translate the data from [-1; 1] to [0; 1]
|
// Typical values to start playing with:
|
||||||
float p = (stb_perlin_fbm_noise3(nx, ny, 1.0f, 2.0f, 0.5f, 6, 0, 0, 0) + 1.0f) / 2.0f;
|
// lacunarity = ~2.0 -- spacing between successive octaves (use exactly 2.0 for wrapping output)
|
||||||
|
// gain = 0.5 -- relative weighting applied to each successive octave
|
||||||
|
// octaves = 6 -- number of "octaves" of noise3() to sum
|
||||||
|
|
||||||
|
// NOTE: We need to translate the data from [-1..1] to [0..1]
|
||||||
|
float p = (stb_perlin_fbm_noise3(nx, ny, 1.0f, 2.0f, 0.5f, 6, 0, 0, 0) + 1.0f)/2.0f;
|
||||||
|
|
||||||
int intensity = (int)(p * 255.0f);
|
int intensity = (int)(p*255.0f);
|
||||||
pixels[y*width + x] = (Color){intensity, intensity, intensity, 255};
|
pixels[y*width + x] = (Color){intensity, intensity, intensity, 255};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1665,7 +1896,7 @@ Image GenImageCellular(int width, int height, int tileSize)
|
||||||
// Generate GPU mipmaps for a texture
|
// Generate GPU mipmaps for a texture
|
||||||
void GenTextureMipmaps(Texture2D *texture)
|
void GenTextureMipmaps(Texture2D *texture)
|
||||||
{
|
{
|
||||||
#if PLATFORM_WEB
|
#if defined(PLATFORM_WEB)
|
||||||
// Calculate next power-of-two values
|
// Calculate next power-of-two values
|
||||||
int potWidth = (int)powf(2, ceilf(logf((float)texture->width)/logf(2)));
|
int potWidth = (int)powf(2, ceilf(logf((float)texture->width)/logf(2)));
|
||||||
int potHeight = (int)powf(2, ceilf(logf((float)texture->height)/logf(2)));
|
int potHeight = (int)powf(2, ceilf(logf((float)texture->height)/logf(2)));
|
||||||
|
|
|
@ -47,7 +47,7 @@ func LoadImageEx(pixels []Color, width, height int32) *Image {
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadImagePro - Load image from raw data with parameters
|
// LoadImagePro - Load image from raw data with parameters
|
||||||
func LoadImagePro(data []byte, width, height int32, format TextureFormat) *Image {
|
func LoadImagePro(data []byte, width, height int32, format PixelFormat) *Image {
|
||||||
cdata := unsafe.Pointer(&data[0])
|
cdata := unsafe.Pointer(&data[0])
|
||||||
cwidth := (C.int)(width)
|
cwidth := (C.int)(width)
|
||||||
cheight := (C.int)(height)
|
cheight := (C.int)(height)
|
||||||
|
@ -58,7 +58,7 @@ func LoadImagePro(data []byte, width, height int32, format TextureFormat) *Image
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadImageRaw - Load image data from RAW file
|
// LoadImageRaw - Load image data from RAW file
|
||||||
func LoadImageRaw(fileName string, width, height int32, format TextureFormat, headerSize int32) *Image {
|
func LoadImageRaw(fileName string, width, height int32, format PixelFormat, headerSize int32) *Image {
|
||||||
cfileName := C.CString(fileName)
|
cfileName := C.CString(fileName)
|
||||||
defer C.free(unsafe.Pointer(cfileName))
|
defer C.free(unsafe.Pointer(cfileName))
|
||||||
cwidth := (C.int)(width)
|
cwidth := (C.int)(width)
|
||||||
|
@ -121,6 +121,15 @@ func GetImageData(image *Image) []byte {
|
||||||
return (*[1 << 30]uint8)(unsafe.Pointer(ret))[:]
|
return (*[1 << 30]uint8)(unsafe.Pointer(ret))[:]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPixelDataSize - Get pixel data size in bytes (image or texture)
|
||||||
|
func GetPixelDataSize(width, height, format int32) int32 {
|
||||||
|
cwidth := (C.int)(width)
|
||||||
|
cheight := (C.int)(height)
|
||||||
|
cformat := (C.int)(format)
|
||||||
|
ret := C.GetPixelDataSize(cwidth, cheight, cformat)
|
||||||
|
return int32(ret)
|
||||||
|
}
|
||||||
|
|
||||||
// GetTextureData - Get pixel data from GPU texture and return an Image
|
// GetTextureData - Get pixel data from GPU texture and return an Image
|
||||||
func GetTextureData(texture Texture2D) *Image {
|
func GetTextureData(texture Texture2D) *Image {
|
||||||
ctexture := texture.cptr()
|
ctexture := texture.cptr()
|
||||||
|
@ -166,6 +175,27 @@ func ImageAlphaMask(image, alphaMask *Image) {
|
||||||
C.ImageAlphaMask(cimage, *calphaMask)
|
C.ImageAlphaMask(cimage, *calphaMask)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ImageAlphaClear - Apply alpha mask to image
|
||||||
|
func ImageAlphaClear(image *Image, color Color, threshold float32) {
|
||||||
|
cimage := image.cptr()
|
||||||
|
ccolor := color.cptr()
|
||||||
|
cthreshold := (C.float)(threshold)
|
||||||
|
C.ImageAlphaClear(cimage, *ccolor, cthreshold)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageAlphaCrop - Crop image depending on alpha value
|
||||||
|
func ImageAlphaCrop(image *Image, threshold float32) {
|
||||||
|
cimage := image.cptr()
|
||||||
|
cthreshold := (C.float)(threshold)
|
||||||
|
C.ImageAlphaCrop(cimage, cthreshold)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageAlphaPremultiply - Premultiply alpha channel
|
||||||
|
func ImageAlphaPremultiply(image *Image) {
|
||||||
|
cimage := image.cptr()
|
||||||
|
C.ImageAlphaPremultiply(cimage)
|
||||||
|
}
|
||||||
|
|
||||||
// ImageDither - Dither image data to 16bpp or lower (Floyd-Steinberg dithering)
|
// ImageDither - Dither image data to 16bpp or lower (Floyd-Steinberg dithering)
|
||||||
func ImageDither(image *Image, rBpp, gBpp, bBpp, aBpp int32) {
|
func ImageDither(image *Image, rBpp, gBpp, bBpp, aBpp int32) {
|
||||||
cimage := image.cptr()
|
cimage := image.cptr()
|
||||||
|
@ -207,6 +237,12 @@ func ImageResizeNN(image *Image, newWidth, newHeight int32) {
|
||||||
C.ImageResizeNN(cimage, cnewWidth, cnewHeight)
|
C.ImageResizeNN(cimage, cnewWidth, cnewHeight)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ImageMipmaps - Generate all mipmap levels for a provided image
|
||||||
|
func ImageMipmaps(image *Image) {
|
||||||
|
cimage := image.cptr()
|
||||||
|
C.ImageMipmaps(cimage)
|
||||||
|
}
|
||||||
|
|
||||||
// ImageText - Create an image from text (default font)
|
// ImageText - Create an image from text (default font)
|
||||||
func ImageText(text string, fontSize int32, color Color) *Image {
|
func ImageText(text string, fontSize int32, color Color) *Image {
|
||||||
ctext := C.CString(text)
|
ctext := C.CString(text)
|
||||||
|
@ -383,12 +419,14 @@ func GenImageWhiteNoise(width, height int, factor float32) *Image {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenImagePerlinNoise - Generate image: perlin noise
|
// GenImagePerlinNoise - Generate image: perlin noise
|
||||||
func GenImagePerlinNoise(width, height int, scale float32) *Image {
|
func GenImagePerlinNoise(width, height, offsetX, offsetY int, scale float32) *Image {
|
||||||
cwidth := (C.int)(width)
|
cwidth := (C.int)(width)
|
||||||
cheight := (C.int)(height)
|
cheight := (C.int)(height)
|
||||||
|
coffsetX := (C.int)(offsetX)
|
||||||
|
coffsetY := (C.int)(offsetY)
|
||||||
cscale := (C.float)(scale)
|
cscale := (C.float)(scale)
|
||||||
|
|
||||||
ret := C.GenImagePerlinNoise(cwidth, cheight, cscale)
|
ret := C.GenImagePerlinNoise(cwidth, cheight, coffsetX, coffsetY, cscale)
|
||||||
v := newImageFromPointer(unsafe.Pointer(&ret))
|
v := newImageFromPointer(unsafe.Pointer(&ret))
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
// +build !js
|
|
||||||
|
|
||||||
/**********************************************************************************************
|
/**********************************************************************************************
|
||||||
*
|
*
|
||||||
* raylib.utils - Some common utility functions
|
* raylib.utils - Some common utility functions
|
||||||
|
@ -18,16 +16,13 @@
|
||||||
* Show TraceLog() output messages
|
* Show TraceLog() output messages
|
||||||
* NOTE: By default LOG_DEBUG traces not shown
|
* NOTE: By default LOG_DEBUG traces not shown
|
||||||
*
|
*
|
||||||
* #define SUPPORT_TRACELOG_DEBUG
|
|
||||||
* Show TraceLog() LOG_DEBUG messages
|
|
||||||
*
|
|
||||||
* DEPENDENCIES:
|
* DEPENDENCIES:
|
||||||
* stb_image_write - BMP/PNG writting functions
|
* stb_image_write - BMP/PNG writting functions
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* LICENSE: zlib/libpng
|
* LICENSE: zlib/libpng
|
||||||
*
|
*
|
||||||
* Copyright (c) 2014-2017 Ramon Santamaria (@raysan5)
|
* Copyright (c) 2014-2018 Ramon Santamaria (@raysan5)
|
||||||
*
|
*
|
||||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
* 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.
|
* will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
@ -47,7 +42,6 @@
|
||||||
**********************************************************************************************/
|
**********************************************************************************************/
|
||||||
|
|
||||||
#define SUPPORT_TRACELOG // Output tracelog messages
|
#define SUPPORT_TRACELOG // Output tracelog messages
|
||||||
//#define SUPPORT_TRACELOG_DEBUG // Avoid LOG_DEBUG messages tracing
|
|
||||||
|
|
||||||
#include "raylib.h" // WARNING: Required for: LogType enum
|
#include "raylib.h" // WARNING: Required for: LogType enum
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
@ -65,15 +59,16 @@
|
||||||
|
|
||||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI)
|
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI)
|
||||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||||
#include "external/stb_image_write.h" // Required for: stbi_write_bmp(), stbi_write_png()
|
#include "external/stb_image_write.h" // Required for: stbi_write_bmp(), stbi_write_png()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define RRES_IMPLEMENTATION
|
|
||||||
#include "rres.h"
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Global Variables Definition
|
// Global Variables Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Log types messages supported flags (bit based)
|
||||||
|
static unsigned char logTypeFlags = LOG_INFO | LOG_WARNING | LOG_ERROR;
|
||||||
|
|
||||||
#if defined(PLATFORM_ANDROID)
|
#if defined(PLATFORM_ANDROID)
|
||||||
AAssetManager *assetManager;
|
AAssetManager *assetManager;
|
||||||
#endif
|
#endif
|
||||||
|
@ -92,16 +87,17 @@ static int android_close(void *cookie);
|
||||||
// Module Functions Definition - Utilities
|
// Module Functions Definition - Utilities
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Enable trace log message types (bit flags based)
|
||||||
|
void SetTraceLog(unsigned char types)
|
||||||
|
{
|
||||||
|
logTypeFlags = types;
|
||||||
|
}
|
||||||
|
|
||||||
// Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG)
|
// Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG)
|
||||||
void TraceLog(int msgType, const char *text, ...)
|
void TraceLog(int msgType, const char *text, ...)
|
||||||
{
|
{
|
||||||
#if defined(SUPPORT_TRACELOG)
|
#if defined(SUPPORT_TRACELOG)
|
||||||
static char buffer[128];
|
static char buffer[128];
|
||||||
int traceDebugMsgs = 0;
|
|
||||||
|
|
||||||
#if defined(SUPPORT_TRACELOG_DEBUG)
|
|
||||||
traceDebugMsgs = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
switch(msgType)
|
switch(msgType)
|
||||||
{
|
{
|
||||||
|
@ -121,14 +117,21 @@ void TraceLog(int msgType, const char *text, ...)
|
||||||
#if defined(PLATFORM_ANDROID)
|
#if defined(PLATFORM_ANDROID)
|
||||||
switch(msgType)
|
switch(msgType)
|
||||||
{
|
{
|
||||||
case LOG_INFO: __android_log_vprint(ANDROID_LOG_INFO, "raylib", buffer, args); break;
|
case LOG_INFO: if (logTypeFlags & LOG_INFO) __android_log_vprint(ANDROID_LOG_INFO, "raylib", buffer, args); break;
|
||||||
case LOG_ERROR: __android_log_vprint(ANDROID_LOG_ERROR, "raylib", buffer, args); break;
|
case LOG_WARNING: if (logTypeFlags & LOG_WARNING) __android_log_vprint(ANDROID_LOG_WARN, "raylib", buffer, args); break;
|
||||||
case LOG_WARNING: __android_log_vprint(ANDROID_LOG_WARN, "raylib", buffer, args); break;
|
case LOG_ERROR: if (logTypeFlags & LOG_ERROR) __android_log_vprint(ANDROID_LOG_ERROR, "raylib", buffer, args); break;
|
||||||
case LOG_DEBUG: if (traceDebugMsgs) __android_log_vprint(ANDROID_LOG_DEBUG, "raylib", buffer, args); break;
|
case LOG_DEBUG: if (logTypeFlags & LOG_DEBUG) __android_log_vprint(ANDROID_LOG_DEBUG, "raylib", buffer, args); break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if ((msgType != LOG_DEBUG) || ((msgType == LOG_DEBUG) && (traceDebugMsgs))) vprintf(buffer, args);
|
switch(msgType)
|
||||||
|
{
|
||||||
|
case LOG_INFO: if (logTypeFlags & LOG_INFO) vprintf(buffer, args); break;
|
||||||
|
case LOG_WARNING: if (logTypeFlags & LOG_WARNING) vprintf(buffer, args); break;
|
||||||
|
case LOG_ERROR: if (logTypeFlags & LOG_ERROR) vprintf(buffer, args); break;
|
||||||
|
case LOG_DEBUG: if (logTypeFlags & LOG_DEBUG) vprintf(buffer, args); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
|
@ -2,23 +2,41 @@
|
||||||
|
|
||||||
package raylib
|
package raylib
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include "raylib.h"
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SetTraceLog - Enable trace log message types (bit flags based)
|
||||||
|
func SetTraceLog(typeFlags int) {
|
||||||
|
logTypeFlags = typeFlags
|
||||||
|
|
||||||
|
ctypeFlags := (C.uchar)(typeFlags)
|
||||||
|
C.SetTraceLog(ctypeFlags)
|
||||||
|
}
|
||||||
|
|
||||||
// TraceLog - Show trace log messages (INFO, WARNING, ERROR, DEBUG)
|
// TraceLog - Show trace log messages (INFO, WARNING, ERROR, DEBUG)
|
||||||
func TraceLog(msgType int, text string, v ...interface{}) {
|
func TraceLog(msgType int, text string, v ...interface{}) {
|
||||||
switch msgType {
|
switch msgType {
|
||||||
case LogInfo:
|
case LogInfo:
|
||||||
fmt.Printf("INFO: "+text+"\n", v...)
|
if logTypeFlags&LogInfo == 0 {
|
||||||
|
fmt.Printf("INFO: "+text+"\n", v...)
|
||||||
|
}
|
||||||
case LogWarning:
|
case LogWarning:
|
||||||
fmt.Printf("WARNING: "+text+"\n", v...)
|
if logTypeFlags&LogWarning == 0 {
|
||||||
|
fmt.Printf("WARNING: "+text+"\n", v...)
|
||||||
|
}
|
||||||
case LogError:
|
case LogError:
|
||||||
fmt.Printf("ERROR: "+text+"\n", v...)
|
if logTypeFlags&LogError == 0 {
|
||||||
os.Exit(1)
|
fmt.Printf("ERROR: "+text+"\n", v...)
|
||||||
|
}
|
||||||
case LogDebug:
|
case LogDebug:
|
||||||
if traceDebugMsgs {
|
if logTypeFlags&LogDebug == 0 {
|
||||||
fmt.Printf("DEBUG: "+text+"\n", v...)
|
fmt.Printf("DEBUG: "+text+"\n", v...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
*
|
*
|
||||||
* LICENSE: zlib/libpng
|
* LICENSE: zlib/libpng
|
||||||
*
|
*
|
||||||
* Copyright (c) 2014-2017 Ramon Santamaria (@raysan5)
|
* Copyright (c) 2014-2018 Ramon Santamaria (@raysan5)
|
||||||
*
|
*
|
||||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
* 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.
|
* will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
@ -32,8 +32,6 @@
|
||||||
#include <android/asset_manager.h> // Required for: AAssetManager
|
#include <android/asset_manager.h> // Required for: AAssetManager
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "rres.h"
|
|
||||||
|
|
||||||
#define SUPPORT_SAVE_PNG
|
#define SUPPORT_SAVE_PNG
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
package raylib
|
package raylib
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
#include "raylib.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
void log_info(const char *msg);
|
void log_info(const char *msg);
|
||||||
|
@ -16,28 +17,40 @@ import "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SetTraceLog - Enable trace log message types (bit flags based)
|
||||||
|
func SetTraceLog(typeFlags int) {
|
||||||
|
logTypeFlags = typeFlags
|
||||||
|
|
||||||
|
ctypeFlags := (C.uchar)(typeFlags)
|
||||||
|
C.SetTraceLog(ctypeFlags)
|
||||||
|
}
|
||||||
|
|
||||||
// TraceLog - Trace log messages showing (INFO, WARNING, ERROR, DEBUG)
|
// TraceLog - Trace log messages showing (INFO, WARNING, ERROR, DEBUG)
|
||||||
func TraceLog(msgType int, text string, v ...interface{}) {
|
func TraceLog(msgType int, text string, v ...interface{}) {
|
||||||
switch msgType {
|
switch msgType {
|
||||||
case LogInfo:
|
case LogInfo:
|
||||||
msg := C.CString(fmt.Sprintf("INFO: "+text, v...))
|
if logTypeFlags&LogInfo == 0 {
|
||||||
defer C.free(unsafe.Pointer(msg))
|
msg := C.CString(fmt.Sprintf("INFO: "+text, v...))
|
||||||
C.log_info(msg)
|
defer C.free(unsafe.Pointer(msg))
|
||||||
case LogError:
|
C.log_info(msg)
|
||||||
msg := C.CString(fmt.Sprintf("ERROR: "+text, v...))
|
}
|
||||||
defer C.free(unsafe.Pointer(msg))
|
|
||||||
C.log_error(msg)
|
|
||||||
os.Exit(1)
|
|
||||||
case LogWarning:
|
case LogWarning:
|
||||||
msg := C.CString(fmt.Sprintf("WARNING: "+text, v...))
|
if logTypeFlags&LogWarning == 0 {
|
||||||
defer C.free(unsafe.Pointer(msg))
|
msg := C.CString(fmt.Sprintf("WARNING: "+text, v...))
|
||||||
C.log_warn(msg)
|
defer C.free(unsafe.Pointer(msg))
|
||||||
|
C.log_warn(msg)
|
||||||
|
}
|
||||||
|
case LogError:
|
||||||
|
if logTypeFlags&LogError == 0 {
|
||||||
|
msg := C.CString(fmt.Sprintf("ERROR: "+text, v...))
|
||||||
|
defer C.free(unsafe.Pointer(msg))
|
||||||
|
C.log_error(msg)
|
||||||
|
}
|
||||||
case LogDebug:
|
case LogDebug:
|
||||||
if traceDebugMsgs {
|
if logTypeFlags&LogDebug == 0 {
|
||||||
msg := C.CString(fmt.Sprintf("DEBUG: "+text, v...))
|
msg := C.CString(fmt.Sprintf("DEBUG: "+text, v...))
|
||||||
defer C.free(unsafe.Pointer(msg))
|
defer C.free(unsafe.Pointer(msg))
|
||||||
C.log_debug(msg)
|
C.log_debug(msg)
|
||||||
|
|
|
@ -2,23 +2,41 @@
|
||||||
|
|
||||||
package raylib
|
package raylib
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include "raylib.h"
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TraceLog - Trace log messages showing (INFO, WARNING, ERROR, DEBUG)
|
// SetTraceLog - Enable trace log message types (bit flags based)
|
||||||
|
func SetTraceLog(typeFlags int) {
|
||||||
|
logTypeFlags = typeFlags
|
||||||
|
|
||||||
|
ctypeFlags := (C.uchar)(typeFlags)
|
||||||
|
C.SetTraceLog(ctypeFlags)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TraceLog - Show trace log messages (INFO, WARNING, ERROR, DEBUG)
|
||||||
func TraceLog(msgType int, text string, v ...interface{}) {
|
func TraceLog(msgType int, text string, v ...interface{}) {
|
||||||
switch msgType {
|
switch msgType {
|
||||||
case LogInfo:
|
case LogInfo:
|
||||||
fmt.Printf("INFO: "+text+"\n", v...)
|
if logTypeFlags&LogInfo == 0 {
|
||||||
case LogError:
|
fmt.Printf("INFO: "+text+"\n", v...)
|
||||||
fmt.Printf("ERROR: "+text+"\n", v...)
|
}
|
||||||
os.Exit(1)
|
|
||||||
case LogWarning:
|
case LogWarning:
|
||||||
fmt.Printf("WARNING: "+text+"\n", v...)
|
if logTypeFlags&LogWarning == 0 {
|
||||||
|
fmt.Printf("WARNING: "+text+"\n", v...)
|
||||||
|
}
|
||||||
|
case LogError:
|
||||||
|
if logTypeFlags&LogError == 0 {
|
||||||
|
fmt.Printf("ERROR: "+text+"\n", v...)
|
||||||
|
}
|
||||||
case LogDebug:
|
case LogDebug:
|
||||||
if traceDebugMsgs {
|
if logTypeFlags&LogDebug == 0 {
|
||||||
fmt.Printf("DEBUG: "+text+"\n", v...)
|
fmt.Printf("DEBUG: "+text+"\n", v...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue