mirror of
				https://github.com/raysan5/raylib.git
				synced 2025-10-26 12:27:01 +00:00 
			
		
		
		
	Remove unecessary spaces...
This commit is contained in:
		
							
								
								
									
										98
									
								
								src/audio.c
									
									
									
									
									
								
							
							
						
						
									
										98
									
								
								src/audio.c
									
									
									
									
									
								
							| @@ -231,9 +231,9 @@ Wave LoadWave(const char *fileName) | |||||||
|     else if (strcmp(GetExtension(fileName),"rres") == 0) |     else if (strcmp(GetExtension(fileName),"rres") == 0) | ||||||
|     { |     { | ||||||
|         RRESData rres = LoadResource(fileName); |         RRESData rres = LoadResource(fileName); | ||||||
|          |  | ||||||
|         // NOTE: Parameters for RRES_WAVE type are: sampleCount, sampleRate, sampleSize, channels |         // NOTE: Parameters for RRES_WAVE type are: sampleCount, sampleRate, sampleSize, channels | ||||||
|          |  | ||||||
|         if (rres.type == RRES_WAVE) wave = LoadWaveEx(rres.data, rres.param1, rres.param2, rres.param3, rres.param4); |         if (rres.type == RRES_WAVE) wave = LoadWaveEx(rres.data, rres.param1, rres.param2, rres.param3, rres.param4); | ||||||
|         else TraceLog(WARNING, "[%s] Resource file does not contain wave data", fileName); |         else TraceLog(WARNING, "[%s] Resource file does not contain wave data", fileName); | ||||||
|  |  | ||||||
| @@ -248,18 +248,18 @@ Wave LoadWave(const char *fileName) | |||||||
| Wave LoadWaveEx(void *data, int sampleCount, int sampleRate, int sampleSize, int channels) | Wave LoadWaveEx(void *data, int sampleCount, int sampleRate, int sampleSize, int channels) | ||||||
| { | { | ||||||
|     Wave wave; |     Wave wave; | ||||||
|      |  | ||||||
|     wave.data = data; |     wave.data = data; | ||||||
|     wave.sampleCount = sampleCount; |     wave.sampleCount = sampleCount; | ||||||
|     wave.sampleRate = sampleRate; |     wave.sampleRate = sampleRate; | ||||||
|     wave.sampleSize = sampleSize; |     wave.sampleSize = sampleSize; | ||||||
|     wave.channels = channels; |     wave.channels = channels; | ||||||
|      |  | ||||||
|     // NOTE: Copy wave data to work with, user is responsible of input data to free |     // NOTE: Copy wave data to work with, user is responsible of input data to free | ||||||
|     Wave cwave = WaveCopy(wave); |     Wave cwave = WaveCopy(wave); | ||||||
|      |  | ||||||
|     WaveFormat(&cwave, sampleRate, sampleSize, channels); |     WaveFormat(&cwave, sampleRate, sampleSize, channels); | ||||||
|      |  | ||||||
|     return cwave; |     return cwave; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -268,9 +268,9 @@ Wave LoadWaveEx(void *data, int sampleCount, int sampleRate, int sampleSize, int | |||||||
| Sound LoadSound(const char *fileName) | Sound LoadSound(const char *fileName) | ||||||
| { | { | ||||||
|     Wave wave = LoadWave(fileName); |     Wave wave = LoadWave(fileName); | ||||||
|      |  | ||||||
|     Sound sound = LoadSoundFromWave(wave); |     Sound sound = LoadSoundFromWave(wave); | ||||||
|      |  | ||||||
|     UnloadWave(wave);       // Sound is loaded, we can unload wave |     UnloadWave(wave);       // Sound is loaded, we can unload wave | ||||||
|  |  | ||||||
|     return sound; |     return sound; | ||||||
| @@ -354,7 +354,7 @@ void UnloadWave(Wave wave) | |||||||
| void UnloadSound(Sound sound) | void UnloadSound(Sound sound) | ||||||
| { | { | ||||||
|     alSourceStop(sound.source); |     alSourceStop(sound.source); | ||||||
|      |  | ||||||
|     alDeleteSources(1, &sound.source); |     alDeleteSources(1, &sound.source); | ||||||
|     alDeleteBuffers(1, &sound.buffer); |     alDeleteBuffers(1, &sound.buffer); | ||||||
|  |  | ||||||
| @@ -369,13 +369,13 @@ void UpdateSound(Sound sound, const void *data, int numSamples) | |||||||
|     alGetBufferi(sound.buffer, AL_FREQUENCY, &sampleRate); |     alGetBufferi(sound.buffer, AL_FREQUENCY, &sampleRate); | ||||||
|     alGetBufferi(sound.buffer, AL_BITS, &sampleSize);           // It could also be retrieved from sound.format |     alGetBufferi(sound.buffer, AL_BITS, &sampleSize);           // It could also be retrieved from sound.format | ||||||
|     alGetBufferi(sound.buffer, AL_CHANNELS, &channels);         // It could also be retrieved from sound.format |     alGetBufferi(sound.buffer, AL_CHANNELS, &channels);         // It could also be retrieved from sound.format | ||||||
|      |  | ||||||
|     TraceLog(DEBUG, "UpdateSound() : AL_FREQUENCY: %i", sampleRate); |     TraceLog(DEBUG, "UpdateSound() : AL_FREQUENCY: %i", sampleRate); | ||||||
|     TraceLog(DEBUG, "UpdateSound() : AL_BITS: %i", sampleSize); |     TraceLog(DEBUG, "UpdateSound() : AL_BITS: %i", sampleSize); | ||||||
|     TraceLog(DEBUG, "UpdateSound() : AL_CHANNELS: %i", channels); |     TraceLog(DEBUG, "UpdateSound() : AL_CHANNELS: %i", channels); | ||||||
|  |  | ||||||
|     unsigned int dataSize = numSamples*channels*sampleSize/8;   // Size of data in bytes |     unsigned int dataSize = numSamples*channels*sampleSize/8;   // Size of data in bytes | ||||||
|      |  | ||||||
|     alSourceStop(sound.source);                 // Stop sound |     alSourceStop(sound.source);                 // Stop sound | ||||||
|     alSourcei(sound.source, AL_BUFFER, 0);      // Unbind buffer from sound to update |     alSourcei(sound.source, AL_BUFFER, 0);      // Unbind buffer from sound to update | ||||||
|     //alDeleteBuffers(1, &sound.buffer);          // Delete current buffer data |     //alDeleteBuffers(1, &sound.buffer);          // Delete current buffer data | ||||||
| @@ -463,18 +463,18 @@ void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels) | |||||||
|     if (wave->sampleRate != sampleRate) |     if (wave->sampleRate != sampleRate) | ||||||
|     { |     { | ||||||
|         // TODO: Resample wave data (upsampling or downsampling) |         // TODO: Resample wave data (upsampling or downsampling) | ||||||
|         // NOTE 1: To downsample, you have to drop samples or average them.  |         // NOTE 1: To downsample, you have to drop samples or average them. | ||||||
|         // NOTE 2: To upsample, you have to interpolate new samples. |         // NOTE 2: To upsample, you have to interpolate new samples. | ||||||
|          |  | ||||||
|         wave->sampleRate = sampleRate; |         wave->sampleRate = sampleRate; | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     // Format sample size |     // Format sample size | ||||||
|     // NOTE: Only supported 8 bit <--> 16 bit <--> 32 bit |     // NOTE: Only supported 8 bit <--> 16 bit <--> 32 bit | ||||||
|     if (wave->sampleSize != sampleSize) |     if (wave->sampleSize != sampleSize) | ||||||
|     { |     { | ||||||
|         void *data = malloc(wave->sampleCount*wave->channels*sampleSize/8); |         void *data = malloc(wave->sampleCount*wave->channels*sampleSize/8); | ||||||
|          |  | ||||||
|         for (int i = 0; i < wave->sampleCount; i++) |         for (int i = 0; i < wave->sampleCount; i++) | ||||||
|         { |         { | ||||||
|             for (int j = 0; j < wave->channels; j++) |             for (int j = 0; j < wave->channels; j++) | ||||||
| @@ -484,30 +484,30 @@ void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels) | |||||||
|                     if (wave->sampleSize == 16) ((unsigned char *)data)[wave->channels*i + j] = (unsigned char)(((float)(((short *)wave->data)[wave->channels*i + j])/32767.0f)*256); |                     if (wave->sampleSize == 16) ((unsigned char *)data)[wave->channels*i + j] = (unsigned char)(((float)(((short *)wave->data)[wave->channels*i + j])/32767.0f)*256); | ||||||
|                     else if (wave->sampleSize == 32) ((unsigned char *)data)[wave->channels*i + j] = (unsigned char)(((float *)wave->data)[wave->channels*i + j]*127.0f + 127); |                     else if (wave->sampleSize == 32) ((unsigned char *)data)[wave->channels*i + j] = (unsigned char)(((float *)wave->data)[wave->channels*i + j]*127.0f + 127); | ||||||
|                 } |                 } | ||||||
|                 else if (sampleSize == 16)  |                 else if (sampleSize == 16) | ||||||
|                 { |                 { | ||||||
|                     if (wave->sampleSize == 8) ((short *)data)[wave->channels*i + j] = (short)(((float)(((unsigned char *)wave->data)[wave->channels*i + j] - 127)/256.0f)*32767); |                     if (wave->sampleSize == 8) ((short *)data)[wave->channels*i + j] = (short)(((float)(((unsigned char *)wave->data)[wave->channels*i + j] - 127)/256.0f)*32767); | ||||||
|                     else if (wave->sampleSize == 32) ((short *)data)[wave->channels*i + j] = (short)((((float *)wave->data)[wave->channels*i + j])*32767); |                     else if (wave->sampleSize == 32) ((short *)data)[wave->channels*i + j] = (short)((((float *)wave->data)[wave->channels*i + j])*32767); | ||||||
|                 } |                 } | ||||||
|                 else if (sampleSize == 32)  |                 else if (sampleSize == 32) | ||||||
|                 { |                 { | ||||||
|                     if (wave->sampleSize == 8) ((float *)data)[wave->channels*i + j] = (float)(((unsigned char *)wave->data)[wave->channels*i + j] - 127)/256.0f; |                     if (wave->sampleSize == 8) ((float *)data)[wave->channels*i + j] = (float)(((unsigned char *)wave->data)[wave->channels*i + j] - 127)/256.0f; | ||||||
|                     else if (wave->sampleSize == 16) ((float *)data)[wave->channels*i + j] = (float)(((short *)wave->data)[wave->channels*i + j])/32767.0f; |                     else if (wave->sampleSize == 16) ((float *)data)[wave->channels*i + j] = (float)(((short *)wave->data)[wave->channels*i + j])/32767.0f; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |  | ||||||
|         wave->sampleSize = sampleSize; |         wave->sampleSize = sampleSize; | ||||||
|         free(wave->data); |         free(wave->data); | ||||||
|         wave->data = data; |         wave->data = data; | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     // Format channels (interlaced mode) |     // Format channels (interlaced mode) | ||||||
|     // NOTE: Only supported mono <--> stereo |     // NOTE: Only supported mono <--> stereo | ||||||
|     if (wave->channels != channels) |     if (wave->channels != channels) | ||||||
|     { |     { | ||||||
|         void *data = malloc(wave->sampleCount*channels*wave->sampleSize/8); |         void *data = malloc(wave->sampleCount*channels*wave->sampleSize/8); | ||||||
|          |  | ||||||
|         if ((wave->channels == 1) && (channels == 2))       // mono ---> stereo (duplicate mono information) |         if ((wave->channels == 1) && (channels == 2))       // mono ---> stereo (duplicate mono information) | ||||||
|         { |         { | ||||||
|             for (int i = 0; i < wave->sampleCount; i++) |             for (int i = 0; i < wave->sampleCount; i++) | ||||||
| @@ -529,7 +529,7 @@ void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels) | |||||||
|                 else if (wave->sampleSize == 32) ((float *)data)[i] = (((float *)wave->data)[j] + ((float *)wave->data)[j + 1])/2.0f; |                 else if (wave->sampleSize == 32) ((float *)data)[i] = (((float *)wave->data)[j] + ((float *)wave->data)[j + 1])/2.0f; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |  | ||||||
|         // TODO: Add/remove additional interlaced channels |         // TODO: Add/remove additional interlaced channels | ||||||
|  |  | ||||||
|         wave->channels = channels; |         wave->channels = channels; | ||||||
| @@ -563,15 +563,15 @@ Wave WaveCopy(Wave wave) | |||||||
| // NOTE: Security check in case of out-of-range | // NOTE: Security check in case of out-of-range | ||||||
| void WaveCrop(Wave *wave, int initSample, int finalSample) | void WaveCrop(Wave *wave, int initSample, int finalSample) | ||||||
| { | { | ||||||
|     if ((initSample >= 0) && (initSample < finalSample) &&  |     if ((initSample >= 0) && (initSample < finalSample) && | ||||||
|         (finalSample > 0) && (finalSample < wave->sampleCount)) |         (finalSample > 0) && (finalSample < wave->sampleCount)) | ||||||
|     { |     { | ||||||
|         int sampleCount = finalSample - initSample; |         int sampleCount = finalSample - initSample; | ||||||
|          |  | ||||||
|         void *data = malloc(sampleCount*wave->channels*wave->sampleSize/8); |         void *data = malloc(sampleCount*wave->channels*wave->sampleSize/8); | ||||||
|          |  | ||||||
|         memcpy(data, wave->data + (initSample*wave->channels*wave->sampleSize/8), sampleCount*wave->channels*wave->sampleSize/8); |         memcpy(data, wave->data + (initSample*wave->channels*wave->sampleSize/8), sampleCount*wave->channels*wave->sampleSize/8); | ||||||
|          |  | ||||||
|         free(wave->data); |         free(wave->data); | ||||||
|         wave->data = data; |         wave->data = data; | ||||||
|     } |     } | ||||||
| @@ -583,7 +583,7 @@ void WaveCrop(Wave *wave, int initSample, int finalSample) | |||||||
| float *GetWaveData(Wave wave) | float *GetWaveData(Wave wave) | ||||||
| { | { | ||||||
|     float *samples = (float *)malloc(wave.sampleCount*wave.channels*sizeof(float)); |     float *samples = (float *)malloc(wave.sampleCount*wave.channels*sizeof(float)); | ||||||
|      |  | ||||||
|     for (int i = 0; i < wave.sampleCount; i++) |     for (int i = 0; i < wave.sampleCount; i++) | ||||||
|     { |     { | ||||||
|         for (int j = 0; j < wave.channels; j++) |         for (int j = 0; j < wave.channels; j++) | ||||||
| @@ -593,7 +593,7 @@ float *GetWaveData(Wave wave) | |||||||
|             else if (wave.sampleSize == 32) samples[wave.channels*i + j] = ((float *)wave.data)[wave.channels*i + j]; |             else if (wave.sampleSize == 32) samples[wave.channels*i + j] = ((float *)wave.data)[wave.channels*i + j]; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     return samples; |     return samples; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -632,7 +632,7 @@ Music LoadMusicStream(const char *fileName) | |||||||
|     else if (strcmp(GetExtension(fileName), "flac") == 0) |     else if (strcmp(GetExtension(fileName), "flac") == 0) | ||||||
|     { |     { | ||||||
|         music->ctxFlac = drflac_open_file(fileName); |         music->ctxFlac = drflac_open_file(fileName); | ||||||
|          |  | ||||||
|         if (music->ctxFlac == NULL) TraceLog(WARNING, "[%s] FLAC audio file could not be opened", fileName); |         if (music->ctxFlac == NULL) TraceLog(WARNING, "[%s] FLAC audio file could not be opened", fileName); | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
| @@ -641,7 +641,7 @@ Music LoadMusicStream(const char *fileName) | |||||||
|             music->samplesLeft = music->totalSamples; |             music->samplesLeft = music->totalSamples; | ||||||
|             music->ctxType = MUSIC_AUDIO_FLAC; |             music->ctxType = MUSIC_AUDIO_FLAC; | ||||||
|             music->loop = true;                  // We loop by default |             music->loop = true;                  // We loop by default | ||||||
|              |  | ||||||
|             TraceLog(DEBUG, "[%s] FLAC total samples: %i", fileName, music->totalSamples); |             TraceLog(DEBUG, "[%s] FLAC total samples: %i", fileName, music->totalSamples); | ||||||
|             TraceLog(DEBUG, "[%s] FLAC sample rate: %i", fileName, music->ctxFlac->sampleRate); |             TraceLog(DEBUG, "[%s] FLAC sample rate: %i", fileName, music->ctxFlac->sampleRate); | ||||||
|             TraceLog(DEBUG, "[%s] FLAC bits per sample: %i", fileName, music->ctxFlac->bitsPerSample); |             TraceLog(DEBUG, "[%s] FLAC bits per sample: %i", fileName, music->ctxFlac->bitsPerSample); | ||||||
| @@ -728,7 +728,7 @@ void ResumeMusicStream(Music music) | |||||||
| void StopMusicStream(Music music) | void StopMusicStream(Music music) | ||||||
| { | { | ||||||
|     alSourceStop(music->stream.source); |     alSourceStop(music->stream.source); | ||||||
|      |  | ||||||
|     switch (music->ctxType) |     switch (music->ctxType) | ||||||
|     { |     { | ||||||
|         case MUSIC_AUDIO_OGG: stb_vorbis_seek_start(music->ctxOgg); break; |         case MUSIC_AUDIO_OGG: stb_vorbis_seek_start(music->ctxOgg); break; | ||||||
| @@ -736,7 +736,7 @@ void StopMusicStream(Music music) | |||||||
|         case MUSIC_MODULE_MOD: jar_mod_seek_start(&music->ctxMod); break; |         case MUSIC_MODULE_MOD: jar_mod_seek_start(&music->ctxMod); break; | ||||||
|         default: break; |         default: break; | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     music->samplesLeft = music->totalSamples; |     music->samplesLeft = music->totalSamples; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -745,14 +745,14 @@ void UpdateMusicStream(Music music) | |||||||
| { | { | ||||||
|     ALenum state; |     ALenum state; | ||||||
|     ALint processed = 0; |     ALint processed = 0; | ||||||
|      |  | ||||||
|     alGetSourcei(music->stream.source, AL_SOURCE_STATE, &state);          // Get music stream state |     alGetSourcei(music->stream.source, AL_SOURCE_STATE, &state);          // Get music stream state | ||||||
|     alGetSourcei(music->stream.source, AL_BUFFERS_PROCESSED, &processed); // Get processed buffers |     alGetSourcei(music->stream.source, AL_BUFFERS_PROCESSED, &processed); // Get processed buffers | ||||||
|  |  | ||||||
|     if (processed > 0) |     if (processed > 0) | ||||||
|     { |     { | ||||||
|         bool active = true; |         bool active = true; | ||||||
|          |  | ||||||
|         // NOTE: Using dynamic allocation because it could require more than 16KB |         // NOTE: Using dynamic allocation because it could require more than 16KB | ||||||
|         void *pcm = calloc(AUDIO_BUFFER_SIZE*music->stream.channels*music->stream.sampleSize/8, 1); |         void *pcm = calloc(AUDIO_BUFFER_SIZE*music->stream.channels*music->stream.sampleSize/8, 1); | ||||||
|  |  | ||||||
| @@ -764,7 +764,7 @@ void UpdateMusicStream(Music music) | |||||||
|         { |         { | ||||||
|             if (music->samplesLeft >= AUDIO_BUFFER_SIZE) numSamples = AUDIO_BUFFER_SIZE; |             if (music->samplesLeft >= AUDIO_BUFFER_SIZE) numSamples = AUDIO_BUFFER_SIZE; | ||||||
|             else numSamples = music->samplesLeft; |             else numSamples = music->samplesLeft; | ||||||
|                      |  | ||||||
|             // TODO: Really don't like ctxType thingy... |             // TODO: Really don't like ctxType thingy... | ||||||
|             switch (music->ctxType) |             switch (music->ctxType) | ||||||
|             { |             { | ||||||
| @@ -784,7 +784,7 @@ void UpdateMusicStream(Music music) | |||||||
|                 case MUSIC_MODULE_MOD: jar_mod_fillbuffer(&music->ctxMod, pcm, numSamples, 0); break; |                 case MUSIC_MODULE_MOD: jar_mod_fillbuffer(&music->ctxMod, pcm, numSamples, 0); break; | ||||||
|                 default: break; |                 default: break; | ||||||
|             } |             } | ||||||
|              |  | ||||||
|             UpdateAudioStream(music->stream, pcm, numSamples); |             UpdateAudioStream(music->stream, pcm, numSamples); | ||||||
|             music->samplesLeft -= numSamples; |             music->samplesLeft -= numSamples; | ||||||
|  |  | ||||||
| @@ -794,12 +794,12 @@ void UpdateMusicStream(Music music) | |||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |  | ||||||
|         // This error is registered when UpdateAudioStream() fails |         // This error is registered when UpdateAudioStream() fails | ||||||
|         if (alGetError() == AL_INVALID_VALUE) TraceLog(WARNING, "OpenAL: Error buffering data..."); |         if (alGetError() == AL_INVALID_VALUE) TraceLog(WARNING, "OpenAL: Error buffering data..."); | ||||||
|  |  | ||||||
|         // Reset audio stream for looping |         // Reset audio stream for looping | ||||||
|         if (!active)  |         if (!active) | ||||||
|         { |         { | ||||||
|             StopMusicStream(music);        // Stop music (and reset) |             StopMusicStream(music);        // Stop music (and reset) | ||||||
|             if (music->loop) PlayMusicStream(music);    // Play again |             if (music->loop) PlayMusicStream(music);    // Play again | ||||||
| @@ -810,7 +810,7 @@ void UpdateMusicStream(Music music) | |||||||
|             // just make sure to play again on window restore |             // just make sure to play again on window restore | ||||||
|             if (state != AL_PLAYING) PlayMusicStream(music); |             if (state != AL_PLAYING) PlayMusicStream(music); | ||||||
|         } |         } | ||||||
|          |  | ||||||
|         free(pcm); |         free(pcm); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -866,7 +866,7 @@ AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, un | |||||||
|  |  | ||||||
|     stream.sampleRate = sampleRate; |     stream.sampleRate = sampleRate; | ||||||
|     stream.sampleSize = sampleSize; |     stream.sampleSize = sampleSize; | ||||||
|      |  | ||||||
|     // Only mono and stereo channels are supported, more channels require AL_EXT_MCFORMATS extension |     // Only mono and stereo channels are supported, more channels require AL_EXT_MCFORMATS extension | ||||||
|     if ((channels > 0) && (channels < 3)) stream.channels = channels; |     if ((channels > 0) && (channels < 3)) stream.channels = channels; | ||||||
|     else |     else | ||||||
| @@ -910,12 +910,12 @@ AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, un | |||||||
|     // Initialize buffer with zeros by default |     // Initialize buffer with zeros by default | ||||||
|     // NOTE: Using dynamic allocation because it requires more than 16KB |     // NOTE: Using dynamic allocation because it requires more than 16KB | ||||||
|     void *pcm = calloc(AUDIO_BUFFER_SIZE*stream.sampleSize/8*stream.channels, 1); |     void *pcm = calloc(AUDIO_BUFFER_SIZE*stream.sampleSize/8*stream.channels, 1); | ||||||
|      |  | ||||||
|     for (int i = 0; i < MAX_STREAM_BUFFERS; i++) |     for (int i = 0; i < MAX_STREAM_BUFFERS; i++) | ||||||
|     { |     { | ||||||
|         alBufferData(stream.buffers[i], stream.format, pcm, AUDIO_BUFFER_SIZE*stream.sampleSize/8*stream.channels, stream.sampleRate); |         alBufferData(stream.buffers[i], stream.format, pcm, AUDIO_BUFFER_SIZE*stream.sampleSize/8*stream.channels, stream.sampleRate); | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     free(pcm); |     free(pcm); | ||||||
|  |  | ||||||
|     alSourceQueueBuffers(stream.source, MAX_STREAM_BUFFERS, stream.buffers); |     alSourceQueueBuffers(stream.source, MAX_STREAM_BUFFERS, stream.buffers); | ||||||
| @@ -1095,7 +1095,7 @@ static Wave LoadWAV(const char *fileName) | |||||||
|                     wave.sampleRate = wavFormat.sampleRate; |                     wave.sampleRate = wavFormat.sampleRate; | ||||||
|                     wave.sampleSize = wavFormat.bitsPerSample; |                     wave.sampleSize = wavFormat.bitsPerSample; | ||||||
|                     wave.channels = wavFormat.numChannels; |                     wave.channels = wavFormat.numChannels; | ||||||
|                      |  | ||||||
|                     // NOTE: Only support 8 bit, 16 bit and 32 bit sample sizes |                     // NOTE: Only support 8 bit, 16 bit and 32 bit sample sizes | ||||||
|                     if ((wave.sampleSize != 8) && (wave.sampleSize != 16) && (wave.sampleSize != 32)) |                     if ((wave.sampleSize != 8) && (wave.sampleSize != 16) && (wave.sampleSize != 32)) | ||||||
|                     { |                     { | ||||||
| @@ -1104,16 +1104,16 @@ static Wave LoadWAV(const char *fileName) | |||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     // NOTE: Only support up to 2 channels (mono, stereo) |                     // NOTE: Only support up to 2 channels (mono, stereo) | ||||||
|                     if (wave.channels > 2)  |                     if (wave.channels > 2) | ||||||
|                     { |                     { | ||||||
|                         WaveFormat(&wave, wave.sampleRate, wave.sampleSize, 2); |                         WaveFormat(&wave, wave.sampleRate, wave.sampleSize, 2); | ||||||
|                         TraceLog(WARNING, "[%s] WAV channels number (%i) not supported, converted to 2 channels", fileName, wave.channels); |                         TraceLog(WARNING, "[%s] WAV channels number (%i) not supported, converted to 2 channels", fileName, wave.channels); | ||||||
|                     } |                     } | ||||||
|                      |  | ||||||
|                     // NOTE: subChunkSize comes in bytes, we need to translate it to number of samples |                     // NOTE: subChunkSize comes in bytes, we need to translate it to number of samples | ||||||
|                     wave.sampleCount = (wavData.subChunkSize/(wave.sampleSize/8))/wave.channels; |                     wave.sampleCount = (wavData.subChunkSize/(wave.sampleSize/8))/wave.channels; | ||||||
|  |  | ||||||
|                     TraceLog(INFO, "[%s] WAV file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo");              |                     TraceLog(INFO, "[%s] WAV file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo"); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @@ -1145,7 +1145,7 @@ static Wave LoadOGG(const char *fileName) | |||||||
|         wave.sampleSize = 16;                   // 16 bit per sample (short) |         wave.sampleSize = 16;                   // 16 bit per sample (short) | ||||||
|         wave.channels = info.channels; |         wave.channels = info.channels; | ||||||
|         wave.sampleCount = (int)stb_vorbis_stream_length_in_samples(oggFile); |         wave.sampleCount = (int)stb_vorbis_stream_length_in_samples(oggFile); | ||||||
|          |  | ||||||
|         float totalSeconds = stb_vorbis_stream_length_in_seconds(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 lenght is larger than 10 seconds (%f), that's a big file in memory, consider music streaming", fileName, totalSeconds); | ||||||
|  |  | ||||||
| @@ -1173,16 +1173,16 @@ static Wave LoadFLAC(const char *fileName) | |||||||
|     // Decode an entire FLAC file in one go |     // Decode an entire FLAC file in one go | ||||||
|     uint64_t totalSampleCount; |     uint64_t totalSampleCount; | ||||||
|     wave.data = drflac_open_and_decode_file_s16(fileName, &wave.channels, &wave.sampleRate, &totalSampleCount); |     wave.data = drflac_open_and_decode_file_s16(fileName, &wave.channels, &wave.sampleRate, &totalSampleCount); | ||||||
|      |  | ||||||
|     wave.sampleCount = (int)totalSampleCount/wave.channels; |     wave.sampleCount = (int)totalSampleCount/wave.channels; | ||||||
|     wave.sampleSize = 16; |     wave.sampleSize = 16; | ||||||
|      |  | ||||||
|     // NOTE: Only support up to 2 channels (mono, stereo) |     // NOTE: Only support up to 2 channels (mono, stereo) | ||||||
|     if (wave.channels > 2) TraceLog(WARNING, "[%s] FLAC channels number (%i) not supported", fileName, wave.channels); |     if (wave.channels > 2) TraceLog(WARNING, "[%s] FLAC channels number (%i) not supported", fileName, wave.channels); | ||||||
|  |  | ||||||
|     if (wave.data == NULL) TraceLog(WARNING, "[%s] FLAC data could not be loaded", fileName); |     if (wave.data == NULL) TraceLog(WARNING, "[%s] FLAC data could not be loaded", fileName); | ||||||
|     else TraceLog(INFO, "[%s] FLAC file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo"); |     else TraceLog(INFO, "[%s] FLAC file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo"); | ||||||
|      |  | ||||||
|     return wave; |     return wave; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										100
									
								
								src/core.c
									
									
									
									
									
								
							
							
						
						
									
										100
									
								
								src/core.c
									
									
									
									
									
								
							| @@ -9,7 +9,7 @@ | |||||||
| *   External libs: | *   External libs: | ||||||
| *       GLFW3    - Manage graphic device, OpenGL context and inputs on PLATFORM_DESKTOP (Windows, Linux, OSX) | *       GLFW3    - Manage graphic device, OpenGL context and inputs on PLATFORM_DESKTOP (Windows, Linux, OSX) | ||||||
| *       raymath  - 3D math functionality (Vector3, Matrix, Quaternion) | *       raymath  - 3D math functionality (Vector3, Matrix, Quaternion) | ||||||
| *       camera   - Multiple 3D camera modes (free, orbital, 1st person, 3rd person)  | *       camera   - Multiple 3D camera modes (free, orbital, 1st person, 3rd person) | ||||||
| *       gestures - Gestures system for touch-ready devices (or simulated from mouse inputs) | *       gestures - Gestures system for touch-ready devices (or simulated from mouse inputs) | ||||||
| * | * | ||||||
| *   Module Configuration Flags: | *   Module Configuration Flags: | ||||||
| @@ -103,7 +103,7 @@ | |||||||
|     #include <linux/kd.h>       // Linux: KDSKBMODE, K_MEDIUMRAM constants definition |     #include <linux/kd.h>       // Linux: KDSKBMODE, K_MEDIUMRAM constants definition | ||||||
|     #include <linux/input.h>    // Linux: Keycodes constants definition (KEY_A, ...) |     #include <linux/input.h>    // Linux: Keycodes constants definition (KEY_A, ...) | ||||||
|     #include <linux/joystick.h> // Linux: Joystick support library |     #include <linux/joystick.h> // Linux: Joystick support library | ||||||
|      |  | ||||||
|     #include "bcm_host.h"       // Raspberry Pi VideoCore IV access functions |     #include "bcm_host.h"       // Raspberry Pi VideoCore IV access functions | ||||||
|  |  | ||||||
|     #include "EGL/egl.h"        // Khronos EGL library - Native platform display device control functions |     #include "EGL/egl.h"        // Khronos EGL library - Native platform display device control functions | ||||||
| @@ -488,9 +488,9 @@ void CloseWindow(void) | |||||||
|     // Wait for mouse and gamepad threads to finish before closing |     // Wait for mouse and gamepad threads to finish before closing | ||||||
|     // NOTE: Those threads should already have finished at this point |     // NOTE: Those threads should already have finished at this point | ||||||
|     // because they are controlled by windowShouldClose variable |     // because they are controlled by windowShouldClose variable | ||||||
|      |  | ||||||
|     windowShouldClose = true;   // Added to force threads to exit when the close window is called |     windowShouldClose = true;   // Added to force threads to exit when the close window is called | ||||||
|      |  | ||||||
|     pthread_join(mouseThreadId, NULL); |     pthread_join(mouseThreadId, NULL); | ||||||
|     pthread_join(touchThreadId, NULL); |     pthread_join(touchThreadId, NULL); | ||||||
|     pthread_join(gamepadThreadId, NULL); |     pthread_join(gamepadThreadId, NULL); | ||||||
| @@ -649,14 +649,14 @@ void EndDrawing(void) | |||||||
|     frameTime = updateTime + drawTime; |     frameTime = updateTime + drawTime; | ||||||
|  |  | ||||||
|     // Wait for some milliseconds... |     // Wait for some milliseconds... | ||||||
|     if (frameTime < targetTime)  |     if (frameTime < targetTime) | ||||||
|     { |     { | ||||||
|         Wait((int)((targetTime - frameTime)*1000)); |         Wait((int)((targetTime - frameTime)*1000)); | ||||||
|      |  | ||||||
|         currentTime = GetTime(); |         currentTime = GetTime(); | ||||||
|         double extraTime = currentTime - previousTime; |         double extraTime = currentTime - previousTime; | ||||||
|         previousTime = currentTime; |         previousTime = currentTime; | ||||||
|          |  | ||||||
|         frameTime = updateTime + drawTime + extraTime; |         frameTime = updateTime + drawTime + extraTime; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -1147,7 +1147,7 @@ bool IsKeyDown(int key) | |||||||
| bool IsKeyReleased(int key) | bool IsKeyReleased(int key) | ||||||
| { | { | ||||||
|     bool released = false; |     bool released = false; | ||||||
|      |  | ||||||
|     if ((currentKeyState[key] != previousKeyState[key]) && (currentKeyState[key] == 0)) released = true; |     if ((currentKeyState[key] != previousKeyState[key]) && (currentKeyState[key] == 0)) released = true; | ||||||
|     else released = false; |     else released = false; | ||||||
|  |  | ||||||
| @@ -1182,7 +1182,7 @@ void SetExitKey(int key) | |||||||
| bool IsGamepadAvailable(int gamepad) | bool IsGamepadAvailable(int gamepad) | ||||||
| { | { | ||||||
|     bool result = false; |     bool result = false; | ||||||
|      |  | ||||||
| #if !defined(PLATFORM_ANDROID) | #if !defined(PLATFORM_ANDROID) | ||||||
|     if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad]) result = true; |     if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad]) result = true; | ||||||
| #endif | #endif | ||||||
| @@ -1196,7 +1196,7 @@ bool IsGamepadName(int gamepad, const char *name) | |||||||
|     bool result = false; |     bool result = false; | ||||||
|  |  | ||||||
| #if !defined(PLATFORM_ANDROID) | #if !defined(PLATFORM_ANDROID) | ||||||
|     const char *gamepadName = NULL;  |     const char *gamepadName = NULL; | ||||||
|  |  | ||||||
|     if (gamepadReady[gamepad]) gamepadName = GetGamepadName(gamepad); |     if (gamepadReady[gamepad]) gamepadName = GetGamepadName(gamepad); | ||||||
|     if ((name != NULL) && (gamepadName != NULL)) result = (strcmp(name, gamepadName) == 0); |     if ((name != NULL) && (gamepadName != NULL)) result = (strcmp(name, gamepadName) == 0); | ||||||
| @@ -1235,7 +1235,7 @@ int GetGamepadAxisCount(int gamepad) | |||||||
| float GetGamepadAxisMovement(int gamepad, int axis) | float GetGamepadAxisMovement(int gamepad, int axis) | ||||||
| { | { | ||||||
|     float value = 0; |     float value = 0; | ||||||
|      |  | ||||||
| #if !defined(PLATFORM_ANDROID) | #if !defined(PLATFORM_ANDROID) | ||||||
|     if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (axis < MAX_GAMEPAD_AXIS)) value = gamepadAxisState[gamepad][axis]; |     if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (axis < MAX_GAMEPAD_AXIS)) value = gamepadAxisState[gamepad][axis]; | ||||||
| #endif | #endif | ||||||
| @@ -1249,8 +1249,8 @@ bool IsGamepadButtonPressed(int gamepad, int button) | |||||||
|     bool pressed = false; |     bool pressed = false; | ||||||
|  |  | ||||||
| #if !defined(PLATFORM_ANDROID) | #if !defined(PLATFORM_ANDROID) | ||||||
|     if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (button < MAX_GAMEPAD_BUTTONS) &&  |     if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (button < MAX_GAMEPAD_BUTTONS) && | ||||||
|         (currentGamepadState[gamepad][button] != previousGamepadState[gamepad][button]) &&  |         (currentGamepadState[gamepad][button] != previousGamepadState[gamepad][button]) && | ||||||
|         (currentGamepadState[gamepad][button] == 1)) pressed = true; |         (currentGamepadState[gamepad][button] == 1)) pressed = true; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| @@ -1274,10 +1274,10 @@ bool IsGamepadButtonDown(int gamepad, int button) | |||||||
| bool IsGamepadButtonReleased(int gamepad, int button) | bool IsGamepadButtonReleased(int gamepad, int button) | ||||||
| { | { | ||||||
|     bool released = false; |     bool released = false; | ||||||
|      |  | ||||||
| #if !defined(PLATFORM_ANDROID) | #if !defined(PLATFORM_ANDROID) | ||||||
|     if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (button < MAX_GAMEPAD_BUTTONS) &&  |     if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (button < MAX_GAMEPAD_BUTTONS) && | ||||||
|         (currentGamepadState[gamepad][button] != previousGamepadState[gamepad][button]) &&  |         (currentGamepadState[gamepad][button] != previousGamepadState[gamepad][button]) && | ||||||
|         (currentGamepadState[gamepad][button] == 0)) released = true; |         (currentGamepadState[gamepad][button] == 0)) released = true; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| @@ -1290,7 +1290,7 @@ bool IsGamepadButtonUp(int gamepad, int button) | |||||||
|     bool result = false; |     bool result = false; | ||||||
|  |  | ||||||
| #if !defined(PLATFORM_ANDROID) | #if !defined(PLATFORM_ANDROID) | ||||||
|     if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (button < MAX_GAMEPAD_BUTTONS) &&  |     if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (button < MAX_GAMEPAD_BUTTONS) && | ||||||
|         (currentGamepadState[gamepad][button] == 0)) result = true; |         (currentGamepadState[gamepad][button] == 0)) result = true; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| @@ -1503,7 +1503,7 @@ static void InitGraphicsDevice(int width, int height) | |||||||
|         glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);    // Resizable window |         glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);    // Resizable window | ||||||
|     } |     } | ||||||
|     else glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);  // Avoid window being resizable |     else glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);  // Avoid window being resizable | ||||||
|      |  | ||||||
|     //glfwWindowHint(GLFW_DECORATED, GL_TRUE);      // Border and buttons on Window |     //glfwWindowHint(GLFW_DECORATED, GL_TRUE);      // Border and buttons on Window | ||||||
|     //glfwWindowHint(GLFW_RED_BITS, 8);             // Framebuffer red color component bits |     //glfwWindowHint(GLFW_RED_BITS, 8);             // Framebuffer red color component bits | ||||||
|     //glfwWindowHint(GLFW_DEPTH_BITS, 16);          // Depthbuffer bits (24 by default) |     //glfwWindowHint(GLFW_DEPTH_BITS, 16);          // Depthbuffer bits (24 by default) | ||||||
| @@ -1941,7 +1941,7 @@ static double GetTime(void) | |||||||
| // Wait for some milliseconds (stop program execution) | // Wait for some milliseconds (stop program execution) | ||||||
| static void Wait(int ms) | static void Wait(int ms) | ||||||
| { | { | ||||||
| #if defined _WIN32     | #if defined _WIN32 | ||||||
|     Sleep(ms); |     Sleep(ms); | ||||||
| #elif defined __linux || defined(PLATFORM_WEB) | #elif defined __linux || defined(PLATFORM_WEB) | ||||||
|     struct timespec req = { 0 }; |     struct timespec req = { 0 }; | ||||||
| @@ -1949,7 +1949,7 @@ static void Wait(int ms) | |||||||
|     ms -= (sec*1000); |     ms -= (sec*1000); | ||||||
|     req.tv_sec=sec; |     req.tv_sec=sec; | ||||||
|     req.tv_nsec=ms*1000000L; |     req.tv_nsec=ms*1000000L; | ||||||
|      |  | ||||||
|     // NOTE: Use nanosleep() on Unix platforms... usleep() it's deprecated. |     // NOTE: Use nanosleep() on Unix platforms... usleep() it's deprecated. | ||||||
|     while (nanosleep(&req,&req) == -1) continue; |     while (nanosleep(&req,&req) == -1) continue; | ||||||
| //#elif defined __APPLE__ | //#elif defined __APPLE__ | ||||||
| @@ -1999,10 +1999,10 @@ static void PollInputEvents(void) | |||||||
|     // NOTE: Gestures update must be called every frame to reset gestures correctly |     // NOTE: Gestures update must be called every frame to reset gestures correctly | ||||||
|     // because ProcessGestureEvent() is just called on an event, not every frame |     // because ProcessGestureEvent() is just called on an event, not every frame | ||||||
|     UpdateGestures(); |     UpdateGestures(); | ||||||
|      |  | ||||||
|     // Reset last key pressed registered |     // Reset last key pressed registered | ||||||
|     lastKeyPressed = -1; |     lastKeyPressed = -1; | ||||||
|      |  | ||||||
| #if !defined(PLATFORM_RPI) | #if !defined(PLATFORM_RPI) | ||||||
|     // Reset last gamepad button/axis registered state |     // Reset last gamepad button/axis registered state | ||||||
|     lastGamepadButtonPressed = -1; |     lastGamepadButtonPressed = -1; | ||||||
| @@ -2018,7 +2018,7 @@ static void PollInputEvents(void) | |||||||
|  |  | ||||||
|     mousePosition.x = (float)mouseX; |     mousePosition.x = (float)mouseX; | ||||||
|     mousePosition.y = (float)mouseY; |     mousePosition.y = (float)mouseY; | ||||||
|      |  | ||||||
|     // Keyboard input polling (automatically managed by GLFW3 through callback) |     // Keyboard input polling (automatically managed by GLFW3 through callback) | ||||||
|  |  | ||||||
|     // Register previous keys states |     // Register previous keys states | ||||||
| @@ -2039,7 +2039,7 @@ static void PollInputEvents(void) | |||||||
|         if (glfwJoystickPresent(i)) gamepadReady[i] = true; |         if (glfwJoystickPresent(i)) gamepadReady[i] = true; | ||||||
|         else gamepadReady[i] = false; |         else gamepadReady[i] = false; | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     // Register gamepads buttons events |     // Register gamepads buttons events | ||||||
|     for (int i = 0; i < MAX_GAMEPADS; i++) |     for (int i = 0; i < MAX_GAMEPADS; i++) | ||||||
|     { |     { | ||||||
| @@ -2047,14 +2047,14 @@ static void PollInputEvents(void) | |||||||
|         { |         { | ||||||
|             // Register previous gamepad states |             // Register previous gamepad states | ||||||
|             for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) previousGamepadState[i][k] = currentGamepadState[i][k]; |             for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) previousGamepadState[i][k] = currentGamepadState[i][k]; | ||||||
|      |  | ||||||
|             // Get current gamepad state |             // Get current gamepad state | ||||||
|             // NOTE: There is no callback available, so we get it manually |             // NOTE: There is no callback available, so we get it manually | ||||||
|             const unsigned char *buttons; |             const unsigned char *buttons; | ||||||
|             int buttonsCount; |             int buttonsCount; | ||||||
|  |  | ||||||
|             buttons = glfwGetJoystickButtons(i, &buttonsCount); |             buttons = glfwGetJoystickButtons(i, &buttonsCount); | ||||||
|              |  | ||||||
|             for (int k = 0; (buttons != NULL) && (k < buttonsCount) && (buttonsCount < MAX_GAMEPAD_BUTTONS); k++) |             for (int k = 0; (buttons != NULL) && (k < buttonsCount) && (buttonsCount < MAX_GAMEPAD_BUTTONS); k++) | ||||||
|             { |             { | ||||||
|                 if (buttons[k] == GLFW_PRESS) |                 if (buttons[k] == GLFW_PRESS) | ||||||
| @@ -2064,18 +2064,18 @@ static void PollInputEvents(void) | |||||||
|                 } |                 } | ||||||
|                 else currentGamepadState[i][k] = 0; |                 else currentGamepadState[i][k] = 0; | ||||||
|             } |             } | ||||||
|              |  | ||||||
|             // Get current axis state |             // Get current axis state | ||||||
|             const float *axes; |             const float *axes; | ||||||
|             int axisCount = 0; |             int axisCount = 0; | ||||||
|  |  | ||||||
|             axes = glfwGetJoystickAxes(i, &axisCount); |             axes = glfwGetJoystickAxes(i, &axisCount); | ||||||
|              |  | ||||||
|             for (int k = 0; (axes != NULL) && (k < axisCount) && (k < MAX_GAMEPAD_AXIS); k++) |             for (int k = 0; (axes != NULL) && (k < axisCount) && (k < MAX_GAMEPAD_AXIS); k++) | ||||||
|             { |             { | ||||||
|                 gamepadAxisState[i][k] = axes[k]; |                 gamepadAxisState[i][k] = axes[k]; | ||||||
|             } |             } | ||||||
|              |  | ||||||
|             gamepadAxisCount = axisCount; |             gamepadAxisCount = axisCount; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -2088,16 +2088,16 @@ static void PollInputEvents(void) | |||||||
| #if defined(PLATFORM_WEB) | #if defined(PLATFORM_WEB) | ||||||
|     // Get number of gamepads connected |     // Get number of gamepads connected | ||||||
|     int numGamepads = emscripten_get_num_gamepads(); |     int numGamepads = emscripten_get_num_gamepads(); | ||||||
|    |  | ||||||
|     for (int i = 0; (i < numGamepads) && (i < MAX_GAMEPADS); i++) |     for (int i = 0; (i < numGamepads) && (i < MAX_GAMEPADS); i++) | ||||||
|     { |     { | ||||||
|         // Register previous gamepad button states |         // Register previous gamepad button states | ||||||
|         for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) previousGamepadState[i][k] = currentGamepadState[i][k]; |         for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) previousGamepadState[i][k] = currentGamepadState[i][k]; | ||||||
|          |  | ||||||
|         EmscriptenGamepadEvent gamepadState; |         EmscriptenGamepadEvent gamepadState; | ||||||
|          |  | ||||||
|         int result = emscripten_get_gamepad_status(i, &gamepadState); |         int result = emscripten_get_gamepad_status(i, &gamepadState); | ||||||
|          |  | ||||||
|         if (result == EMSCRIPTEN_RESULT_SUCCESS) |         if (result == EMSCRIPTEN_RESULT_SUCCESS) | ||||||
|         { |         { | ||||||
|             // Register buttons data for every connected gamepad |             // Register buttons data for every connected gamepad | ||||||
| @@ -2109,16 +2109,16 @@ static void PollInputEvents(void) | |||||||
|                     lastGamepadButtonPressed = j; |                     lastGamepadButtonPressed = j; | ||||||
|                 } |                 } | ||||||
|                 else currentGamepadState[i][j] = 0; |                 else currentGamepadState[i][j] = 0; | ||||||
|                  |  | ||||||
|                 //printf("Gamepad %d, button %d: Digital: %d, Analog: %g\n", gamepadState.index, j, gamepadState.digitalButton[j], gamepadState.analogButton[j]); |                 //printf("Gamepad %d, button %d: Digital: %d, Analog: %g\n", gamepadState.index, j, gamepadState.digitalButton[j], gamepadState.analogButton[j]); | ||||||
|             } |             } | ||||||
|              |  | ||||||
|             // Register axis data for every connected gamepad |             // Register axis data for every connected gamepad | ||||||
|             for (int j = 0; (j < gamepadState.numAxes) && (j < MAX_GAMEPAD_AXIS); j++) |             for (int j = 0; (j < gamepadState.numAxes) && (j < MAX_GAMEPAD_AXIS); j++) | ||||||
|             { |             { | ||||||
|                 gamepadAxisState[i][j] = gamepadState.axis[j]; |                 gamepadAxisState[i][j] = gamepadState.axis[j]; | ||||||
|             } |             } | ||||||
|              |  | ||||||
|             gamepadAxisCount = gamepadState.numAxes; |             gamepadAxisCount = gamepadState.numAxes; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -2665,16 +2665,16 @@ static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadE | |||||||
| { | { | ||||||
|     /* |     /* | ||||||
|     printf("%s: timeStamp: %g, connected: %d, index: %ld, numAxes: %d, numButtons: %d, id: \"%s\", mapping: \"%s\"\n", |     printf("%s: timeStamp: %g, connected: %d, index: %ld, numAxes: %d, numButtons: %d, id: \"%s\", mapping: \"%s\"\n", | ||||||
|            eventType != 0 ? emscripten_event_type_to_string(eventType) : "Gamepad state",  |            eventType != 0 ? emscripten_event_type_to_string(eventType) : "Gamepad state", | ||||||
|            gamepadEvent->timestamp, gamepadEvent->connected, gamepadEvent->index, gamepadEvent->numAxes, gamepadEvent->numButtons, gamepadEvent->id, gamepadEvent->mapping); |            gamepadEvent->timestamp, gamepadEvent->connected, gamepadEvent->index, gamepadEvent->numAxes, gamepadEvent->numButtons, gamepadEvent->id, gamepadEvent->mapping); | ||||||
|             |  | ||||||
|     for(int i = 0; i < gamepadEvent->numAxes; ++i) printf("Axis %d: %g\n", i, gamepadEvent->axis[i]); |     for(int i = 0; i < gamepadEvent->numAxes; ++i) printf("Axis %d: %g\n", i, gamepadEvent->axis[i]); | ||||||
|     for(int i = 0; i < gamepadEvent->numButtons; ++i) printf("Button %d: Digital: %d, Analog: %g\n", i, gamepadEvent->digitalButton[i], gamepadEvent->analogButton[i]); |     for(int i = 0; i < gamepadEvent->numButtons; ++i) printf("Button %d: Digital: %d, Analog: %g\n", i, gamepadEvent->digitalButton[i], gamepadEvent->analogButton[i]); | ||||||
|     */ |     */ | ||||||
|      |  | ||||||
|     if ((gamepadEvent->connected) && (gamepadEvent->index < MAX_GAMEPADS)) gamepadReady[gamepadEvent->index] = true; |     if ((gamepadEvent->connected) && (gamepadEvent->index < MAX_GAMEPADS)) gamepadReady[gamepadEvent->index] = true; | ||||||
|     else gamepadReady[gamepadEvent->index] = false; |     else gamepadReady[gamepadEvent->index] = false; | ||||||
|      |  | ||||||
|     // TODO: Test gamepadEvent->index |     // TODO: Test gamepadEvent->index | ||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| @@ -2935,7 +2935,7 @@ static void InitTouch(void) | |||||||
| } | } | ||||||
|  |  | ||||||
| // Touch reading thread. | // Touch reading thread. | ||||||
| // This reads from a Virtual Input Event /dev/input/event4 which is  | // This reads from a Virtual Input Event /dev/input/event4 which is | ||||||
| // created by the ts_uinput daemon. This takes, filters and scales | // created by the ts_uinput daemon. This takes, filters and scales | ||||||
| // raw input from the Touchscreen (which appears in /dev/input/event3) | // raw input from the Touchscreen (which appears in /dev/input/event3) | ||||||
| // based on the Calibration data referenced by tslib. | // based on the Calibration data referenced by tslib. | ||||||
| @@ -2949,7 +2949,7 @@ static void *TouchThread(void *arg) | |||||||
|         if (read(touchStream, &ev, sizeof(ev)) == (int)sizeof(ev)) |         if (read(touchStream, &ev, sizeof(ev)) == (int)sizeof(ev)) | ||||||
|         { |         { | ||||||
|             // if pressure > 0 then simulate left mouse button click |             // if pressure > 0 then simulate left mouse button click | ||||||
|             if (ev.type == EV_ABS && ev.code == 24 && ev.value == 0 && currentMouseState[0] == 1)  |             if (ev.type == EV_ABS && ev.code == 24 && ev.value == 0 && currentMouseState[0] == 1) | ||||||
|             { |             { | ||||||
|                 currentMouseState[0] = 0; |                 currentMouseState[0] = 0; | ||||||
|                 gestureEvent.touchAction = TOUCH_UP; |                 gestureEvent.touchAction = TOUCH_UP; | ||||||
| @@ -2963,10 +2963,10 @@ static void *TouchThread(void *arg) | |||||||
|                 gestureEvent.position[1].x /= (float)GetScreenWidth(); |                 gestureEvent.position[1].x /= (float)GetScreenWidth(); | ||||||
|                 gestureEvent.position[1].y /= (float)GetScreenHeight(); |                 gestureEvent.position[1].y /= (float)GetScreenHeight(); | ||||||
|                 ProcessGestureEvent(gestureEvent); |                 ProcessGestureEvent(gestureEvent); | ||||||
|             }  |             } | ||||||
|             if (ev.type == EV_ABS && ev.code == 24 && ev.value > 0 && currentMouseState[0] == 0)  |             if (ev.type == EV_ABS && ev.code == 24 && ev.value > 0 && currentMouseState[0] == 0) | ||||||
|             { |             { | ||||||
|                 currentMouseState[0] = 1;    |                 currentMouseState[0] = 1; | ||||||
|                 gestureEvent.touchAction = TOUCH_DOWN; |                 gestureEvent.touchAction = TOUCH_DOWN; | ||||||
|                 gestureEvent.pointCount = 1; |                 gestureEvent.pointCount = 1; | ||||||
|                 gestureEvent.pointerId[0] = 0; |                 gestureEvent.pointerId[0] = 0; | ||||||
| @@ -2978,9 +2978,9 @@ static void *TouchThread(void *arg) | |||||||
|                 gestureEvent.position[1].x /= (float)GetScreenWidth(); |                 gestureEvent.position[1].x /= (float)GetScreenWidth(); | ||||||
|                 gestureEvent.position[1].y /= (float)GetScreenHeight(); |                 gestureEvent.position[1].y /= (float)GetScreenHeight(); | ||||||
|                 ProcessGestureEvent(gestureEvent); |                 ProcessGestureEvent(gestureEvent); | ||||||
|             }  |             } | ||||||
|             // x & y values supplied by event4 have been scaled & de-jittered using tslib calibration data |             // x & y values supplied by event4 have been scaled & de-jittered using tslib calibration data | ||||||
|             if (ev.type == EV_ABS && ev.code == 0)  |             if (ev.type == EV_ABS && ev.code == 0) | ||||||
|             { |             { | ||||||
|                 mousePosition.x = ev.value; |                 mousePosition.x = ev.value; | ||||||
|                 if (mousePosition.x < 0) mousePosition.x = 0; |                 if (mousePosition.x < 0) mousePosition.x = 0; | ||||||
| @@ -2997,7 +2997,7 @@ static void *TouchThread(void *arg) | |||||||
|                 gestureEvent.position[1].y /= (float)GetScreenHeight(); |                 gestureEvent.position[1].y /= (float)GetScreenHeight(); | ||||||
|                 ProcessGestureEvent(gestureEvent); |                 ProcessGestureEvent(gestureEvent); | ||||||
|             } |             } | ||||||
|             if (ev.type == EV_ABS && ev.code == 1)  |             if (ev.type == EV_ABS && ev.code == 1) | ||||||
|             { |             { | ||||||
|                 mousePosition.y = ev.value; |                 mousePosition.y = ev.value; | ||||||
|                 if (mousePosition.y < 0) mousePosition.y = 0; |                 if (mousePosition.y < 0) mousePosition.y = 0; | ||||||
| @@ -3014,7 +3014,7 @@ static void *TouchThread(void *arg) | |||||||
|                 gestureEvent.position[1].y /= (float)GetScreenHeight(); |                 gestureEvent.position[1].y /= (float)GetScreenHeight(); | ||||||
|                 ProcessGestureEvent(gestureEvent); |                 ProcessGestureEvent(gestureEvent); | ||||||
|             } |             } | ||||||
|   |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     return NULL; |     return NULL; | ||||||
| @@ -3084,7 +3084,7 @@ static void *GamepadThread(void *arg) | |||||||
|                     { |                     { | ||||||
|                         // 1 - button pressed, 0 - button released |                         // 1 - button pressed, 0 - button released | ||||||
|                         currentGamepadState[i][gamepadEvent.number] = (int)gamepadEvent.value; |                         currentGamepadState[i][gamepadEvent.number] = (int)gamepadEvent.value; | ||||||
|                          |  | ||||||
|                         if ((int)gamepadEvent.value == 1) lastGamepadButtonPressed = gamepadEvent.number; |                         if ((int)gamepadEvent.value == 1) lastGamepadButtonPressed = gamepadEvent.number; | ||||||
|                         else lastGamepadButtonPressed = -1; |                         else lastGamepadButtonPressed = -1; | ||||||
|                     } |                     } | ||||||
|   | |||||||
							
								
								
									
										66
									
								
								src/models.c
									
									
									
									
									
								
							
							
						
						
									
										66
									
								
								src/models.c
									
									
									
									
									
								
							| @@ -584,7 +584,7 @@ Mesh LoadMesh(const char *fileName) | |||||||
|  |  | ||||||
|     if (mesh.vertexCount == 0) TraceLog(WARNING, "Mesh could not be loaded"); |     if (mesh.vertexCount == 0) TraceLog(WARNING, "Mesh could not be loaded"); | ||||||
|     else rlglLoadMesh(&mesh, false);  // Upload vertex data to GPU (static mesh) |     else rlglLoadMesh(&mesh, false);  // Upload vertex data to GPU (static mesh) | ||||||
|      |  | ||||||
|     // TODO: Initialize default mesh data in case loading fails, maybe a cube? |     // TODO: Initialize default mesh data in case loading fails, maybe a cube? | ||||||
|  |  | ||||||
|     return mesh; |     return mesh; | ||||||
| @@ -607,7 +607,7 @@ Mesh LoadMeshEx(int numVertex, float *vData, float *vtData, float *vnData, Color | |||||||
|     mesh.indices = NULL; |     mesh.indices = NULL; | ||||||
|  |  | ||||||
|     rlglLoadMesh(&mesh, false);     // Upload vertex data to GPU (static mesh) |     rlglLoadMesh(&mesh, false);     // Upload vertex data to GPU (static mesh) | ||||||
|      |  | ||||||
|     return mesh; |     return mesh; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -668,7 +668,7 @@ Model LoadCubicmap(Image cubicmap) | |||||||
|  |  | ||||||
|     return model; |     return model; | ||||||
| } | } | ||||||
|                                                                     |  | ||||||
| // Unload mesh from memory (RAM and/or VRAM) | // Unload mesh from memory (RAM and/or VRAM) | ||||||
| void UnloadMesh(Mesh *mesh) | void UnloadMesh(Mesh *mesh) | ||||||
| { | { | ||||||
| @@ -1438,34 +1438,34 @@ RayHitInfo GetCollisionRayMesh(Ray ray, Mesh *mesh) | |||||||
|     int triangleCount = mesh->vertexCount/3; |     int triangleCount = mesh->vertexCount/3; | ||||||
|  |  | ||||||
|     // Test against all triangles in mesh |     // Test against all triangles in mesh | ||||||
|     for (int i = 0; i < triangleCount; i++)  |     for (int i = 0; i < triangleCount; i++) | ||||||
|     { |     { | ||||||
|         Vector3 a, b, c; |         Vector3 a, b, c; | ||||||
|         Vector3 *vertdata = (Vector3 *)mesh->vertices; |         Vector3 *vertdata = (Vector3 *)mesh->vertices; | ||||||
|          |  | ||||||
|         if (mesh->indices)  |         if (mesh->indices) | ||||||
|         { |         { | ||||||
|             a = vertdata[mesh->indices[i*3 + 0]]; |             a = vertdata[mesh->indices[i*3 + 0]]; | ||||||
|             b = vertdata[mesh->indices[i*3 + 1]]; |             b = vertdata[mesh->indices[i*3 + 1]]; | ||||||
|             c = vertdata[mesh->indices[i*3 + 2]];             |             c = vertdata[mesh->indices[i*3 + 2]]; | ||||||
|         }  |         } | ||||||
|         else  |         else | ||||||
|         {             |         { | ||||||
|             a = vertdata[i*3 + 0]; |             a = vertdata[i*3 + 0]; | ||||||
|             b = vertdata[i*3 + 1]; |             b = vertdata[i*3 + 1]; | ||||||
|             c = vertdata[i*3 + 2]; |             c = vertdata[i*3 + 2]; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         RayHitInfo triHitInfo = GetCollisionRayTriangle(ray, a, b, c); |         RayHitInfo triHitInfo = GetCollisionRayTriangle(ray, a, b, c); | ||||||
|          |  | ||||||
|         if (triHitInfo.hit)  |         if (triHitInfo.hit) | ||||||
|         { |         { | ||||||
|             // Save the closest hit triangle |             // Save the closest hit triangle | ||||||
|             if ((!result.hit) || (result.distance > triHitInfo.distance)) result = triHitInfo; |             if ((!result.hit) || (result.distance > triHitInfo.distance)) result = triHitInfo; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return result;  |     return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| // Get collision info between ray and triangle | // Get collision info between ray and triangle | ||||||
| @@ -1478,44 +1478,44 @@ RayHitInfo GetCollisionRayTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3) | |||||||
|     Vector3 p, q, tv; |     Vector3 p, q, tv; | ||||||
|     float det, invDet, u, v, t; |     float det, invDet, u, v, t; | ||||||
|     RayHitInfo result = {0}; |     RayHitInfo result = {0}; | ||||||
|      |  | ||||||
|     // Find vectors for two edges sharing V1 |     // Find vectors for two edges sharing V1 | ||||||
|     edge1 = VectorSubtract(p2, p1); |     edge1 = VectorSubtract(p2, p1); | ||||||
|     edge2 = VectorSubtract(p3, p1); |     edge2 = VectorSubtract(p3, p1); | ||||||
|      |  | ||||||
|     // Begin calculating determinant - also used to calculate u parameter |     // Begin calculating determinant - also used to calculate u parameter | ||||||
|     p = VectorCrossProduct(ray.direction, edge2); |     p = VectorCrossProduct(ray.direction, edge2); | ||||||
|      |  | ||||||
|     // If determinant is near zero, ray lies in plane of triangle or ray is parallel to plane of triangle |     // If determinant is near zero, ray lies in plane of triangle or ray is parallel to plane of triangle | ||||||
|     det = VectorDotProduct(edge1, p); |     det = VectorDotProduct(edge1, p); | ||||||
|      |  | ||||||
|     // Avoid culling! |     // Avoid culling! | ||||||
|     if ((det > -EPSILON) && (det < EPSILON)) return result; |     if ((det > -EPSILON) && (det < EPSILON)) return result; | ||||||
|      |  | ||||||
|     invDet = 1.0f/det; |     invDet = 1.0f/det; | ||||||
|      |  | ||||||
|     // Calculate distance from V1 to ray origin |     // Calculate distance from V1 to ray origin | ||||||
|     tv = VectorSubtract(ray.position, p1); |     tv = VectorSubtract(ray.position, p1); | ||||||
|      |  | ||||||
|     // Calculate u parameter and test bound |     // Calculate u parameter and test bound | ||||||
|     u = VectorDotProduct(tv, p)*invDet; |     u = VectorDotProduct(tv, p)*invDet; | ||||||
|      |  | ||||||
|     // The intersection lies outside of the triangle |     // The intersection lies outside of the triangle | ||||||
|     if ((u < 0.0f) || (u > 1.0f)) return result; |     if ((u < 0.0f) || (u > 1.0f)) return result; | ||||||
|      |  | ||||||
|     // Prepare to test v parameter |     // Prepare to test v parameter | ||||||
|     q = VectorCrossProduct(tv, edge1); |     q = VectorCrossProduct(tv, edge1); | ||||||
|      |  | ||||||
|     // Calculate V parameter and test bound |     // Calculate V parameter and test bound | ||||||
|     v = VectorDotProduct(ray.direction, q)*invDet; |     v = VectorDotProduct(ray.direction, q)*invDet; | ||||||
|      |  | ||||||
|     // The intersection lies outside of the triangle |     // The intersection lies outside of the triangle | ||||||
|     if ((v < 0.0f) || ((u + v) > 1.0f)) return result; |     if ((v < 0.0f) || ((u + v) > 1.0f)) return result; | ||||||
|      |  | ||||||
|     t = VectorDotProduct(edge2, q)*invDet; |     t = VectorDotProduct(edge2, q)*invDet; | ||||||
|      |  | ||||||
|     if (t > EPSILON)  |     if (t > EPSILON) | ||||||
|     {  |     { | ||||||
|         // Ray hit, get hit point and normal |         // Ray hit, get hit point and normal | ||||||
|         result.hit = true; |         result.hit = true; | ||||||
|         result.distance = t; |         result.distance = t; | ||||||
| @@ -1523,10 +1523,10 @@ RayHitInfo GetCollisionRayTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3) | |||||||
|         result.hitNormal = VectorCrossProduct(edge1, edge2); |         result.hitNormal = VectorCrossProduct(edge1, edge2); | ||||||
|         VectorNormalize(&result.hitNormal); |         VectorNormalize(&result.hitNormal); | ||||||
|         Vector3 rayDir = ray.direction; |         Vector3 rayDir = ray.direction; | ||||||
|         VectorScale(&rayDir, t);         |         VectorScale(&rayDir, t); | ||||||
|         result.hitPosition = VectorAdd(ray.position, rayDir); |         result.hitPosition = VectorAdd(ray.position, rayDir); | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     return result; |     return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1540,8 +1540,8 @@ RayHitInfo GetCollisionRayGround(Ray ray, float groundHeight) | |||||||
|     if (fabsf(ray.direction.y) > EPSILON) |     if (fabsf(ray.direction.y) > EPSILON) | ||||||
|     { |     { | ||||||
|         float t = (ray.position.y - groundHeight)/-ray.direction.y; |         float t = (ray.position.y - groundHeight)/-ray.direction.y; | ||||||
|          |  | ||||||
|         if (t >= 0.0)  |         if (t >= 0.0) | ||||||
|         { |         { | ||||||
|             Vector3 rayDir = ray.direction; |             Vector3 rayDir = ray.direction; | ||||||
|             VectorScale(&rayDir, t); |             VectorScale(&rayDir, t); | ||||||
| @@ -1551,7 +1551,7 @@ RayHitInfo GetCollisionRayGround(Ray ray, float groundHeight) | |||||||
|             result.hitPosition = VectorAdd(ray.position, rayDir); |             result.hitPosition = VectorAdd(ray.position, rayDir); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     return result; |     return result; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										26
									
								
								src/raylib.h
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								src/raylib.h
									
									
									
									
									
								
							| @@ -593,21 +593,21 @@ typedef enum { | |||||||
| // rRES data returned when reading a resource, it contains all required data for user (24 byte) | // rRES data returned when reading a resource, it contains all required data for user (24 byte) | ||||||
| typedef struct { | typedef struct { | ||||||
|     unsigned int type;          // Resource type (4 byte) |     unsigned int type;          // Resource type (4 byte) | ||||||
|      |  | ||||||
|     unsigned int param1;        // Resouce parameter 1 (4 byte) |     unsigned int param1;        // Resouce parameter 1 (4 byte) | ||||||
|     unsigned int param2;        // Resouce parameter 2 (4 byte) |     unsigned int param2;        // Resouce parameter 2 (4 byte) | ||||||
|     unsigned int param3;        // Resouce parameter 3 (4 byte) |     unsigned int param3;        // Resouce parameter 3 (4 byte) | ||||||
|     unsigned int param4;        // Resouce parameter 4 (4 byte) |     unsigned int param4;        // Resouce parameter 4 (4 byte) | ||||||
|      |  | ||||||
|     void *data;                 // Resource data pointer (4 byte) |     void *data;                 // Resource data pointer (4 byte) | ||||||
| } RRESData; | } RRESData; | ||||||
|  |  | ||||||
| typedef enum {  | typedef enum { | ||||||
|     RRES_RAW = 0,  |     RRES_RAW = 0, | ||||||
|     RRES_IMAGE,  |     RRES_IMAGE, | ||||||
|     RRES_WAVE,  |     RRES_WAVE, | ||||||
|     RRES_VERTEX,  |     RRES_VERTEX, | ||||||
|     RRES_TEXT  |     RRES_TEXT | ||||||
| } RRESDataType; | } RRESDataType; | ||||||
|  |  | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| @@ -800,7 +800,7 @@ RLAPI Image ImageText(const char *text, int fontSize, Color color); | |||||||
| 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 | ||||||
| RLAPI void ImageDrawText(Image *dst, Vector2 position, const char *text, int fontSize, Color color);     // Draw text (default font) within an image (destination) | RLAPI void ImageDrawText(Image *dst, Vector2 position, const char *text, int fontSize, Color color);     // Draw text (default font) within an image (destination) | ||||||
| RLAPI void ImageDrawTextEx(Image *dst, Vector2 position, SpriteFont font, const char *text,  | RLAPI void ImageDrawTextEx(Image *dst, Vector2 position, SpriteFont font, const char *text, | ||||||
|                            float fontSize, int spacing, Color color);                                    // Draw text (custom sprite font) within an image (destination) |                            float fontSize, int spacing, Color color);                                    // Draw text (custom sprite font) within an image (destination) | ||||||
| RLAPI void ImageFlipVertical(Image *image);                                                              // Flip image vertically | RLAPI void ImageFlipVertical(Image *image);                                                              // Flip image vertically | ||||||
| RLAPI void ImageFlipHorizontal(Image *image);                                                            // Flip image horizontally | RLAPI void ImageFlipHorizontal(Image *image);                                                            // Flip image horizontally | ||||||
| @@ -876,15 +876,15 @@ RLAPI Material LoadDefaultMaterial(void); | |||||||
| RLAPI void UnloadMaterial(Material material);                                                           // Unload material from GPU memory (VRAM) | RLAPI void UnloadMaterial(Material material);                                                           // Unload material from GPU memory (VRAM) | ||||||
|  |  | ||||||
| RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint);                           // Draw a model (with texture if set) | RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint);                           // Draw a model (with texture if set) | ||||||
| RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis,  | RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, | ||||||
|                        float rotationAngle, Vector3 scale, Color tint);                                 // Draw a model with extended parameters |                        float rotationAngle, Vector3 scale, Color tint);                                 // Draw a model with extended parameters | ||||||
| RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint);                      // Draw a model wires (with texture if set) | RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint);                      // Draw a model wires (with texture if set) | ||||||
| RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis,  | RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, | ||||||
|                             float rotationAngle, Vector3 scale, Color tint);                            // Draw a model wires (with texture if set) with extended parameters |                             float rotationAngle, Vector3 scale, Color tint);                            // Draw a model wires (with texture if set) with extended parameters | ||||||
| RLAPI void DrawBoundingBox(BoundingBox box, Color color);                                               // Draw bounding box (wires) | RLAPI void DrawBoundingBox(BoundingBox box, Color color);                                               // Draw bounding box (wires) | ||||||
|  |  | ||||||
| RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size, Color tint);     // Draw a billboard texture | RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size, Color tint);     // Draw a billboard texture | ||||||
| RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec,  | RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, | ||||||
|                             Vector3 center, float size, Color tint);                                    // Draw a billboard texture defined by sourceRec |                             Vector3 center, float size, Color tint);                                    // Draw a billboard texture defined by sourceRec | ||||||
|  |  | ||||||
| RLAPI BoundingBox CalculateBoundingBox(Mesh mesh);                                                      // Calculate mesh bounding box limits | RLAPI BoundingBox CalculateBoundingBox(Mesh mesh);                                                      // Calculate mesh bounding box limits | ||||||
| @@ -892,7 +892,7 @@ RLAPI bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB | |||||||
| RLAPI bool CheckCollisionBoxes(BoundingBox box1, BoundingBox box2);                                     // Detect collision between two bounding boxes | RLAPI bool CheckCollisionBoxes(BoundingBox box1, BoundingBox box2);                                     // Detect collision between two bounding boxes | ||||||
| RLAPI bool CheckCollisionBoxSphere(BoundingBox box, Vector3 centerSphere, float radiusSphere);          // Detect collision between box and sphere | RLAPI bool CheckCollisionBoxSphere(BoundingBox box, Vector3 centerSphere, float radiusSphere);          // Detect collision between box and sphere | ||||||
| RLAPI bool CheckCollisionRaySphere(Ray ray, Vector3 spherePosition, float sphereRadius);                // Detect collision between ray and sphere | RLAPI bool CheckCollisionRaySphere(Ray ray, Vector3 spherePosition, float sphereRadius);                // Detect collision between ray and sphere | ||||||
| RLAPI bool CheckCollisionRaySphereEx(Ray ray, Vector3 spherePosition, float sphereRadius,  | RLAPI bool CheckCollisionRaySphereEx(Ray ray, Vector3 spherePosition, float sphereRadius, | ||||||
|                                      Vector3 *collisionPoint);                                          // Detect collision between ray and sphere, returns collision point |                                      Vector3 *collisionPoint);                                          // Detect collision between ray and sphere, returns collision point | ||||||
| RLAPI bool CheckCollisionRayBox(Ray ray, BoundingBox box);                                              // Detect collision between ray and box | RLAPI bool CheckCollisionRayBox(Ray ray, BoundingBox box);                                              // Detect collision between ray and box | ||||||
| RLAPI RayHitInfo GetCollisionRayMesh(Ray ray, Mesh *mesh);                                              // Get collision info between ray and mesh | RLAPI RayHitInfo GetCollisionRayMesh(Ray ray, Mesh *mesh);                                              // Get collision info between ray and mesh | ||||||
|   | |||||||
							
								
								
									
										488
									
								
								src/rlgl.c
									
									
									
									
									
								
							
							
						
						
									
										488
									
								
								src/rlgl.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										60
									
								
								src/text.c
									
									
									
									
									
								
							
							
						
						
									
										60
									
								
								src/text.c
									
									
									
									
									
								
							| @@ -286,17 +286,17 @@ SpriteFont LoadSpriteFont(const char *fileName) | |||||||
| SpriteFont LoadSpriteFontTTF(const char *fileName, int fontSize, int numChars, int *fontChars) | SpriteFont LoadSpriteFontTTF(const char *fileName, int fontSize, int numChars, int *fontChars) | ||||||
| { | { | ||||||
|     SpriteFont spriteFont = { 0 }; |     SpriteFont spriteFont = { 0 }; | ||||||
|      |  | ||||||
|     if (strcmp(GetExtension(fileName),"ttf") == 0)  |     if (strcmp(GetExtension(fileName),"ttf") == 0) | ||||||
|     { |     { | ||||||
|         if ((fontChars == NULL) || (numChars == 0)) |         if ((fontChars == NULL) || (numChars == 0)) | ||||||
|         { |         { | ||||||
|             int totalChars = 95;    // Default charset [32..126] |             int totalChars = 95;    // Default charset [32..126] | ||||||
|              |  | ||||||
|             int *defaultFontChars = (int *)malloc(totalChars*sizeof(int)); |             int *defaultFontChars = (int *)malloc(totalChars*sizeof(int)); | ||||||
|              |  | ||||||
|             for (int i = 0; i < totalChars; i++) defaultFontChars[i] = i + 32; // Default first character: SPACE[32] |             for (int i = 0; i < totalChars; i++) defaultFontChars[i] = i + 32; // Default first character: SPACE[32] | ||||||
|              |  | ||||||
|             spriteFont = LoadTTF(fileName, fontSize, totalChars, defaultFontChars); |             spriteFont = LoadTTF(fileName, fontSize, totalChars, defaultFontChars); | ||||||
|         } |         } | ||||||
|         else spriteFont = LoadTTF(fileName, fontSize, numChars, fontChars); |         else spriteFont = LoadTTF(fileName, fontSize, numChars, fontChars); | ||||||
| @@ -353,10 +353,10 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float | |||||||
|     int textOffsetX = 0;        // Offset between characters |     int textOffsetX = 0;        // Offset between characters | ||||||
|     int textOffsetY = 0;        // Required for line break! |     int textOffsetY = 0;        // Required for line break! | ||||||
|     float scaleFactor; |     float scaleFactor; | ||||||
|      |  | ||||||
|     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.size; |     scaleFactor = fontSize/spriteFont.size; | ||||||
|  |  | ||||||
|     // 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 | ||||||
| @@ -388,10 +388,10 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float | |||||||
|             } |             } | ||||||
|             else index = GetCharIndex(spriteFont, (int)text[i]); |             else index = GetCharIndex(spriteFont, (int)text[i]); | ||||||
|  |  | ||||||
|             DrawTexturePro(spriteFont.texture, spriteFont.charRecs[index],  |             DrawTexturePro(spriteFont.texture, spriteFont.charRecs[index], | ||||||
|                            (Rectangle){ position.x + textOffsetX + spriteFont.charOffsets[index].x*scaleFactor, |                            (Rectangle){ position.x + textOffsetX + spriteFont.charOffsets[index].x*scaleFactor, | ||||||
|                                         position.y + textOffsetY + spriteFont.charOffsets[index].y*scaleFactor, |                                         position.y + textOffsetY + spriteFont.charOffsets[index].y*scaleFactor, | ||||||
|                                         spriteFont.charRecs[index].width*scaleFactor,  |                                         spriteFont.charRecs[index].width*scaleFactor, | ||||||
|                                         spriteFont.charRecs[index].height*scaleFactor }, (Vector2){ 0, 0 }, 0.0f, tint); |                                         spriteFont.charRecs[index].height*scaleFactor }, (Vector2){ 0, 0 }, 0.0f, tint); | ||||||
|  |  | ||||||
|             if (spriteFont.charAdvanceX[index] == 0) textOffsetX += (int)(spriteFont.charRecs[index].width*scaleFactor + spacing); |             if (spriteFont.charAdvanceX[index] == 0) textOffsetX += (int)(spriteFont.charRecs[index].width*scaleFactor + spacing); | ||||||
| @@ -476,7 +476,7 @@ 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 = GetCharIndex(spriteFont, (int)text[i]); | ||||||
|              |  | ||||||
|             if (spriteFont.charAdvanceX[index] != 0) textWidth += spriteFont.charAdvanceX[index]; |             if (spriteFont.charAdvanceX[index] != 0) textWidth += spriteFont.charAdvanceX[index]; | ||||||
|             else textWidth += (spriteFont.charRecs[index].width + spriteFont.charOffsets[index].x); |             else textWidth += (spriteFont.charRecs[index].width + spriteFont.charOffsets[index].x); | ||||||
|         } |         } | ||||||
| @@ -517,7 +517,7 @@ static int GetCharIndex(SpriteFont font, int letter) | |||||||
| #define UNORDERED_CHARSET | #define UNORDERED_CHARSET | ||||||
| #if defined(UNORDERED_CHARSET) | #if defined(UNORDERED_CHARSET) | ||||||
|     int index = 0; |     int index = 0; | ||||||
|      |  | ||||||
|     for (int i = 0; i < font.numChars; i++) |     for (int i = 0; i < font.numChars; i++) | ||||||
|     { |     { | ||||||
|         if (font.charValues[i] == letter) |         if (font.charValues[i] == letter) | ||||||
| @@ -526,7 +526,7 @@ static int GetCharIndex(SpriteFont font, int letter) | |||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     return index; |     return index; | ||||||
| #else | #else | ||||||
|     return (letter - 32); |     return (letter - 32); | ||||||
| @@ -607,14 +607,14 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     TraceLog(DEBUG, "SpriteFont data parsed correctly from image"); |     TraceLog(DEBUG, "SpriteFont data parsed correctly from image"); | ||||||
|      |  | ||||||
|     // NOTE: We need to remove key color borders from image to avoid weird  |     // NOTE: We need to remove key color borders from image to avoid weird | ||||||
|     // artifacts on texture scaling when using FILTER_BILINEAR or FILTER_TRILINEAR |     // artifacts on texture scaling when using FILTER_BILINEAR or FILTER_TRILINEAR | ||||||
|     for (int i = 0; i < image.height*image.width; i++) if (COLOR_EQUAL(pixels[i], key)) pixels[i] = BLANK; |     for (int i = 0; i < image.height*image.width; i++) if (COLOR_EQUAL(pixels[i], key)) pixels[i] = BLANK; | ||||||
|  |  | ||||||
|     // Create a new image with the processed color data (key color replaced by BLANK) |     // Create a new image with the processed color data (key color replaced by BLANK) | ||||||
|     Image fontClear = LoadImageEx(pixels, image.width, image.height); |     Image fontClear = LoadImageEx(pixels, image.width, image.height); | ||||||
|      |  | ||||||
|     free(pixels);    // Free pixels array memory |     free(pixels);    // Free pixels array memory | ||||||
|  |  | ||||||
|     // Create spritefont with all data parsed from image |     // Create spritefont with all data parsed from image | ||||||
| @@ -622,7 +622,7 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar) | |||||||
|  |  | ||||||
|     spriteFont.texture = LoadTextureFromImage(fontClear); // Convert processed image to OpenGL texture |     spriteFont.texture = LoadTextureFromImage(fontClear); // Convert processed image to OpenGL texture | ||||||
|     spriteFont.numChars = index; |     spriteFont.numChars = index; | ||||||
|      |  | ||||||
|     UnloadImage(fontClear);     // Unload processed image once converted to texture |     UnloadImage(fontClear);     // Unload processed image once converted to texture | ||||||
|  |  | ||||||
|     // We got tempCharValues and tempCharsRecs populated with chars data |     // We got tempCharValues and tempCharsRecs populated with chars data | ||||||
| @@ -643,7 +643,7 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     spriteFont.size = spriteFont.charRecs[0].height; |     spriteFont.size = spriteFont.charRecs[0].height; | ||||||
|      |  | ||||||
|     TraceLog(INFO, "Image file loaded correctly as SpriteFont"); |     TraceLog(INFO, "Image file loaded correctly as SpriteFont"); | ||||||
|  |  | ||||||
|     return spriteFont; |     return spriteFont; | ||||||
| @@ -853,13 +853,13 @@ static SpriteFont LoadBMFont(const char *fileName) | |||||||
|     strncat(texPath, texFileName, strlen(texFileName)); |     strncat(texPath, texFileName, strlen(texFileName)); | ||||||
|  |  | ||||||
|     TraceLog(DEBUG, "[%s] Font texture loading path: %s", fileName, texPath); |     TraceLog(DEBUG, "[%s] Font texture loading path: %s", fileName, texPath); | ||||||
|      |  | ||||||
|     Image imFont = LoadImage(texPath); |     Image imFont = LoadImage(texPath); | ||||||
|      |  | ||||||
|     if (imFont.format == UNCOMPRESSED_GRAYSCALE)  |     if (imFont.format == UNCOMPRESSED_GRAYSCALE) | ||||||
|     { |     { | ||||||
|         Image imCopy = ImageCopy(imFont); |         Image imCopy = ImageCopy(imFont); | ||||||
|          |  | ||||||
|         for (int i = 0; i < imCopy.width*imCopy.height; i++) ((unsigned char *)imCopy.data)[i] = 0xff;  // WHITE pixel |         for (int i = 0; i < imCopy.width*imCopy.height; i++) ((unsigned char *)imCopy.data)[i] = 0xff;  // WHITE pixel | ||||||
|  |  | ||||||
|         ImageAlphaMask(&imCopy, imFont); |         ImageAlphaMask(&imCopy, imFont); | ||||||
| @@ -867,7 +867,7 @@ static SpriteFont LoadBMFont(const char *fileName) | |||||||
|         UnloadImage(imCopy); |         UnloadImage(imCopy); | ||||||
|     } |     } | ||||||
|     else font.texture = LoadTextureFromImage(imFont); |     else font.texture = LoadTextureFromImage(imFont); | ||||||
|      |  | ||||||
|     font.size = fontSize; |     font.size = fontSize; | ||||||
|     font.numChars = numChars; |     font.numChars = numChars; | ||||||
|     font.charValues = (int *)malloc(numChars*sizeof(int)); |     font.charValues = (int *)malloc(numChars*sizeof(int)); | ||||||
| @@ -876,7 +876,7 @@ static SpriteFont LoadBMFont(const char *fileName) | |||||||
|     font.charAdvanceX = (int *)malloc(numChars*sizeof(int)); |     font.charAdvanceX = (int *)malloc(numChars*sizeof(int)); | ||||||
|  |  | ||||||
|     UnloadImage(imFont); |     UnloadImage(imFont); | ||||||
|      |  | ||||||
|     free(texPath); |     free(texPath); | ||||||
|  |  | ||||||
|     int charId, charX, charY, charWidth, charHeight, charOffsetX, charOffsetY, charAdvanceX; |     int charId, charX, charY, charWidth, charHeight, charOffsetX, charOffsetY, charAdvanceX; | ||||||
| @@ -913,11 +913,11 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize, int numChars, int | |||||||
|     // NOTE: Font texture size is predicted (being as much conservative as possible) |     // NOTE: Font texture size is predicted (being as much conservative as possible) | ||||||
|     // Predictive method consist of supposing same number of chars by line-column (sqrtf) |     // Predictive method consist of supposing same number of chars by line-column (sqrtf) | ||||||
|     // and a maximum character width of 3/4 of fontSize... it worked ok with all my tests... |     // and a maximum character width of 3/4 of fontSize... it worked ok with all my tests... | ||||||
|      |  | ||||||
|     // Calculate next power-of-two value |     // Calculate next power-of-two value | ||||||
|     float guessSize = ceilf((float)fontSize*3/4)*ceilf(sqrtf((float)numChars)); |     float guessSize = ceilf((float)fontSize*3/4)*ceilf(sqrtf((float)numChars)); | ||||||
|     int textureSize = (int)powf(2, ceilf(logf((float)guessSize)/logf(2)));      // Calculate next POT |     int textureSize = (int)powf(2, ceilf(logf((float)guessSize)/logf(2)));      // Calculate next POT | ||||||
|      |  | ||||||
|     TraceLog(INFO, "TTF spritefont loading: Predicted texture size: %ix%i", textureSize, textureSize); |     TraceLog(INFO, "TTF spritefont loading: Predicted texture size: %ix%i", textureSize, textureSize); | ||||||
|  |  | ||||||
|     unsigned char *ttfBuffer = (unsigned char *)malloc(1 << 25); |     unsigned char *ttfBuffer = (unsigned char *)malloc(1 << 25); | ||||||
| @@ -935,7 +935,7 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize, int numChars, int | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     fread(ttfBuffer, 1, 1 << 25, ttfFile); |     fread(ttfBuffer, 1, 1 << 25, ttfFile); | ||||||
|      |  | ||||||
|     if (fontChars[0] != 32) TraceLog(WARNING, "TTF spritefont loading: first character is not SPACE(32) character"); |     if (fontChars[0] != 32) TraceLog(WARNING, "TTF spritefont loading: first character is not SPACE(32) character"); | ||||||
|  |  | ||||||
|     // NOTE: Using stb_truetype crappy packing method, no guarante the font fits the image... |     // NOTE: Using stb_truetype crappy packing method, no guarante the font fits the image... | ||||||
| @@ -945,7 +945,7 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize, int numChars, int | |||||||
|  |  | ||||||
|     //if (result > 0) TraceLog(INFO, "TTF spritefont loading: first unused row of generated bitmap: %i", result); |     //if (result > 0) TraceLog(INFO, "TTF spritefont loading: first unused row of generated bitmap: %i", result); | ||||||
|     if (result < 0) TraceLog(WARNING, "TTF spritefont loading: Not all the characters fit in the font"); |     if (result < 0) TraceLog(WARNING, "TTF spritefont loading: Not all the characters fit in the font"); | ||||||
|      |  | ||||||
|     free(ttfBuffer); |     free(ttfBuffer); | ||||||
|  |  | ||||||
|     // Convert image data from grayscale to to UNCOMPRESSED_GRAY_ALPHA |     // Convert image data from grayscale to to UNCOMPRESSED_GRAY_ALPHA | ||||||
| @@ -966,11 +966,11 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize, int numChars, int | |||||||
|     image.mipmaps = 1; |     image.mipmaps = 1; | ||||||
|     image.format = UNCOMPRESSED_GRAY_ALPHA; |     image.format = UNCOMPRESSED_GRAY_ALPHA; | ||||||
|     image.data = dataGrayAlpha; |     image.data = dataGrayAlpha; | ||||||
|      |  | ||||||
|     font.texture = LoadTextureFromImage(image); |     font.texture = LoadTextureFromImage(image); | ||||||
|      |  | ||||||
|     //SavePNG("generated_ttf_image.png", (unsigned char *)image.data, image.width, image.height, 2); |     //SavePNG("generated_ttf_image.png", (unsigned char *)image.data, image.width, image.height, 2); | ||||||
|      |  | ||||||
|     UnloadImage(image);     // Unloads dataGrayAlpha |     UnloadImage(image);     // Unloads dataGrayAlpha | ||||||
|  |  | ||||||
|     font.size = fontSize; |     font.size = fontSize; | ||||||
|   | |||||||
| @@ -144,9 +144,9 @@ Image LoadImage(const char *fileName) | |||||||
|     else if (strcmp(GetExtension(fileName),"rres") == 0) |     else if (strcmp(GetExtension(fileName),"rres") == 0) | ||||||
|     { |     { | ||||||
|         RRESData rres = LoadResource(fileName); |         RRESData rres = LoadResource(fileName); | ||||||
|          |  | ||||||
|         // NOTE: Parameters for RRES_IMAGE type are: width, height, format, mipmaps |         // NOTE: Parameters for RRES_IMAGE type are: width, height, format, mipmaps | ||||||
|          |  | ||||||
|         if (rres.type == RRES_IMAGE) image = LoadImagePro(rres.data, rres.param1, rres.param2, rres.param3); |         if (rres.type == RRES_IMAGE) image = LoadImagePro(rres.data, rres.param1, rres.param2, rres.param3); | ||||||
|         else TraceLog(WARNING, "[%s] Resource file does not contain image data", fileName); |         else TraceLog(WARNING, "[%s] Resource file does not contain image data", fileName); | ||||||
|  |  | ||||||
| @@ -197,9 +197,9 @@ Image LoadImagePro(void *data, int width, int height, int format) | |||||||
|     srcImage.height = height; |     srcImage.height = height; | ||||||
|     srcImage.mipmaps = 1; |     srcImage.mipmaps = 1; | ||||||
|     srcImage.format = format; |     srcImage.format = format; | ||||||
|      |  | ||||||
|     Image dstImage = ImageCopy(srcImage); |     Image dstImage = ImageCopy(srcImage); | ||||||
|      |  | ||||||
|     return dstImage; |     return dstImage; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -244,7 +244,7 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int | |||||||
|         if (bytes < size) |         if (bytes < size) | ||||||
|         { |         { | ||||||
|             TraceLog(WARNING, "[%s] RAW image data can not be read, wrong requested format or size", fileName); |             TraceLog(WARNING, "[%s] RAW image data can not be read, wrong requested format or size", fileName); | ||||||
|              |  | ||||||
|             if (image.data != NULL) free(image.data); |             if (image.data != NULL) free(image.data); | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
| @@ -615,12 +615,12 @@ void ImageAlphaMask(Image *image, Image alphaMask) | |||||||
|         // Force mask to be Grayscale |         // Force mask to be Grayscale | ||||||
|         Image mask = ImageCopy(alphaMask); |         Image mask = ImageCopy(alphaMask); | ||||||
|         if (mask.format != UNCOMPRESSED_GRAYSCALE) ImageFormat(&mask, UNCOMPRESSED_GRAYSCALE); |         if (mask.format != UNCOMPRESSED_GRAYSCALE) ImageFormat(&mask, UNCOMPRESSED_GRAYSCALE); | ||||||
|          |  | ||||||
|         // In case image is only grayscale, we just add alpha channel |         // In case image is only grayscale, we just add alpha channel | ||||||
|         if (image->format == UNCOMPRESSED_GRAYSCALE) |         if (image->format == UNCOMPRESSED_GRAYSCALE) | ||||||
|         { |         { | ||||||
|             ImageFormat(image, UNCOMPRESSED_GRAY_ALPHA); |             ImageFormat(image, UNCOMPRESSED_GRAY_ALPHA); | ||||||
|              |  | ||||||
|             // Apply alpha mask to alpha channel |             // Apply alpha mask to alpha channel | ||||||
|             for (int i = 0, k = 1; (i < mask.width*mask.height) || (i < image->width*image->height); i++, k += 2) |             for (int i = 0, k = 1; (i < mask.width*mask.height) || (i < image->width*image->height); i++, k += 2) | ||||||
|             { |             { | ||||||
| @@ -955,7 +955,7 @@ void ImageResizeNN(Image *image,int newWidth,int newHeight) | |||||||
| void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec) | void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec) | ||||||
| { | { | ||||||
|     bool cropRequired = false; |     bool cropRequired = false; | ||||||
|      |  | ||||||
|     // Security checks to avoid size and rectangle issues (out of bounds) |     // Security checks to avoid size and rectangle issues (out of bounds) | ||||||
|     // Check that srcRec is inside src image |     // Check that srcRec is inside src image | ||||||
|     if (srcRec.x < 0) srcRec.x = 0; |     if (srcRec.x < 0) srcRec.x = 0; | ||||||
| @@ -973,15 +973,15 @@ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec) | |||||||
|         TraceLog(WARNING, "Source rectangle height out of bounds, rescaled height: %i", srcRec.height); |         TraceLog(WARNING, "Source rectangle height out of bounds, rescaled height: %i", srcRec.height); | ||||||
|         cropRequired = true; |         cropRequired = true; | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     Image srcCopy = ImageCopy(src);     // Make a copy of source image to work with it |     Image srcCopy = ImageCopy(src);     // Make a copy of source image to work with it | ||||||
|     ImageCrop(&srcCopy, srcRec);        // Crop source image to desired source rectangle |     ImageCrop(&srcCopy, srcRec);        // Crop source image to desired source rectangle | ||||||
|      |  | ||||||
|     // Check that dstRec is inside dst image |     // Check that dstRec is inside dst image | ||||||
|     // TODO: Allow negative position within destination with cropping |     // TODO: Allow negative position within destination with cropping | ||||||
|     if (dstRec.x < 0) dstRec.x = 0; |     if (dstRec.x < 0) dstRec.x = 0; | ||||||
|     if (dstRec.y < 0) dstRec.y = 0; |     if (dstRec.y < 0) dstRec.y = 0; | ||||||
|      |  | ||||||
|     // Scale source image in case destination rec size is different than source rec size |     // Scale source image in case destination rec size is different than source rec size | ||||||
|     if ((dstRec.width != srcRec.width) || (dstRec.height != srcRec.height)) |     if ((dstRec.width != srcRec.width) || (dstRec.height != srcRec.height)) | ||||||
|     { |     { | ||||||
| @@ -1001,20 +1001,20 @@ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec) | |||||||
|         TraceLog(WARNING, "Destination rectangle height out of bounds, rescaled height: %i", dstRec.height); |         TraceLog(WARNING, "Destination rectangle height out of bounds, rescaled height: %i", dstRec.height); | ||||||
|         cropRequired = true; |         cropRequired = true; | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     if (cropRequired) |     if (cropRequired) | ||||||
|     { |     { | ||||||
|         // Crop destination rectangle if out of bounds |         // Crop destination rectangle if out of bounds | ||||||
|         Rectangle crop = { 0, 0, dstRec.width, dstRec.height }; |         Rectangle crop = { 0, 0, dstRec.width, dstRec.height }; | ||||||
|         ImageCrop(&srcCopy, crop); |         ImageCrop(&srcCopy, crop); | ||||||
|     } |     } | ||||||
|     |  | ||||||
|     // Get image data as Color pixels array to work with it |     // Get image data as Color pixels array to work with it | ||||||
|     Color *dstPixels = GetImageData(*dst); |     Color *dstPixels = GetImageData(*dst); | ||||||
|     Color *srcPixels = GetImageData(srcCopy); |     Color *srcPixels = GetImageData(srcCopy); | ||||||
|  |  | ||||||
|     UnloadImage(srcCopy);       // Source copy not required any more... |     UnloadImage(srcCopy);       // Source copy not required any more... | ||||||
|      |  | ||||||
|     Color srcCol, dstCol; |     Color srcCol, dstCol; | ||||||
|  |  | ||||||
|     // Blit pixels, copy source image into destination |     // Blit pixels, copy source image into destination | ||||||
| @@ -1026,13 +1026,13 @@ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec) | |||||||
|             // Alpha blending implementation |             // Alpha blending implementation | ||||||
|             dstCol = dstPixels[j*dst->width + i]; |             dstCol = dstPixels[j*dst->width + i]; | ||||||
|             srcCol = srcPixels[(j - dstRec.y)*dstRec.width + (i - dstRec.x)]; |             srcCol = srcPixels[(j - dstRec.y)*dstRec.width + (i - dstRec.x)]; | ||||||
|              |  | ||||||
|             dstCol.r = ((srcCol.a*(srcCol.r - dstCol.r)) >> 8) + dstCol.r; |             dstCol.r = ((srcCol.a*(srcCol.r - dstCol.r)) >> 8) + dstCol.r; | ||||||
|             dstCol.g = ((srcCol.a*(srcCol.g - dstCol.g)) >> 8) + dstCol.g; |             dstCol.g = ((srcCol.a*(srcCol.g - dstCol.g)) >> 8) + dstCol.g; | ||||||
|             dstCol.b = ((srcCol.a*(srcCol.b - dstCol.b)) >> 8) + dstCol.b; |             dstCol.b = ((srcCol.a*(srcCol.b - dstCol.b)) >> 8) + dstCol.b; | ||||||
|              |  | ||||||
|             dstPixels[j*dst->width + i] = dstCol; |             dstPixels[j*dst->width + i] = dstCol; | ||||||
|              |  | ||||||
|             // TODO: Support other blending options |             // TODO: Support other blending options | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -1369,7 +1369,7 @@ void SetTextureFilter(Texture2D texture, int filterMode) | |||||||
|             { |             { | ||||||
|                 // RL_FILTER_MIP_NEAREST - tex filter: POINT, mipmaps filter: POINT (sharp switching between mipmaps) |                 // RL_FILTER_MIP_NEAREST - tex filter: POINT, mipmaps filter: POINT (sharp switching between mipmaps) | ||||||
|                 rlTextureParameters(texture.id, RL_TEXTURE_MIN_FILTER, RL_FILTER_MIP_NEAREST); |                 rlTextureParameters(texture.id, RL_TEXTURE_MIN_FILTER, RL_FILTER_MIP_NEAREST); | ||||||
|                  |  | ||||||
|                 // RL_FILTER_NEAREST - tex filter: POINT (no filter), no mipmaps |                 // RL_FILTER_NEAREST - tex filter: POINT (no filter), no mipmaps | ||||||
|                 rlTextureParameters(texture.id, RL_TEXTURE_MAG_FILTER, RL_FILTER_NEAREST); |                 rlTextureParameters(texture.id, RL_TEXTURE_MAG_FILTER, RL_FILTER_NEAREST); | ||||||
|             } |             } | ||||||
| @@ -1387,7 +1387,7 @@ void SetTextureFilter(Texture2D texture, int filterMode) | |||||||
|                 // RL_FILTER_LINEAR_MIP_NEAREST - tex filter: BILINEAR, mipmaps filter: POINT (sharp switching between mipmaps) |                 // RL_FILTER_LINEAR_MIP_NEAREST - tex filter: BILINEAR, mipmaps filter: POINT (sharp switching between mipmaps) | ||||||
|                 // Alternative: RL_FILTER_NEAREST_MIP_LINEAR - tex filter: POINT, mipmaps filter: BILINEAR (smooth transition between mipmaps) |                 // Alternative: RL_FILTER_NEAREST_MIP_LINEAR - tex filter: POINT, mipmaps filter: BILINEAR (smooth transition between mipmaps) | ||||||
|                 rlTextureParameters(texture.id, RL_TEXTURE_MIN_FILTER, RL_FILTER_LINEAR_MIP_NEAREST); |                 rlTextureParameters(texture.id, RL_TEXTURE_MIN_FILTER, RL_FILTER_LINEAR_MIP_NEAREST); | ||||||
|                  |  | ||||||
|                 // RL_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps |                 // RL_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps | ||||||
|                 rlTextureParameters(texture.id, RL_TEXTURE_MAG_FILTER, RL_FILTER_LINEAR); |                 rlTextureParameters(texture.id, RL_TEXTURE_MAG_FILTER, RL_FILTER_LINEAR); | ||||||
|             } |             } | ||||||
| @@ -1404,14 +1404,14 @@ void SetTextureFilter(Texture2D texture, int filterMode) | |||||||
|             { |             { | ||||||
|                 // RL_FILTER_MIP_LINEAR - tex filter: BILINEAR, mipmaps filter: BILINEAR (smooth transition between mipmaps) |                 // RL_FILTER_MIP_LINEAR - tex filter: BILINEAR, mipmaps filter: BILINEAR (smooth transition between mipmaps) | ||||||
|                 rlTextureParameters(texture.id, RL_TEXTURE_MIN_FILTER, RL_FILTER_MIP_LINEAR); |                 rlTextureParameters(texture.id, RL_TEXTURE_MIN_FILTER, RL_FILTER_MIP_LINEAR); | ||||||
|                  |  | ||||||
|                 // RL_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps |                 // RL_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps | ||||||
|                 rlTextureParameters(texture.id, RL_TEXTURE_MAG_FILTER, RL_FILTER_LINEAR); |                 rlTextureParameters(texture.id, RL_TEXTURE_MAG_FILTER, RL_FILTER_LINEAR); | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 TraceLog(WARNING, "[TEX ID %i] No mipmaps available for TRILINEAR texture filtering", texture.id); |                 TraceLog(WARNING, "[TEX ID %i] No mipmaps available for TRILINEAR texture filtering", texture.id); | ||||||
|                  |  | ||||||
|                 // RL_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps |                 // RL_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps | ||||||
|                 rlTextureParameters(texture.id, RL_TEXTURE_MIN_FILTER, RL_FILTER_LINEAR); |                 rlTextureParameters(texture.id, RL_TEXTURE_MIN_FILTER, RL_FILTER_LINEAR); | ||||||
|                 rlTextureParameters(texture.id, RL_TEXTURE_MAG_FILTER, RL_FILTER_LINEAR); |                 rlTextureParameters(texture.id, RL_TEXTURE_MAG_FILTER, RL_FILTER_LINEAR); | ||||||
| @@ -2007,19 +2007,19 @@ static Image LoadPVR(const char *fileName) | |||||||
|                 image.mipmaps = pvrHeader.numMipmaps; |                 image.mipmaps = pvrHeader.numMipmaps; | ||||||
|  |  | ||||||
|                 // Check data format |                 // Check data format | ||||||
|                 if (((pvrHeader.channels[0] == 'l') && (pvrHeader.channels[1] == 0)) && (pvrHeader.channelDepth[0] == 8))  |                 if (((pvrHeader.channels[0] == 'l') && (pvrHeader.channels[1] == 0)) && (pvrHeader.channelDepth[0] == 8)) | ||||||
|                     image.format = UNCOMPRESSED_GRAYSCALE; |                     image.format = UNCOMPRESSED_GRAYSCALE; | ||||||
|                 else if (((pvrHeader.channels[0] == 'l') && (pvrHeader.channels[1] == 'a')) && ((pvrHeader.channelDepth[0] == 8) && (pvrHeader.channelDepth[1] == 8)))  |                 else if (((pvrHeader.channels[0] == 'l') && (pvrHeader.channels[1] == 'a')) && ((pvrHeader.channelDepth[0] == 8) && (pvrHeader.channelDepth[1] == 8))) | ||||||
|                     image.format = UNCOMPRESSED_GRAY_ALPHA; |                     image.format = UNCOMPRESSED_GRAY_ALPHA; | ||||||
|                 else if ((pvrHeader.channels[0] == 'r') && (pvrHeader.channels[1] == 'g') && (pvrHeader.channels[2] == 'b')) |                 else if ((pvrHeader.channels[0] == 'r') && (pvrHeader.channels[1] == 'g') && (pvrHeader.channels[2] == 'b')) | ||||||
|                 { |                 { | ||||||
|                     if (pvrHeader.channels[3] == 'a') |                     if (pvrHeader.channels[3] == 'a') | ||||||
|                     { |                     { | ||||||
|                         if ((pvrHeader.channelDepth[0] == 5) && (pvrHeader.channelDepth[1] == 5) && (pvrHeader.channelDepth[2] == 5) && (pvrHeader.channelDepth[3] == 1))  |                         if ((pvrHeader.channelDepth[0] == 5) && (pvrHeader.channelDepth[1] == 5) && (pvrHeader.channelDepth[2] == 5) && (pvrHeader.channelDepth[3] == 1)) | ||||||
|                             image.format = UNCOMPRESSED_R5G5B5A1; |                             image.format = UNCOMPRESSED_R5G5B5A1; | ||||||
|                         else if ((pvrHeader.channelDepth[0] == 4) && (pvrHeader.channelDepth[1] == 4) && (pvrHeader.channelDepth[2] == 4) && (pvrHeader.channelDepth[3] == 4))  |                         else if ((pvrHeader.channelDepth[0] == 4) && (pvrHeader.channelDepth[1] == 4) && (pvrHeader.channelDepth[2] == 4) && (pvrHeader.channelDepth[3] == 4)) | ||||||
|                             image.format = UNCOMPRESSED_R4G4B4A4; |                             image.format = UNCOMPRESSED_R4G4B4A4; | ||||||
|                         else if ((pvrHeader.channelDepth[0] == 8) && (pvrHeader.channelDepth[1] == 8) && (pvrHeader.channelDepth[2] == 8) && (pvrHeader.channelDepth[3] == 8))  |                         else if ((pvrHeader.channelDepth[0] == 8) && (pvrHeader.channelDepth[1] == 8) && (pvrHeader.channelDepth[2] == 8) && (pvrHeader.channelDepth[3] == 8)) | ||||||
|                             image.format = UNCOMPRESSED_R8G8B8A8; |                             image.format = UNCOMPRESSED_R8G8B8A8; | ||||||
|                     } |                     } | ||||||
|                     else if (pvrHeader.channels[3] == 0) |                     else if (pvrHeader.channels[3] == 0) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Ray
					Ray