aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorvictorfisac <victorfisac@gmail.com>2017-03-30 02:46:19 +0200
committervictorfisac <victorfisac@gmail.com>2017-03-30 02:46:19 +0200
commit0d06c946f2a6b7ce0eb374159333872392a707d9 (patch)
treeac7321f9ef1d4ea8221aa01089e660ff477e2326 /src
parentb2f0c7ca8b8e9484560a45c4547794fa62cf484f (diff)
parent954a24545ffd65f55893bf02c3c8d530a03f099a (diff)
downloadraylib-0d06c946f2a6b7ce0eb374159333872392a707d9.tar.gz
raylib-0d06c946f2a6b7ce0eb374159333872392a707d9.zip
Merge remote-tracking branch 'refs/remotes/raysan5/develop' into develop
Diffstat (limited to 'src')
-rw-r--r--src/Makefile9
-rw-r--r--src/audio.c131
-rw-r--r--src/audio.h33
-rw-r--r--src/core.c35
-rw-r--r--src/models.c30
-rw-r--r--src/raylib.h7
-rw-r--r--src/rlgl.c21
-rw-r--r--src/text.c179
-rw-r--r--src/textures.c379
-rw-r--r--src/utils.c39
-rw-r--r--src/utils.h5
11 files changed, 462 insertions, 406 deletions
diff --git a/src/Makefile b/src/Makefile
index 598a9be4..4259a66b 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -172,9 +172,12 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
endif
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
- CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3 -s ASSERTIONS=1 --preload-file resources
- #-s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing
- #-s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB)
+ CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3 -s ASSERTIONS=1 --profiling --preload-file resources
+ # -O2 # if used, also set --memory-init-file 0
+ # --memory-init-file 0 # to avoid an external memory initialization code file (.mem)
+ # -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing
+ # -s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB)
+ # -s USE_PTHREADS=1 # multithreading support
endif
ifeq ($(PLATFORM),PLATFORM_RPI)
CFLAGS = -O1 -Wall -std=gnu99 -fgnu89-inline -Wno-missing-braces
diff --git a/src/audio.c b/src/audio.c
index 68bd88e9..34be4789 100644
--- a/src/audio.c
+++ b/src/audio.c
@@ -16,7 +16,7 @@
* Define to use the module as standalone library (independently of raylib).
* Required types and functions are defined in the same module.
*
-* #define SUPPORT_FILEFORMAT_WAV / SUPPORT_LOAD_WAV
+* #define SUPPORT_FILEFORMAT_WAV
* #define SUPPORT_FILEFORMAT_OGG
* #define SUPPORT_FILEFORMAT_XM
* #define SUPPORT_FILEFORMAT_MOD
@@ -24,10 +24,6 @@
* Selected desired fileformats to be supported for loading. Some of those formats are
* supported by default, to remove support, just comment unrequired #define in this module
*
-* #define SUPPORT_RAW_AUDIO_BUFFERS
-* Support creating raw audio buffers to send raw data. Buffers must be managed by the user,
-* it means initialization, refilling and cleaning.
-*
* LIMITATIONS:
* 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)
@@ -68,7 +64,11 @@
*
**********************************************************************************************/
-//#define AUDIO_STANDALONE // NOTE: To use the audio module as standalone lib, just uncomment this line
+// Default configuration flags (supported features)
+//-------------------------------------------------
+#define SUPPORT_FILEFORMAT_WAV
+#define SUPPORT_FILEFORMAT_OGG
+//-------------------------------------------------
#if defined(AUDIO_STANDALONE)
#include "audio.h"
@@ -94,18 +94,26 @@
#include <string.h> // Required for: strcmp(), strncmp()
#include <stdio.h> // Required for: FILE, fopen(), fclose(), fread()
-//#define STB_VORBIS_HEADER_ONLY
-#include "external/stb_vorbis.h" // OGG loading functions
+#if defined(SUPPORT_FILEFORMAT_OGG)
+ //#define STB_VORBIS_HEADER_ONLY
+ #include "external/stb_vorbis.h" // OGG loading functions
+#endif
-#define JAR_XM_IMPLEMENTATION
-#include "external/jar_xm.h" // XM loading functions
+#if defined(SUPPORT_FILEFORMAT_XM)
+ #define JAR_XM_IMPLEMENTATION
+ #include "external/jar_xm.h" // XM loading functions
+#endif
-#define JAR_MOD_IMPLEMENTATION
-#include "external/jar_mod.h" // MOD loading functions
+#if defined(SUPPORT_FILEFORMAT_MOD)
+ #define JAR_MOD_IMPLEMENTATION
+ #include "external/jar_mod.h" // MOD loading functions
+#endif
-#define DR_FLAC_IMPLEMENTATION
-#define DR_FLAC_NO_WIN32_IO
-#include "external/dr_flac.h" // FLAC loading functions
+#if defined(SUPPORT_FILEFORMAT_FLAC)
+ #define DR_FLAC_IMPLEMENTATION
+ #define DR_FLAC_NO_WIN32_IO
+ #include "external/dr_flac.h" // FLAC loading functions
+#endif
#ifdef _MSC_VER
#undef bool
@@ -140,10 +148,18 @@ typedef enum { MUSIC_AUDIO_OGG = 0, MUSIC_AUDIO_FLAC, MUSIC_MODULE_XM, MUSIC_MOD
// Music type (file streaming from memory)
typedef struct MusicData {
MusicContextType ctxType; // Type of music context (OGG, XM, MOD)
+#if defined(SUPPORT_FILEFORMAT_OGG)
stb_vorbis *ctxOgg; // OGG audio context
+#endif
+#if defined(SUPPORT_FILEFORMAT_FLAC)
drflac *ctxFlac; // FLAC audio context
+#endif
+#if defined(SUPPORT_FILEFORMAT_XM)
jar_xm_context_t *ctxXm; // XM chiptune context
+#endif
+#if defined(SUPPORT_FILEFORMAT_MOD)
jar_mod_context_t ctxMod; // MOD chiptune context
+#endif
AudioStream stream; // Audio stream (double buffering)
@@ -164,13 +180,19 @@ typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType;
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
+#if defined(SUPPORT_FILEFORMAT_WAV)
static Wave LoadWAV(const char *fileName); // Load WAV file
+#endif
+#if defined(SUPPORT_FILEFORMAT_OGG)
static Wave LoadOGG(const char *fileName); // Load OGG file
+#endif
+#if defined(SUPPORT_FILEFORMAT_FLAC)
static Wave LoadFLAC(const char *fileName); // Load FLAC file
+#endif
#if defined(AUDIO_STANDALONE)
-const char *GetExtension(const char *fileName); // Get the extension for a filename
-void TraceLog(int msgType, const char *text, ...); // Outputs a trace log message (INFO, ERROR, WARNING)
+bool IsFileExtension(const char *fileName, const char *ext); // Check file extension
+void TraceLog(int msgType, const char *text, ...); // Outputs trace log message (INFO, ERROR, WARNING)
#endif
//----------------------------------------------------------------------------------
@@ -260,10 +282,15 @@ Wave LoadWave(const char *fileName)
{
Wave wave = { 0 };
- if (strcmp(GetExtension(fileName), "wav") == 0) wave = LoadWAV(fileName);
- else if (strcmp(GetExtension(fileName), "ogg") == 0) wave = LoadOGG(fileName);
- else if (strcmp(GetExtension(fileName), "flac") == 0) wave = LoadFLAC(fileName);
- else if (strcmp(GetExtension(fileName),"rres") == 0)
+ if (IsFileExtension(fileName, ".wav")) wave = LoadWAV(fileName);
+#if defined(SUPPORT_FILEFORMAT_OGG)
+ else if (IsFileExtension(fileName, ".ogg")) wave = LoadOGG(fileName);
+#endif
+#if defined(SUPPORT_FILEFORMAT_FLAC)
+ else if (IsFileExtension(fileName, ".flac")) wave = LoadFLAC(fileName);
+#endif
+#if !defined(AUDIO_STANDALONE)
+ else if (IsFileExtension(fileName, ".rres"))
{
RRES rres = LoadResource(fileName, 0);
@@ -274,7 +301,8 @@ Wave LoadWave(const char *fileName)
UnloadResource(rres);
}
- else TraceLog(WARNING, "[%s] File extension not recognized, it can't be loaded", fileName);
+#endif
+ else TraceLog(WARNING, "[%s] Audio fileformat not supported, it can't be loaded", fileName);
return wave;
}
@@ -641,7 +669,7 @@ Music LoadMusicStream(const char *fileName)
{
Music music = (MusicData *)malloc(sizeof(MusicData));
- if (strcmp(GetExtension(fileName), "ogg") == 0)
+ if (IsFileExtension(fileName, ".ogg"))
{
// Open ogg audio stream
music->ctxOgg = stb_vorbis_open_filename(fileName, NULL, NULL);
@@ -664,7 +692,8 @@ Music LoadMusicStream(const char *fileName)
TraceLog(DEBUG, "[%s] OGG memory required: %i", fileName, info.temp_memory_required);
}
}
- else if (strcmp(GetExtension(fileName), "flac") == 0)
+#if defined(SUPPORT_FILEFORMAT_FLAC)
+ else if (IsFileExtension(fileName, ".flac"))
{
music->ctxFlac = drflac_open_file(fileName);
@@ -683,7 +712,9 @@ Music LoadMusicStream(const char *fileName)
TraceLog(DEBUG, "[%s] FLAC channels: %i", fileName, music->ctxFlac->channels);
}
}
- else if (strcmp(GetExtension(fileName), "xm") == 0)
+#endif
+#if defined(SUPPORT_FILEFORMAT_XM)
+ else if (IsFileExtension(fileName, ".xm"))
{
int result = jar_xm_create_context_from_file(&music->ctxXm, 48000, fileName);
@@ -703,7 +734,9 @@ Music LoadMusicStream(const char *fileName)
}
else TraceLog(WARNING, "[%s] XM file could not be opened", fileName);
}
- else if (strcmp(GetExtension(fileName), "mod") == 0)
+#endif
+#if defined(SUPPORT_FILEFORMAT_MOD)
+ else if (IsFileExtension(fileName, ".mod"))
{
jar_mod_init(&music->ctxMod);
@@ -720,7 +753,8 @@ Music LoadMusicStream(const char *fileName)
}
else TraceLog(WARNING, "[%s] MOD file could not be opened", fileName);
}
- else TraceLog(WARNING, "[%s] Music extension not recognized, it can't be loaded", fileName);
+#endif
+ else TraceLog(WARNING, "[%s] Audio fileformat not supported, it can't be loaded", fileName);
return music;
}
@@ -731,9 +765,15 @@ void UnloadMusicStream(Music music)
CloseAudioStream(music->stream);
if (music->ctxType == MUSIC_AUDIO_OGG) stb_vorbis_close(music->ctxOgg);
+#if defined(SUPPORT_FILEFORMAT_FLAC)
else if (music->ctxType == MUSIC_AUDIO_FLAC) drflac_free(music->ctxFlac);
+#endif
+#if defined(SUPPORT_FILEFORMAT_XM)
else if (music->ctxType == MUSIC_MODULE_XM) jar_xm_free_context(music->ctxXm);
+#endif
+#if defined(SUPPORT_FILEFORMAT_MOD)
else if (music->ctxType == MUSIC_MODULE_MOD) jar_mod_unload(&music->ctxMod);
+#endif
free(music);
}
@@ -778,8 +818,15 @@ void StopMusicStream(Music music)
switch (music->ctxType)
{
case MUSIC_AUDIO_OGG: stb_vorbis_seek_start(music->ctxOgg); break;
+#if defined(SUPPORT_FILEFORMAT_FLAC)
+ case MUSIC_MODULE_FLAC: /* TODO: Restart FLAC context */ break;
+#endif
+#if defined(SUPPORT_FILEFORMAT_XM)
case MUSIC_MODULE_XM: /* TODO: Restart XM context */ break;
+#endif
+#if defined(SUPPORT_FILEFORMAT_MOD)
case MUSIC_MODULE_MOD: jar_mod_seek_start(&music->ctxMod); break;
+#endif
default: break;
}
@@ -821,14 +868,20 @@ void UpdateMusicStream(Music music)
int numSamplesOgg = stb_vorbis_get_samples_short_interleaved(music->ctxOgg, music->stream.channels, (short *)pcm, samplesCount*music->stream.channels);
} break;
+ #if defined(SUPPORT_FILEFORMAT_FLAC)
case MUSIC_AUDIO_FLAC:
{
// NOTE: Returns the number of samples to process
unsigned int numSamplesFlac = (unsigned int)drflac_read_s16(music->ctxFlac, samplesCount*music->stream.channels, (short *)pcm);
} break;
+ #endif
+ #if defined(SUPPORT_FILEFORMAT_XM)
case MUSIC_MODULE_XM: jar_xm_generate_samples_16bit(music->ctxXm, pcm, samplesCount); break;
+ #endif
+ #if defined(SUPPORT_FILEFORMAT_MOD)
case MUSIC_MODULE_MOD: jar_mod_fillbuffer(&music->ctxMod, pcm, samplesCount, 0); break;
+ #endif
default: break;
}
@@ -1067,6 +1120,7 @@ void StopAudioStream(AudioStream stream)
// Module specific Functions Definition
//----------------------------------------------------------------------------------
+#if defined(SUPPORT_FILEFORMAT_WAV)
// Load WAV file into Wave structure
static Wave LoadWAV(const char *fileName)
{
@@ -1183,7 +1237,9 @@ static Wave LoadWAV(const char *fileName)
return wave;
}
+#endif
+#if defined(SUPPORT_FILEFORMAT_OGG)
// Load OGG file into Wave structure
// NOTE: Using stb_vorbis library
static Wave LoadOGG(const char *fileName)
@@ -1207,7 +1263,7 @@ static Wave LoadOGG(const char *fileName)
wave.sampleCount = (int)stb_vorbis_stream_length_in_samples(oggFile);
float totalSeconds = stb_vorbis_stream_length_in_seconds(oggFile);
- if (totalSeconds > 10) TraceLog(WARNING, "[%s] Ogg audio lenght is larger than 10 seconds (%f), that's a big file in memory, consider music streaming", fileName, totalSeconds);
+ if (totalSeconds > 10) TraceLog(WARNING, "[%s] Ogg audio length is larger than 10 seconds (%f), that's a big file in memory, consider music streaming", fileName, totalSeconds);
wave.data = (short *)malloc(wave.sampleCount*wave.channels*sizeof(short));
@@ -1223,7 +1279,9 @@ static Wave LoadOGG(const char *fileName)
return wave;
}
+#endif
+#if defined(SUPPORT_FILEFORMAT_FLAC)
// Load FLAC file into Wave structure
// NOTE: Using dr_flac library
static Wave LoadFLAC(const char *fileName)
@@ -1245,15 +1303,22 @@ static Wave LoadFLAC(const char *fileName)
return wave;
}
+#endif
// Some required functions for audio standalone module version
#if defined(AUDIO_STANDALONE)
-// Get the extension for a filename
-const char *GetExtension(const char *fileName)
+// Check file extension
+bool IsFileExtension(const char *fileName, const char *ext)
{
- const char *dot = strrchr(fileName, '.');
- if (!dot || dot == fileName) return "";
- return (dot + 1);
+ bool result = false;
+ const char *fileExt;
+
+ if ((fileExt = strrchr(fileName, '.')) != NULL)
+ {
+ if (strcmp(fileExt, ext) == 0) result = true;
+ }
+
+ return result;
}
// Outputs a trace log message (INFO, ERROR, WARNING)
diff --git a/src/audio.h b/src/audio.h
index 8047d9bb..48ef7403 100644
--- a/src/audio.h
+++ b/src/audio.h
@@ -2,22 +2,24 @@
*
* raylib.audio - Basic funtionality to work with audio
*
-* DESCRIPTION:
+* FEATURES:
+* - Manage audio device (init/close)
+* - Load and unload audio files
+* - Format wave data (sample rate, size, channels)
+* - Play/Stop/Pause/Resume loaded audio
+* - Manage mixing channels
+* - Manage raw audio context
*
-* This module provides basic functionality to:
-* - Manage audio device (init/close)
-* - Load and unload audio files
-* - Format wave data (sample rate, size, channels)
-* - Play/Stop/Pause/Resume loaded audio
-* - Manage mixing channels
-* - Manage raw audio context
+* LIMITATIONS:
+* 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)
*
* DEPENDENCIES:
* OpenAL Soft - Audio device management (http://kcat.strangesoft.net/openal.html)
* stb_vorbis - OGG audio files loading (http://www.nothings.org/stb_vorbis/)
-* jar_xm - XM module file loading
-* jar_mod - MOD audio file loading
-* dr_flac - FLAC audio file loading
+* jar_xm - XM module file loading (#define SUPPORT_FILEFORMAT_XM)
+* jar_mod - MOD audio file loading (#define SUPPORT_FILEFORMAT_MOD)
+* dr_flac - FLAC audio file loading (#define SUPPORT_FILEFORMAT_FLAC)
*
* CONTRIBUTORS:
* Joshua Reisenauer (github: @kd7tck):
@@ -121,7 +123,7 @@ Wave LoadWave(const char *fileName); // Load wave dat
Wave LoadWaveEx(void *data, int sampleCount, int sampleRate, int sampleSize, int channels); // Load wave data from raw array data
Sound LoadSound(const char *fileName); // Load sound from file
Sound LoadSoundFromWave(Wave wave); // Load sound from wave data
-void UpdateSound(Sound sound, const void *data, int samplesCount); // Update sound buffer with new data
+void UpdateSound(Sound sound, const void *data, int samplesCount);// Update sound buffer with new data
void UnloadWave(Wave wave); // Unload wave data
void UnloadSound(Sound sound); // Unload sound
void PlaySound(Sound sound); // Play a sound
@@ -149,10 +151,11 @@ void SetMusicLoopCount(Music music, float count); // Set music loo
float GetMusicTimeLength(Music music); // Get music time length (in seconds)
float GetMusicTimePlayed(Music music); // Get current music time played (in seconds)
+// Raw audio stream functions
AudioStream InitAudioStream(unsigned int sampleRate,
- unsigned int sampleSize,
- unsigned int channels); // Init audio stream (to stream raw audio pcm data)
-void UpdateAudioStream(AudioStream stream, void *data, int samplesCount); // Update audio stream buffers with data
+ unsigned int sampleSize,
+ 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 CloseAudioStream(AudioStream stream); // Close audio stream and free memory
bool IsAudioBufferProcessed(AudioStream stream); // Check if any audio stream buffers requires refill
void PlayAudioStream(AudioStream stream); // Play audio stream
diff --git a/src/core.c b/src/core.c
index 1a0e5a66..b9ea9315 100644
--- a/src/core.c
+++ b/src/core.c
@@ -70,13 +70,13 @@
*
**********************************************************************************************/
-// Default supported features
-//-------------------------------------
+// Default configuration flags (supported features)
+//-------------------------------------------------
#define SUPPORT_DEFAULT_FONT
#define SUPPORT_MOUSE_GESTURES
#define SUPPORT_CAMERA_SYSTEM
#define SUPPORT_GESTURES_SYSTEM
-//-------------------------------------
+//-------------------------------------------------
#include "raylib.h"
@@ -102,7 +102,7 @@
#include <stdint.h> // Required for: typedef unsigned long long int uint64_t, used by hi-res timer
#include <time.h> // Required for: time() - Android/RPI hi-res timer (NOTE: Linux only!)
#include <math.h> // Required for: tan() [Used in Begin3dMode() to set perspective]
-#include <string.h> // Required for: strcmp()
+#include <string.h> // Required for: strrchr(), strcmp()
//#include <errno.h> // Macros for reporting and retrieving error conditions through error codes
#if defined __linux__ || defined(PLATFORM_WEB)
@@ -978,6 +978,12 @@ Color Fade(Color color, float alpha)
return (Color){color.r, color.g, color.b, (unsigned char)colorAlpha};
}
+// Activates raylib logo at startup
+void ShowLogo(void)
+{
+ showLogo = true;
+}
+
// Enable some window/system configurations
void SetConfigFlags(char flags)
{
@@ -987,10 +993,18 @@ void SetConfigFlags(char flags)
if (configFlags & FLAG_FULLSCREEN_MODE) fullscreen = true;
}
-// Activates raylib logo at startup
-void ShowLogo(void)
+// Check file extension
+bool IsFileExtension(const char *fileName, const char *ext)
{
- showLogo = true;
+ bool result = false;
+ const char *fileExt;
+
+ if ((fileExt = strrchr(fileName, '.')) != NULL)
+ {
+ if (strcmp(fileExt, ext) == 0) result = true;
+ }
+
+ return result;
}
#if defined(PLATFORM_DESKTOP)
@@ -2024,9 +2038,12 @@ static double GetTime(void)
}
// Wait for some milliseconds (stop program execution)
+// 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
+// http://stackoverflow.com/questions/43057578/c-programming-win32-games-sleep-taking-longer-than-expected
static void Wait(float ms)
{
-//#define SUPPORT_BUSY_WAIT_LOOP
+#define SUPPORT_BUSY_WAIT_LOOP
#if defined(SUPPORT_BUSY_WAIT_LOOP)
double prevTime = GetTime();
double nextTime = 0.0;
@@ -2035,7 +2052,7 @@ static void Wait(float ms)
while ((nextTime - prevTime) < ms/1000.0f) nextTime = GetTime();
#else
#if defined _WIN32
- Sleep(ms);
+ Sleep((unsigned int)ms);
#elif defined __linux__ || defined(PLATFORM_WEB)
struct timespec req = { 0 };
time_t sec = (int)(ms/1000.0f);
diff --git a/src/models.c b/src/models.c
index 67e1693c..47220af8 100644
--- a/src/models.c
+++ b/src/models.c
@@ -4,7 +4,7 @@
*
* CONFIGURATION:
*
-* #define SUPPORT_FILEFORMAT_OBJ / SUPPORT_LOAD_OBJ
+* #define SUPPORT_FILEFORMAT_OBJ
* Selected desired fileformats to be supported for loading.
*
* #define SUPPORT_FILEFORMAT_MTL
@@ -32,6 +32,12 @@
*
**********************************************************************************************/
+// Default configuration flags (supported features)
+//-------------------------------------------------
+#define SUPPORT_FILEFORMAT_OBJ
+#define SUPPORT_FILEFORMAT_MTL
+//-------------------------------------------------
+
#include "raylib.h"
#if defined(PLATFORM_ANDROID)
@@ -63,8 +69,12 @@
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
+#if defined(SUPPORT_FILEFORMAT_OBJ)
static Mesh LoadOBJ(const char *fileName); // Load OBJ mesh data
+#endif
+#if defined(SUPPORT_FILEFORMAT_MTL)
static Material LoadMTL(const char *fileName); // Load MTL material data
+#endif
static Mesh GenMeshHeightmap(Image image, Vector3 size);
static Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize);
@@ -582,8 +592,11 @@ Mesh LoadMesh(const char *fileName)
{
Mesh mesh = { 0 };
- if (strcmp(GetExtension(fileName), "obj") == 0) mesh = LoadOBJ(fileName);
- else TraceLog(WARNING, "[%s] Mesh extension not recognized, it can't be loaded", fileName);
+#if defined(SUPPORT_FILEFORMAT_OBJ)
+ if (IsFileExtension(fileName, ".obj")) mesh = LoadOBJ(fileName);
+#else
+ TraceLog(WARNING, "[%s] Mesh fileformat not supported, it can't be loaded", fileName);
+#endif
if (mesh.vertexCount == 0) TraceLog(WARNING, "Mesh could not be loaded");
else rlglLoadMesh(&mesh, false); // Upload vertex data to GPU (static mesh)
@@ -692,8 +705,11 @@ Material LoadMaterial(const char *fileName)
{
Material material = { 0 };
- if (strcmp(GetExtension(fileName), "mtl") == 0) material = LoadMTL(fileName);
- else TraceLog(WARNING, "[%s] Material extension not recognized, it can't be loaded", fileName);
+#if defined(SUPPORT_FILEFORMAT_MTL)
+ if (IsFileExtension(fileName, ".mtl")) material = LoadMTL(fileName);
+#else
+ TraceLog(WARNING, "[%s] Material fileformat not supported, it can't be loaded", fileName);
+#endif
return material;
}
@@ -1590,6 +1606,7 @@ BoundingBox CalculateBoundingBox(Mesh mesh)
// Module specific Functions Definition
//----------------------------------------------------------------------------------
+#if defined(SUPPORT_FILEFORMAT_OBJ)
// Load OBJ mesh data
static Mesh LoadOBJ(const char *fileName)
{
@@ -1838,7 +1855,9 @@ static Mesh LoadOBJ(const char *fileName)
return mesh;
}
+#endif
+#if defined(SUPPORT_FILEFORMAT_MTL)
// Load MTL material data (specs: http://paulbourke.net/dataformats/mtl/)
// NOTE: Texture map parameters are not supported
static Material LoadMTL(const char *fileName)
@@ -2002,3 +2021,4 @@ static Material LoadMTL(const char *fileName)
return material;
}
+#endif
diff --git a/src/raylib.h b/src/raylib.h
index cdefceb2..3e6c68ff 100644
--- a/src/raylib.h
+++ b/src/raylib.h
@@ -13,7 +13,7 @@
* - Multiple textures support, including compressed formats and mipmaps generation
* - Basic 3d support for Shapes, Models, Billboards, Heightmaps and Cubicmaps
* - Powerful math module for Vector, Matrix and Quaternion operations: [raymath]
-* - Audio loading and playing with streaming support and mixing channels [audio]
+* - Audio loading and playing with streaming support and mixing channels: [audio]
* - VR stereo rendering support with configurable HMD device parameters
* - Multiple platforms support: Windows, Linux, Mac, Android, Raspberry Pi, HTML5 and Oculus Rift CV1
* - Custom color palette for fancy visuals on raywhite background
@@ -687,9 +687,10 @@ RLAPI float *MatrixToFloat(Matrix mat); // Converts Ma
RLAPI int GetRandomValue(int min, int max); // Returns a random value between min and max (both included)
RLAPI Color Fade(Color color, float alpha); // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f
-RLAPI void SetConfigFlags(char flags); // Setup some window configuration flags
RLAPI void ShowLogo(void); // Activates raylib logo at startup (can be done with flags)
-//RLAPI void TraceLog(int logType, const char *text, ...); // Trace log messages showing (INFO, WARNING, ERROR, DEBUG)
+RLAPI void SetConfigFlags(char flags); // Setup some window configuration flags
+//RLAPI void TraceLog(int logType, const char *text, ...); // Show trace log messages (INFO, WARNING, ERROR, DEBUG)
+RLAPI bool IsFileExtension(const char *fileName, const char *ext);// Check file extension
RLAPI bool IsFileDropped(void); // Check if a file have been dropped into window
RLAPI char **GetDroppedFiles(int *count); // Retrieve dropped files into window
diff --git a/src/rlgl.c b/src/rlgl.c
index a937bdec..546fbe6e 100644
--- a/src/rlgl.c
+++ b/src/rlgl.c
@@ -25,7 +25,7 @@
* #define SUPPORT_VR_SIMULATION / SUPPORT_STEREO_RENDERING
* Support VR simulation functionality (stereo rendering)
*
-* #define SUPPORT_SHADER_DISTORTION
+* #define SUPPORT_DISTORTION_SHADER
* Include stereo rendering distortion shader (shader_distortion.h)
*
* DEPENDENCIES:
@@ -54,6 +54,11 @@
*
**********************************************************************************************/
+// Default configuration flags (supported features)
+//-------------------------------------------------
+#define SUPPORT_VR_SIMULATION
+//-------------------------------------------------
+
#include "rlgl.h"
#include <stdio.h> // Required for: fopen(), fclose(), fread()... [Used only on LoadText()]
@@ -100,7 +105,7 @@
#include <stdarg.h> // Required for: va_list, va_start(), vfprintf(), va_end() [Used only on TraceLog()]
#endif
-#if !defined(GRAPHICS_API_OPENGL_11) && !defined(RLGL_NO_DISTORTION_SHADER)
+#if !defined(GRAPHICS_API_OPENGL_11) && defined(SUPPORT_DISTORTION_SHADER)
#include "shader_distortion.h" // Distortion shader to be embedded
#endif
@@ -2591,10 +2596,12 @@ void InitVrSimulator(int vrDevice)
// Initialize framebuffer and textures for stereo rendering
// NOTE: screen size should match HMD aspect ratio
vrConfig.stereoFbo = rlglLoadRenderTexture(screenWidth, screenHeight);
-
+
+#if defined(SUPPORT_DISTORTION_SHADER)
// Load distortion shader (initialized by default with Oculus Rift CV1 parameters)
vrConfig.distortionShader.id = LoadShaderProgram(vDistortionShaderStr, fDistortionShaderStr);
if (vrConfig.distortionShader.id != 0) LoadDefaultShaderLocations(&vrConfig.distortionShader);
+#endif
SetStereoConfig(hmd);
@@ -2613,7 +2620,9 @@ void CloseVrSimulator(void)
if (vrSimulatorReady)
{
rlDeleteRenderTextures(vrConfig.stereoFbo); // Unload stereo framebuffer and texture
+ #if defined(SUPPORT_DISTORTION_SHADER)
UnloadShader(vrConfig.distortionShader); // Unload distortion shader
+ #endif
}
#endif
}
@@ -2700,8 +2709,12 @@ void EndVrDrawing(void)
rlMatrixMode(RL_MODELVIEW); // Enable internal modelview matrix
rlLoadIdentity(); // Reset internal modelview matrix
+#if defined(SUPPORT_DISTORTION_SHADER)
// Draw RenderTexture (stereoFbo) using distortion shader
currentShader = vrConfig.distortionShader;
+#else
+ currentShader = GetDefaultShader();
+#endif
rlEnableTexture(vrConfig.stereoFbo.texture.id);
@@ -3536,6 +3549,7 @@ static void SetStereoConfig(VrDeviceInfo hmd)
TraceLog(DEBUG, "VR: Distortion Shader: Scale = { %f, %f }", scale[0], scale[1]);
TraceLog(DEBUG, "VR: Distortion Shader: ScaleIn = { %f, %f }", scaleIn[0], scaleIn[1]);
+#if defined(SUPPORT_DISTORTION_SHADER)
// Update distortion shader with lens and distortion-scale parameters
SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "leftLensCenter"), leftLensCenter, 2);
SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "rightLensCenter"), rightLensCenter, 2);
@@ -3546,6 +3560,7 @@ static void SetStereoConfig(VrDeviceInfo hmd)
SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "scaleIn"), scaleIn, 2);
SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "hmdWarpParam"), hmd.distortionK, 4);
SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "chromaAbParam"), hmd.chromaAbCorrection, 4);
+#endif
// Fovy is normally computed with: 2*atan2(hmd.vScreenSize, 2*hmd.eyeToScreenDistance)*RAD2DEG
// ...but with lens distortion it is increased (see Oculus SDK Documentation)
diff --git a/src/text.c b/src/text.c
index 13a01469..09f69ff6 100644
--- a/src/text.c
+++ b/src/text.c
@@ -5,8 +5,7 @@
* CONFIGURATION:
*
* #define SUPPORT_FILEFORMAT_FNT
-* #define SUPPORT_FILEFORMAT_TTF / INCLUDE_STB_TRUETYPE
-* #define SUPPORT_FILEFORMAT_IMAGE_FONT
+* #define SUPPORT_FILEFORMAT_TTF
* Selected desired fileformats to be supported for loading. Some of those formats are
* supported by default, to remove support, just comment unrequired #define in this module
*
@@ -49,12 +48,14 @@
#include <stdarg.h> // Required for: va_list, va_start(), vfprintf(), va_end()
#include <stdio.h> // Required for: FILE, fopen(), fclose(), fscanf(), feof(), rewind(), fgets()
-#include "utils.h" // Required for: GetExtension()
+#include "utils.h" // Required for: IsFileExtension()
-// Following libs are used on LoadTTF()
-#define STBTT_STATIC // Define stb_truetype functions static to this module
-#define STB_TRUETYPE_IMPLEMENTATION
-#include "external/stb_truetype.h" // Required for: stbtt_BakeFontBitmap()
+#if defined(SUPPORT_FILEFORMAT_TTF)
+ // Following libs are used on LoadTTF()
+ #define STBTT_STATIC // Define stb_truetype functions static to this module
+ #define STB_TRUETYPE_IMPLEMENTATION
+ #include "external/stb_truetype.h" // Required for: stbtt_BakeFontBitmap()
+#endif
// Rectangle packing functions (not used at the moment)
//#define STB_RECT_PACK_IMPLEMENTATION
@@ -90,9 +91,12 @@ static SpriteFont defaultFont; // Default font provided by raylib
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 LoadRBMF(const char *fileName); // Load a rBMF font file (raylib BitMap Font)
+#if defined(SUPPORT_FILEFORMAT_FNT)
static SpriteFont LoadBMFont(const char *fileName); // Load a BMFont file (AngelCode font file)
+#endif
+#if defined(SUPPORT_FILEFORMAT_TTF)
static SpriteFont LoadTTF(const char *fileName, int fontSize, int charsCount, int *fontChars); // Load spritefont from TTF data
+#endif
#if defined(SUPPORT_DEFAULT_FONT)
extern void LoadDefaultFont(void);
@@ -283,10 +287,7 @@ SpriteFont LoadSpriteFont(const char *fileName)
SpriteFont spriteFont = { 0 };
// Check file extension
- if (strcmp(GetExtension(fileName),"rbmf") == 0) spriteFont = LoadRBMF(fileName); // TODO: DELETE... SOON...
- else if (strcmp(GetExtension(fileName),"ttf") == 0) spriteFont = LoadSpriteFontTTF(fileName, DEFAULT_TTF_FONTSIZE, 0, NULL);
- else if (strcmp(GetExtension(fileName),"fnt") == 0) spriteFont = LoadBMFont(fileName);
- else if (strcmp(GetExtension(fileName),"rres") == 0)
+ if (IsFileExtension(fileName, ".rres"))
{
// TODO: Read multiple resource blocks from file (RRES_FONT_IMAGE, RRES_FONT_CHARDATA)
RRES rres = LoadResource(fileName, 0);
@@ -312,6 +313,12 @@ SpriteFont LoadSpriteFont(const char *fileName)
// TODO: Do not free rres.data memory (chars info data!)
//UnloadResource(rres[0]);
}
+#if defined(SUPPORT_FILEFORMAT_TTF)
+ else if (IsFileExtension(fileName, ".ttf")) spriteFont = LoadSpriteFontTTF(fileName, DEFAULT_TTF_FONTSIZE, 0, NULL);
+#endif
+#if defined(SUPPORT_FILEFORMAT_FNT)
+ else if (IsFileExtension(fileName, ".fnt")) spriteFont = LoadBMFont(fileName);
+#endif
else
{
Image image = LoadImage(fileName);
@@ -336,7 +343,8 @@ SpriteFont LoadSpriteFontTTF(const char *fileName, int fontSize, int charsCount,
{
SpriteFont spriteFont = { 0 };
- if (strcmp(GetExtension(fileName),"ttf") == 0)
+#if defined(SUPPORT_FILEFORMAT_TTF)
+ if (IsFileExtension(fileName, ".ttf"))
{
if ((fontChars == NULL) || (charsCount == 0))
{
@@ -350,6 +358,7 @@ SpriteFont LoadSpriteFontTTF(const char *fileName, int fontSize, int charsCount,
}
else spriteFont = LoadTTF(fileName, fontSize, charsCount, fontChars);
}
+#endif
if (spriteFont.texture.id == 0)
{
@@ -707,144 +716,7 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar)
return spriteFont;
}
-// Load a rBMF font file (raylib BitMap Font)
-static SpriteFont LoadRBMF(const char *fileName)
-{
- // rBMF Info Header (16 bytes)
- typedef struct {
- char id[4]; // rBMF file identifier
- char version; // rBMF file version
- // 4 MSB --> main version
- // 4 LSB --> subversion
- char firstChar; // First character in the font
- // NOTE: Depending on charDataType, it could be useless
- short imgWidth; // Image width - always POT (power-of-two)
- short imgHeight; // Image height - always POT (power-of-two)
- short numChars; // Number of characters contained
- short charHeight; // Characters height - the same for all characters
- char compType; // Compression type:
- // 4 MSB --> image data compression
- // 4 LSB --> chars data compression
- char charsDataType; // Char data type provided
- } rbmfInfoHeader;
-
- SpriteFont spriteFont = { 0 };
-
- // REMOVE SOON!!!
-/*
- rbmfInfoHeader rbmfHeader;
- unsigned int *rbmfFileData = NULL;
- unsigned char *rbmfCharWidthData = NULL;
-
- int charsDivisor = 1; // Every char is separated from the consecutive by a 1 pixel divisor, horizontally and vertically
-
- FILE *rbmfFile = fopen(fileName, "rb"); // Define a pointer to bitmap file and open it in read-binary mode
-
- if (rbmfFile == NULL)
- {
- TraceLog(WARNING, "[%s] rBMF font file could not be opened, using default font", fileName);
-
- spriteFont = GetDefaultFont();
- }
- else
- {
- fread(&rbmfHeader, sizeof(rbmfInfoHeader), 1, rbmfFile);
-
- TraceLog(DEBUG, "[%s] Loading rBMF file, size: %ix%i, numChars: %i, charHeight: %i", fileName, rbmfHeader.imgWidth, rbmfHeader.imgHeight, rbmfHeader.numChars, rbmfHeader.charHeight);
-
- spriteFont.numChars = (int)rbmfHeader.numChars;
-
- int numPixelBits = rbmfHeader.imgWidth*rbmfHeader.imgHeight/32;
-
- rbmfFileData = (unsigned int *)malloc(numPixelBits*sizeof(unsigned int));
-
- for (int i = 0; i < numPixelBits; i++) fread(&rbmfFileData[i], sizeof(unsigned int), 1, rbmfFile);
-
- rbmfCharWidthData = (unsigned char *)malloc(spriteFont.numChars*sizeof(unsigned char));
-
- for (int i = 0; i < spriteFont.numChars; i++) fread(&rbmfCharWidthData[i], sizeof(unsigned char), 1, rbmfFile);
-
- // Re-construct image from rbmfFileData
- //-----------------------------------------
- Color *imagePixels = (Color *)malloc(rbmfHeader.imgWidth*rbmfHeader.imgHeight*sizeof(Color));
-
- for (int i = 0; i < rbmfHeader.imgWidth*rbmfHeader.imgHeight; i++) imagePixels[i] = BLANK; // Initialize array
-
- int counter = 0; // Font data elements counter
-
- // Fill image data (convert from bit to pixel!)
- for (int i = 0; i < rbmfHeader.imgWidth*rbmfHeader.imgHeight; i += 32)
- {
- for (int j = 31; j >= 0; j--)
- {
- if (BIT_CHECK(rbmfFileData[counter], j)) imagePixels[i+j] = WHITE;
- }
-
- counter++;
- }
-
- Image image = LoadImageEx(imagePixels, rbmfHeader.imgWidth, rbmfHeader.imgHeight);
- ImageFormat(&image, UNCOMPRESSED_GRAY_ALPHA);
-
- free(imagePixels);
-
- TraceLog(DEBUG, "[%s] Image reconstructed correctly, now converting it to texture", fileName);
-
- // Create spritefont with all data read from rbmf file
- spriteFont.texture = LoadTextureFromImage(image);
- UnloadImage(image); // Unload image data
-
- //TraceLog(INFO, "[%s] Starting chars set reconstruction", fileName);
-
- // Get characters data using rbmfCharWidthData, rbmfHeader.charHeight, charsDivisor, rbmfHeader.numChars
- spriteFont.chars = (CharInfo *)malloc(spriteFont.charsCount*sizeof(CharInfo));
-
- int currentLine = 0;
- int currentPosX = charsDivisor;
- int testPosX = charsDivisor;
-
- for (int i = 0; i < spriteFont.charsCount; i++)
- {
- spriteFont.chars[i].value = (int)rbmfHeader.firstChar + i;
-
- spriteFont.chars[i].rec.x = currentPosX;
- spriteFont.chars[i].rec.y = charsDivisor + currentLine*((int)rbmfHeader.charHeight + charsDivisor);
- spriteFont.chars[i].rec.width = (int)rbmfCharWidthData[i];
- spriteFont.chars[i].rec.height = (int)rbmfHeader.charHeight;
-
- // NOTE: On image based fonts (XNA style), character offsets and xAdvance are not required (set to 0)
- spriteFont.chars[i].offsetX = 0;
- spriteFont.chars[i].offsetY = 0;
- spriteFont.chars[i].advanceX = 0;
-
- testPosX += (spriteFont.chars[i].rec.width + charsDivisor);
-
- if (testPosX > spriteFont.texture.width)
- {
- currentLine++;
- currentPosX = 2*charsDivisor + (int)rbmfCharWidthData[i];
- testPosX = currentPosX;
-
- spriteFont.chars[i].rec.x = charsDivisor;
- spriteFont.chars[i].rec.y = charsDivisor + currentLine*(rbmfHeader.charHeight + charsDivisor);
- }
- else currentPosX = testPosX;
- }
-
- spriteFont.baseSize = spriteFont.charRecs[0].height;
-
- TraceLog(INFO, "[%s] rBMF file loaded correctly as SpriteFont", fileName);
- }
-
- fclose(rbmfFile);
-
- free(rbmfFileData); // Now we can free loaded data from RAM memory
- free(rbmfCharWidthData);
-*/
-
- return spriteFont;
-}
-
+#if defined(SUPPORT_FILEFORMAT_FNT)
// Load a BMFont file (AngelCode font file)
static SpriteFont LoadBMFont(const char *fileName)
{
@@ -962,7 +834,9 @@ static SpriteFont LoadBMFont(const char *fileName)
return font;
}
+#endif
+#if defined(SUPPORT_FILEFORMAT_TTF)
// Generate a sprite font from TTF file data (font size required)
// TODO: Review texture packing method and generation (use oversampling)
static SpriteFont LoadTTF(const char *fileName, int fontSize, int charsCount, int *fontChars)
@@ -1054,4 +928,5 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize, int charsCount, in
free(charData);
return font;
-} \ No newline at end of file
+}
+#endif
diff --git a/src/textures.c b/src/textures.c
index f323f352..fff0e4e9 100644
--- a/src/textures.c
+++ b/src/textures.c
@@ -4,24 +4,24 @@
*
* CONFIGURATION:
*
-* #define SUPPORT_STB_IMAGE / INCLUDE_STB_IMAGE
-*
-* #define SUPPORT_FILEFORMAT_BMP / SUPPORT_LOAD_BMP
-* #define SUPPORT_FILEFORMAT_PNG / SUPPORT_LOAD_PNG
+* #define SUPPORT_FILEFORMAT_BMP
+* #define SUPPORT_FILEFORMAT_PNG
* #define SUPPORT_FILEFORMAT_TGA
-* #define SUPPORT_FILEFORMAT_JPG / ENABLE_LOAD_JPG
+* #define SUPPORT_FILEFORMAT_JPG
* #define SUPPORT_FILEFORMAT_GIF
+* #define SUPPORT_FILEFORMAT_PSD
* #define SUPPORT_FILEFORMAT_HDR
-* #define SUPPORT_FILEFORMAT_DDS / ENABLE_LOAD_DDS
+* #define SUPPORT_FILEFORMAT_DDS
* #define SUPPORT_FILEFORMAT_PKM
* #define SUPPORT_FILEFORMAT_KTX
* #define SUPPORT_FILEFORMAT_PVR
* #define SUPPORT_FILEFORMAT_ASTC
-* Selected desired fileformats to be supported for loading. Some of those formats are
+* Selecte desired fileformats to be supported for image data loading. Some of those formats are
* supported by default, to remove support, just comment unrequired #define in this module
*
-* #define SUPPORT_IMAGE_RESIZE / INCLUDE_STB_IMAGE_RESIZE
* #define SUPPORT_IMAGE_MANIPULATION
+* Support multiple image editing functions to scale, adjust colors, flip, draw on images, crop...
+* If not defined only three image editing functions supported: ImageFormat(), ImageAlphaMask(), ImageToPOT()
*
* DEPENDENCIES:
* stb_image - Multiple image formats loading (JPEG, PNG, BMP, TGA, PSD, GIF, PIC)
@@ -50,6 +50,12 @@
*
**********************************************************************************************/
+// Default configuration flags (supported features)
+//-------------------------------------------------
+#define SUPPORT_FILEFORMAT_PNG
+#define SUPPORT_IMAGE_MANIPULATION
+//-------------------------------------------------
+
#include "raylib.h"
#include <stdlib.h> // Required for: malloc(), free()
@@ -61,23 +67,46 @@
#include "utils.h" // Required for: fopen() Android mapping, TraceLog()
-// Support only desired texture formats, by default: JPEG, PNG, BMP, TGA
-//#define STBI_NO_JPEG // Image format .jpg and .jpeg
-//#define STBI_NO_PNG
-//#define STBI_NO_BMP
-//#define STBI_NO_TGA
-#define STBI_NO_PSD
-#define STBI_NO_GIF
-#define STBI_NO_HDR
+// Support only desired texture formats on stb_image
+#if !defined(SUPPORT_FILEFORMAT_BMP)
+ #define STBI_NO_BMP
+#endif
+#if !defined(SUPPORT_FILEFORMAT_PNG)
+ #define STBI_NO_PNG
+#endif
+#if !defined(SUPPORT_FILEFORMAT_TGA)
+ #define STBI_NO_TGA
+#endif
+#if !defined(SUPPORT_FILEFORMAT_JPG)
+ #define STBI_NO_JPEG // Image format .jpg and .jpeg
+#endif
+#if !defined(SUPPORT_FILEFORMAT_PSD)
+ #define STBI_NO_PSD
+#endif
+#if !defined(SUPPORT_FILEFORMAT_GIF)
+ #define STBI_NO_GIF
+#endif
+#if !defined(SUPPORT_FILEFORMAT_HDR)
+ #define STBI_NO_HDR
+#endif
+
+// Image fileformats not supported by default
#define STBI_NO_PIC
#define STBI_NO_PNM // Image format .ppm and .pgm
-#define STB_IMAGE_IMPLEMENTATION
-#include "external/stb_image.h" // Required for: stbi_load()
- // NOTE: Used to read image data (multiple formats support)
-#define STB_IMAGE_RESIZE_IMPLEMENTATION
-#include "external/stb_image_resize.h" // Required for: stbir_resize_uint8()
- // NOTE: Used for image scaling on ImageResize()
+#if (defined(SUPPORT_FILEFORMAT_BMP) || defined(SUPPORT_FILEFORMAT_PNG) || defined(SUPPORT_FILEFORMAT_TGA) || \
+ defined(SUPPORT_FILEFORMAT_JPG) || defined(SUPPORT_FILEFORMAT_PSD) || defined(SUPPORT_FILEFORMAT_GIF) || \
+ defined(SUPPORT_FILEFORMAT_HDR))
+ #define STB_IMAGE_IMPLEMENTATION
+ #include "external/stb_image.h" // Required for: stbi_load()
+ // NOTE: Used to read image data (multiple formats support)
+#endif
+
+#if defined(SUPPORT_IMAGE_MANIPULATION)
+ #define STB_IMAGE_RESIZE_IMPLEMENTATION
+ #include "external/stb_image_resize.h" // Required for: stbir_resize_uint8()
+ // NOTE: Used for image scaling on ImageResize()
+#endif
//----------------------------------------------------------------------------------
// Defines and Macros
@@ -102,11 +131,21 @@
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
+#if defined(SUPPORT_FILEFORMAT_DDS)
static Image LoadDDS(const char *fileName); // Load DDS file
+#endif
+#if defined(SUPPORT_FILEFORMAT_PKM)
static Image LoadPKM(const char *fileName); // Load PKM file
+#endif
+#if defined(SUPPORT_FILEFORMAT_KTX)
static Image LoadKTX(const char *fileName); // Load KTX file
+#endif
+#if defined(SUPPORT_FILEFORMAT_PVR)
static Image LoadPVR(const char *fileName); // Load PVR file
+#endif
+#if defined(SUPPORT_FILEFORMAT_ASTC)
static Image LoadASTC(const char *fileName); // Load ASTC file
+#endif
//----------------------------------------------------------------------------------
// Module Functions Definition
@@ -124,18 +163,32 @@ Image LoadImage(const char *fileName)
image.mipmaps = 0;
image.format = 0;
- if ((strcmp(GetExtension(fileName),"png") == 0) ||
- (strcmp(GetExtension(fileName),"bmp") == 0) ||
- (strcmp(GetExtension(fileName),"tga") == 0) ||
- (strcmp(GetExtension(fileName),"jpg") == 0)
-#ifndef STBI_NO_GIF
- || (strcmp(GetExtension(fileName),"gif") == 0)
+ if (IsFileExtension(fileName, ".rres"))
+ {
+ 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(WARNING, "[%s] Resource file does not contain image data", fileName);
+
+ UnloadResource(rres);
+ }
+ else if ((IsFileExtension(fileName, ".png"))
+#if defined(SUPPORT_FILEFORMAT_BMP)
+ || (IsFileExtension(fileName, ".bmp"))
+#endif
+#if defined(SUPPORT_FILEFORMAT_TGA)
+ || (IsFileExtension(fileName, ".tga"))
#endif
-#ifndef STBI_NO_PSD
- || (strcmp(GetExtension(fileName),"psd") == 0)
+#if defined(SUPPORT_FILEFORMAT_JPG)
+ || (IsFileExtension(fileName, ".jpg"))
#endif
-#ifndef STBI_NO_PIC
- || (strcmp(GetExtension(fileName),"pic") == 0)
+#if defined(SUPPORT_FILEFORMAT_DDS)
+ || (IsFileExtension(fileName, ".gif"))
+#endif
+#if defined(SUPPORT_FILEFORMAT_PSD)
+ || (IsFileExtension(fileName, ".psd"))
#endif
)
{
@@ -155,22 +208,22 @@ Image LoadImage(const char *fileName)
else if (imgBpp == 3) image.format = UNCOMPRESSED_R8G8B8;
else if (imgBpp == 4) image.format = UNCOMPRESSED_R8G8B8A8;
}
- else if (strcmp(GetExtension(fileName),"dds") == 0) image = LoadDDS(fileName);
- else if (strcmp(GetExtension(fileName),"pkm") == 0) image = LoadPKM(fileName);
- else if (strcmp(GetExtension(fileName),"ktx") == 0) image = LoadKTX(fileName);
- else if (strcmp(GetExtension(fileName),"pvr") == 0) image = LoadPVR(fileName);
- else if (strcmp(GetExtension(fileName),"astc") == 0) image = LoadASTC(fileName);
- else if (strcmp(GetExtension(fileName),"rres") == 0)
- {
- 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(WARNING, "[%s] Resource file does not contain image data", fileName);
-
- UnloadResource(rres);
- }
+#if defined(SUPPORT_FILEFORMAT_DDS)
+ else if (IsFileExtension(fileName, ".dds")) image = LoadDDS(fileName);
+#endif
+#if defined(SUPPORT_FILEFORMAT_PKM)
+ else if (IsFileExtension(fileName, ".pkm")) image = LoadPKM(fileName);
+#endif
+#if defined(SUPPORT_FILEFORMAT_KTX)
+ else if (IsFileExtension(fileName, ".ktx")) image = LoadKTX(fileName);
+#endif
+#if defined(SUPPORT_FILEFORMAT_PVR)
+ else if (IsFileExtension(fileName, ".pvr")) image = LoadPVR(fileName);
+#endif
+#if defined(SUPPORT_FILEFORMAT_ASTC)
+ else if (IsFileExtension(fileName, ".astc")) image = LoadASTC(fileName);
+#endif
+ else TraceLog(WARNING, "[%s] Image fileformat not supported", fileName);
if (image.data != NULL) TraceLog(INFO, "[%s] Image loaded successfully (%ix%i)", fileName, image.width, image.height);
else TraceLog(WARNING, "[%s] Image could not be loaded", fileName);
@@ -664,115 +717,6 @@ void ImageAlphaMask(Image *image, Image alphaMask)
}
}
-// 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(WARNING, "Compressed data formats can not be dithered");
- return;
- }
-
- if ((rBpp+gBpp+bBpp+aBpp) > 16)
- {
- TraceLog(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(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(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);
- }
-}
-
// 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)
@@ -818,6 +762,7 @@ void ImageToPOT(Image *image, Color fillColor)
}
}
+#if defined(SUPPORT_IMAGE_MANIPULATION)
// Copy an image to a new image
Image ImageCopy(Image image)
{
@@ -1203,6 +1148,115 @@ void ImageFlipHorizontal(Image *image)
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(WARNING, "Compressed data formats can not be dithered");
+ return;
+ }
+
+ if ((rBpp+gBpp+bBpp+aBpp) > 16)
+ {
+ TraceLog(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(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(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
void ImageColorTint(Image *image, Color color)
{
@@ -1359,6 +1413,7 @@ void ImageColorBrightness(Image *image, int brightness)
image->data = processed.data;
}
+#endif // SUPPORT_IMAGE_MANIPULATION
// Generate GPU mipmaps for a texture
void GenTextureMipmaps(Texture2D *texture)
@@ -1547,6 +1602,7 @@ void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, V
// Module specific Functions Definition
//----------------------------------------------------------------------------------
+#if defined(SUPPORT_FILEFORMAT_DDS)
// Loading DDS image data (compressed or uncompressed)
static Image LoadDDS(const char *fileName)
{
@@ -1744,7 +1800,9 @@ static Image LoadDDS(const char *fileName)
return image;
}
+#endif
+#if defined(SUPPORT_FILEFORMAT_PKM)
// Loading PKM image data (ETC1/ETC2 compression)
// NOTE: KTX is the standard Khronos Group compression format (ETC1/ETC2, mipmaps)
// PKM is a much simpler file format used mainly to contain a single ETC1/ETC2 compressed image (no mipmaps)
@@ -1836,7 +1894,9 @@ static Image LoadPKM(const char *fileName)
return image;
}
+#endif
+#if defined(SUPPORT_FILEFORMAT_KTX)
// Load KTX compressed image data (ETC1/ETC2 compression)
static Image LoadKTX(const char *fileName)
{
@@ -1929,7 +1989,9 @@ static Image LoadKTX(const char *fileName)
return image;
}
+#endif
+#if defined(SUPPORT_FILEFORMAT_PVR)
// Loading PVR image data (uncompressed or PVRT compression)
// NOTE: PVR v2 not supported, use PVR v3 instead
static Image LoadPVR(const char *fileName)
@@ -2087,7 +2149,9 @@ static Image LoadPVR(const char *fileName)
return image;
}
+#endif
+#if defined(SUPPORT_FILEFORMAT_ASTC)
// Load ASTC compressed image data (ASTC compression)
static Image LoadASTC(const char *fileName)
{
@@ -2170,3 +2234,4 @@ static Image LoadASTC(const char *fileName)
return image;
}
+#endif \ No newline at end of file
diff --git a/src/utils.c b/src/utils.c
index 4d30cbc7..649fda4f 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -20,7 +20,7 @@
* Show TraceLog() DEBUG messages
*
* DEPENDENCIES:
-* stb_image_write - PNG writting functions
+* stb_image_write - BMP/PNG writting functions
*
*
* LICENSE: zlib/libpng
@@ -88,14 +88,15 @@ static int android_close(void *cookie);
//----------------------------------------------------------------------------------
// Module Functions Definition - Utilities
//----------------------------------------------------------------------------------
-// Outputs a trace log message
+
+// Output trace log messages
void TraceLog(int msgType, const char *text, ...)
{
-#if !defined(NO_TRACELOG)
+#if defined(SUPPORT_TRACELOG)
static char buffer[128];
int traceDebugMsgs = 1;
-#ifdef DO_NOT_TRACE_DEBUG_MSGS
+#if defined(SUPPORT_TRACELOG_DEBUG)
traceDebugMsgs = 0;
#endif
@@ -131,7 +132,7 @@ void TraceLog(int msgType, const char *text, ...)
if (msgType == ERROR) exit(1); // If ERROR message, exit program
-#endif // NO_TRACELOG
+#endif // SUPPORT_TRACELOG
}
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI)
@@ -153,6 +154,16 @@ void SavePNG(const char *fileName, unsigned char *imgData, int width, int height
#endif
#endif
+// Keep track of memory allocated
+// NOTE: mallocType defines the type of data allocated
+/*
+void RecordMalloc(int mallocType, int mallocSize, const char *msg)
+{
+ // TODO: Investigate how to record memory allocation data...
+ // Maybe creating my own malloc function...
+}
+*/
+
#if defined(PLATFORM_ANDROID)
// Initialize asset manager from android app
void InitAssetManager(AAssetManager *manager)
@@ -173,24 +184,6 @@ FILE *android_fopen(const char *fileName, const char *mode)
}
#endif
-// Keep track of memory allocated
-// NOTE: mallocType defines the type of data allocated
-/*
-void RecordMalloc(int mallocType, int mallocSize, const char *msg)
-{
- // TODO: Investigate how to record memory allocation data...
- // Maybe creating my own malloc function...
-}
-*/
-
-// Get the extension for a filename
-const char *GetExtension(const char *fileName)
-{
- const char *dot = strrchr(fileName, '.');
- if (!dot || dot == fileName) return "";
- return (dot + 1);
-}
-
//----------------------------------------------------------------------------------
// Module specific Functions Definition
//----------------------------------------------------------------------------------
diff --git a/src/utils.h b/src/utils.h
index 45ffcf81..2b4d838b 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -60,8 +60,7 @@ extern "C" { // Prevents name mangling of functions
//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
-void TraceLog(int msgType, const char *text, ...); // Outputs a trace log message
-const char *GetExtension(const char *fileName); // Returns extension of a filename
+void TraceLog(int msgType, const char *text, ...); // Outputs a trace log message
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI)
#if defined(SUPPORT_SAVE_BMP)
@@ -74,7 +73,7 @@ void SavePNG(const char *fileName, unsigned char *imgData, int width, int height
#if defined(PLATFORM_ANDROID)
void InitAssetManager(AAssetManager *manager); // Initialize asset manager from android app
-FILE *android_fopen(const char *fileName, const char *mode); // Replacement for fopen()
+FILE *android_fopen(const char *fileName, const char *mode); // Replacement for fopen()
#endif
#ifdef __cplusplus