Merge remote-tracking branch 'refs/remotes/raysan5/develop' into develop
This commit is contained in:
commit
80f6b2f963
@ -47,7 +47,7 @@ int main()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(&camera); // Update camera and player position
|
||||
UpdateCamera(&camera); // Update camera
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
|
@ -39,7 +39,7 @@ int main()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(&camera); // Update internal camera and our camera
|
||||
UpdateCamera(&camera); // Update camera
|
||||
|
||||
if (IsKeyDown('Z')) camera.target = (Vector3){ 0.0f, 0.0f, 0.0f };
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -22,7 +22,7 @@ int main()
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
Camera camera;
|
||||
camera.position = (Vector3){ 0.0f, 10.0f, 10.0f }; // Camera position
|
||||
camera.position = (Vector3){ 10.0f, 10.0f, 10.0f }; // Camera position
|
||||
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point
|
||||
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
|
||||
camera.fovy = 45.0f; // Camera field-of-view Y
|
||||
@ -34,9 +34,7 @@ int main()
|
||||
|
||||
bool collision = false;
|
||||
|
||||
SetCameraMode(CAMERA_FREE); // Set a free camera mode
|
||||
SetCameraPosition(camera.position); // Set internal camera position to match our camera position
|
||||
SetCameraFovy(camera.fovy); // Set internal camera field-of-view Y
|
||||
SetCameraMode(camera, CAMERA_FREE); // Set a free camera mode
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
@ -46,7 +44,7 @@ int main()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(&camera); // Update internal camera and our camera
|
||||
UpdateCamera(&camera); // Update camera
|
||||
|
||||
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
|
||||
{
|
||||
|
@ -30,13 +30,15 @@ int main()
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
Camera camera;
|
||||
camera.position = (Vector3){ 5.0f, 5.0f, 5.0f }; // Camera position
|
||||
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point
|
||||
camera.position = (Vector3){ 5.0f, 2.0f, 5.0f }; // Camera position
|
||||
camera.target = (Vector3){ 0.0f, 2.0f, 0.0f }; // Camera looking at point
|
||||
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
|
||||
camera.fovy = 60.0f; // Camera field-of-view Y
|
||||
|
||||
Vector3 cubePosition = { 0.0f, 0.0f, 0.0f };
|
||||
|
||||
SetCameraMode(camera, CAMERA_FIRST_PERSON); // Set first person camera mode
|
||||
|
||||
SetTargetFPS(90); // Set our game to run at 90 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
@ -45,9 +47,10 @@ int main()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateVrTracking();
|
||||
if (IsVrSimulator()) UpdateCamera(&camera); // Update camera (simulator mode)
|
||||
else UpdateVrTracking(&camera); // Update camera with device tracking data
|
||||
|
||||
if (IsKeyPressed(KEY_SPACE)) ToggleVrMode();
|
||||
if (IsKeyPressed(KEY_SPACE)) ToggleVrMode(); // Toggle VR mode
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
@ -61,7 +64,7 @@ int main()
|
||||
DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED);
|
||||
DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON);
|
||||
|
||||
DrawGrid(10, 1.0f);
|
||||
DrawGrid(40, 1.0f);
|
||||
|
||||
End3dMode();
|
||||
|
||||
|
@ -21,16 +21,13 @@ int main()
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera free");
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f };
|
||||
Camera camera = {{ 10.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f };
|
||||
|
||||
Vector3 cubePosition = { 0.0f, 0.0f, 0.0f };
|
||||
|
||||
Vector2 cubeScreenPosition;
|
||||
|
||||
SetCameraMode(CAMERA_FREE); // Set a free camera mode
|
||||
SetCameraPosition(camera.position); // Set internal camera position to match our camera position
|
||||
SetCameraTarget(camera.target); // Set internal camera target to match our camera target
|
||||
SetCameraFovy(camera.fovy); // Set internal camera field-of-view Y
|
||||
SetCameraMode(camera, CAMERA_FREE); // Set a free camera mode
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
@ -40,7 +37,7 @@ int main()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(&camera); // Update internal camera and our camera
|
||||
UpdateCamera(&camera); // Update camera
|
||||
|
||||
// Calculate cube screen space position (with a little offset to be in top)
|
||||
cubeScreenPosition = GetWorldToScreen((Vector3){cubePosition.x, cubePosition.y + 2.5f, cubePosition.z}, camera);
|
||||
|
@ -26,20 +26,17 @@ int main()
|
||||
Texture2D bill = LoadTexture("resources/billboard.png"); // Our texture billboard
|
||||
Vector3 billPosition = { 0.0f, 2.0f, 0.0f }; // Position where draw billboard
|
||||
|
||||
SetCameraMode(CAMERA_ORBITAL); // Set an orbital camera mode
|
||||
SetCameraPosition(camera.position); // Set internal camera position to match our camera position
|
||||
SetCameraTarget(camera.target); // Set internal camera target to match our camera target
|
||||
SetCameraFovy(camera.fovy); // Set internal camera field-of-view Y
|
||||
SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(&camera); // Update internal camera and our camera
|
||||
UpdateCamera(&camera); // Update camera
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
|
@ -45,7 +45,7 @@ int main()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(&camera); // Update internal camera and our camera
|
||||
UpdateCamera(&camera); // Update camera
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
|
@ -29,20 +29,19 @@ int main()
|
||||
map.material.texDiffuse = texture; // Set map diffuse texture
|
||||
Vector3 mapPosition = { -8.0f, 0.0f, -8.0f }; // Set model position (depends on model scaling!)
|
||||
|
||||
UnloadImage(image); // Unload heightmap image from RAM, already uploaded to VRAM
|
||||
UnloadImage(image); // Unload heightmap image from RAM, already uploaded to VRAM
|
||||
|
||||
SetCameraMode(CAMERA_ORBITAL); // Set an orbital camera mode
|
||||
SetCameraPosition(camera.position); // Set internal camera position to match our custom camera position
|
||||
SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(&camera); // Update internal camera and our camera
|
||||
UpdateCamera(&camera); // Update camera
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
|
@ -38,7 +38,6 @@ uniform Light lights[maxLights];
|
||||
|
||||
vec3 ComputeLightPoint(Light l, vec3 n, vec3 v, float s)
|
||||
{
|
||||
/*
|
||||
vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1.0));
|
||||
vec3 surfaceToLight = l.position - surfacePos;
|
||||
|
||||
@ -51,17 +50,14 @@ vec3 ComputeLightPoint(Light l, vec3 n, vec3 v, float s)
|
||||
if (diff > 0.0)
|
||||
{
|
||||
vec3 h = normalize(-l.direction + v);
|
||||
spec = pow(dot(n, h), 3.0 + glossiness)*s;
|
||||
spec = pow(abs(dot(n, h)), 3.0 + glossiness)*s;
|
||||
}
|
||||
|
||||
return (diff*l.diffuse.rgb + spec*colSpecular.rgb);
|
||||
*/
|
||||
return vec3(0.5);
|
||||
}
|
||||
|
||||
vec3 ComputeLightDirectional(Light l, vec3 n, vec3 v, float s)
|
||||
{
|
||||
/*
|
||||
vec3 lightDir = normalize(-l.direction);
|
||||
|
||||
// Diffuse shading
|
||||
@ -72,18 +68,15 @@ vec3 ComputeLightDirectional(Light l, vec3 n, vec3 v, float s)
|
||||
if (diff > 0.0)
|
||||
{
|
||||
vec3 h = normalize(lightDir + v);
|
||||
spec = pow(dot(n, h), 3.0 + glossiness)*s;
|
||||
spec = pow(abs(dot(n, h)), 3.0 + glossiness)*s;
|
||||
}
|
||||
|
||||
// Combine results
|
||||
return (diff*l.intensity*l.diffuse.rgb + spec*colSpecular.rgb);
|
||||
*/
|
||||
return vec3(0.5);
|
||||
}
|
||||
|
||||
vec3 ComputeLightSpot(Light l, vec3 n, vec3 v, float s)
|
||||
{
|
||||
/*
|
||||
vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1));
|
||||
vec3 lightToSurface = normalize(surfacePos - l.position);
|
||||
vec3 lightDir = normalize(-l.direction);
|
||||
@ -108,12 +101,10 @@ vec3 ComputeLightSpot(Light l, vec3 n, vec3 v, float s)
|
||||
if (diffAttenuation > 0.0)
|
||||
{
|
||||
vec3 h = normalize(lightDir + v);
|
||||
spec = pow(dot(n, h), 3.0 + glossiness)*s;
|
||||
spec = pow(abs(dot(n, h)), 3.0 + glossiness)*s;
|
||||
}
|
||||
|
||||
return (falloff*(diffAttenuation*l.diffuse.rgb + spec*colSpecular.rgb));
|
||||
*/
|
||||
return vec3(0.5);
|
||||
}
|
||||
|
||||
void main()
|
||||
@ -140,7 +131,7 @@ void main()
|
||||
|
||||
// Calculate specular texture color fetching or set to maximum specular value by default
|
||||
float spec = 1.0;
|
||||
if (useSpecular == 1) spec *= normalize(texture2D(texture2, fragTexCoord).r);
|
||||
if (useSpecular == 1) spec = texture2D(texture2, fragTexCoord).r;
|
||||
|
||||
for (int i = 0; i < maxLights; i++)
|
||||
{
|
||||
|
@ -50,7 +50,7 @@ vec3 ComputeLightPoint(Light l, vec3 n, vec3 v, float s)
|
||||
if (diff > 0.0)
|
||||
{
|
||||
vec3 h = normalize(-l.direction + v);
|
||||
spec = pow(dot(n, h), 3.0 + glossiness)*s;
|
||||
spec = pow(abs(dot(n, h)), 3.0 + glossiness)*s;
|
||||
}
|
||||
|
||||
return (diff*l.diffuse.rgb + spec*colSpecular.rgb);
|
||||
@ -68,7 +68,7 @@ vec3 ComputeLightDirectional(Light l, vec3 n, vec3 v, float s)
|
||||
if (diff > 0.0)
|
||||
{
|
||||
vec3 h = normalize(lightDir + v);
|
||||
spec = pow(dot(n, h), 3.0 + glossiness)*s;
|
||||
spec = pow(abs(dot(n, h)), 3.0 + glossiness)*s;
|
||||
}
|
||||
|
||||
// Combine results
|
||||
@ -101,7 +101,7 @@ vec3 ComputeLightSpot(Light l, vec3 n, vec3 v, float s)
|
||||
if (diffAttenuation > 0.0)
|
||||
{
|
||||
vec3 h = normalize(lightDir + v);
|
||||
spec = pow(dot(n, h), 3.0 + glossiness)*s;
|
||||
spec = pow(abs(dot(n, h)), 3.0 + glossiness)*s;
|
||||
}
|
||||
|
||||
return (falloff*(diffAttenuation*l.diffuse.rgb + spec*colSpecular.rgb));
|
||||
@ -131,7 +131,7 @@ void main()
|
||||
|
||||
// Calculate specular texture color fetching or set to maximum specular value by default
|
||||
float spec = 1.0;
|
||||
if (useSpecular == 1) spec *= normalize(texture(texture2, fragTexCoord).r);
|
||||
if (useSpecular == 1) spec = texture(texture2, fragTexCoord).r;
|
||||
|
||||
for (int i = 0; i < maxLights; i++)
|
||||
{
|
||||
|
@ -51,9 +51,7 @@ int main()
|
||||
RenderTexture2D target = LoadRenderTexture(screenWidth, screenHeight);
|
||||
|
||||
// Setup orbital camera
|
||||
SetCameraMode(CAMERA_ORBITAL); // Set an orbital camera mode
|
||||
SetCameraPosition(camera.position); // Set internal camera position to match our camera position
|
||||
SetCameraTarget(camera.target); // Set internal camera target to match our camera target
|
||||
SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
@ -71,7 +69,7 @@ int main()
|
||||
// Send new value to the shader to be used on drawing
|
||||
SetShaderValue(shader, swirlCenterLoc, swirlCenter, 2);
|
||||
|
||||
UpdateCamera(&camera); // Update internal camera and our camera
|
||||
UpdateCamera(&camera); // Update camera
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
|
@ -42,7 +42,7 @@ int main()
|
||||
|
||||
Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position
|
||||
|
||||
SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode
|
||||
SetCameraMode(camera, CAMERA_FREE); // Set an orbital camera mode
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
@ -70,6 +70,9 @@ int main()
|
||||
End3dMode();
|
||||
|
||||
DrawText("(c) Dwarf 3D model by David Moreno", screenWidth - 200, screenHeight - 20, 10, GRAY);
|
||||
|
||||
DrawText(FormatText("Camera position: (%.2f, %.2f, %.2f)", camera.position.x, camera.position.y, camera.position.z), 600, 20, 10, BLACK);
|
||||
DrawText(FormatText("Camera target: (%.2f, %.2f, %.2f)", camera.target.x, camera.target.y, camera.target.z), 600, 40, 10, GRAY);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
|
@ -45,9 +45,7 @@ int main()
|
||||
RenderTexture2D target = LoadRenderTexture(screenWidth, screenHeight);
|
||||
|
||||
// Setup orbital camera
|
||||
SetCameraMode(CAMERA_ORBITAL); // Set an orbital camera mode
|
||||
SetCameraPosition(camera.position); // Set internal camera position to match our camera position
|
||||
SetCameraTarget(camera.target); // Set internal camera target to match our camera target
|
||||
SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
@ -57,7 +55,7 @@ int main()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(&camera); // Update internal camera and our camera
|
||||
UpdateCamera(&camera); // Update camera
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
@ -67,7 +65,7 @@ int main()
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
BeginTextureMode(target); // Enable drawing to texture
|
||||
|
||||
|
||||
Begin3dMode(camera);
|
||||
|
||||
DrawModel(dwarf, position, 2.0f, WHITE); // Draw 3d model with texture
|
||||
|
@ -64,9 +64,7 @@ int main()
|
||||
pointLight->radius = 3.0f;
|
||||
|
||||
// Setup orbital camera
|
||||
SetCameraMode(CAMERA_ORBITAL); // Set an orbital camera mode
|
||||
SetCameraPosition(camera.position); // Set internal camera position to match our camera position
|
||||
SetCameraTarget(camera.target); // Set internal camera target to match our camera target
|
||||
SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
@ -76,7 +74,7 @@ int main()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(&camera); // Update internal camera and our camera
|
||||
UpdateCamera(&camera); // Update camera
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
|
64
src/audio.c
64
src/audio.c
@ -79,6 +79,10 @@
|
||||
#define JAR_MOD_IMPLEMENTATION
|
||||
#include "external/jar_mod.h" // MOD loading functions
|
||||
|
||||
#define DR_FLAC_IMPLEMENTATION
|
||||
#define DR_FLAC_NO_WIN32_IO
|
||||
#include "external/dr_flac.h" // FLAC loading functions
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#undef bool
|
||||
#endif
|
||||
@ -98,12 +102,13 @@
|
||||
// Types and Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
typedef enum { MUSIC_AUDIO_OGG = 0, MUSIC_MODULE_XM, MUSIC_MODULE_MOD } MusicContextType;
|
||||
typedef enum { MUSIC_AUDIO_OGG = 0, MUSIC_AUDIO_FLAC, MUSIC_MODULE_XM, MUSIC_MODULE_MOD } MusicContextType;
|
||||
|
||||
// Music type (file streaming from memory)
|
||||
typedef struct MusicData {
|
||||
MusicContextType ctxType; // Type of music context (OGG, XM, MOD)
|
||||
stb_vorbis *ctxOgg; // OGG audio context
|
||||
drflac *ctxFlac; // FLAC audio context
|
||||
jar_xm_context_t *ctxXm; // XM chiptune context
|
||||
jar_mod_context_t ctxMod; // MOD chiptune context
|
||||
|
||||
@ -128,6 +133,7 @@ typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType;
|
||||
//----------------------------------------------------------------------------------
|
||||
static Wave LoadWAV(const char *fileName); // Load WAV file
|
||||
static Wave LoadOGG(const char *fileName); // Load OGG file
|
||||
static Wave LoadFLAC(const char *fileName); // Load FLAC file
|
||||
|
||||
#if defined(AUDIO_STANDALONE)
|
||||
const char *GetExtension(const char *fileName); // Get the extension for a filename
|
||||
@ -212,6 +218,7 @@ Wave LoadWave(const char *fileName)
|
||||
|
||||
if (strcmp(GetExtension(fileName), "wav") == 0) wave = LoadWAV(fileName);
|
||||
else if (strcmp(GetExtension(fileName), "ogg") == 0) wave = LoadOGG(fileName);
|
||||
else if (strcmp(GetExtension(fileName), "flac") == 0) wave = LoadFLAC(fileName);
|
||||
else TraceLog(WARNING, "[%s] File extension not recognized, it can't be loaded", fileName);
|
||||
|
||||
return wave;
|
||||
@ -672,7 +679,7 @@ Music LoadMusicStream(const char *fileName)
|
||||
// Open ogg audio stream
|
||||
music->ctxOgg = stb_vorbis_open_filename(fileName, NULL, NULL);
|
||||
|
||||
if (music->ctxOgg == NULL) TraceLog(WARNING, "[%s] OGG audio file could not be opened", fileName);
|
||||
if (music->ctxOgg == NULL) TraceLog(WARNING, "[%s] OGG audio file could not be opened", fileName);
|
||||
else
|
||||
{
|
||||
stb_vorbis_info info = stb_vorbis_get_info(music->ctxOgg); // Get Ogg file info
|
||||
@ -691,6 +698,24 @@ Music LoadMusicStream(const char *fileName)
|
||||
|
||||
}
|
||||
}
|
||||
else if (strcmp(GetExtension(fileName), "flac") == 0)
|
||||
{
|
||||
music->ctxFlac = drflac_open_file(fileName);
|
||||
|
||||
if (music->ctxFlac == NULL) TraceLog(WARNING, "[%s] FLAC audio file could not be opened", fileName);
|
||||
else
|
||||
{
|
||||
music->stream = InitAudioStream(music->ctxFlac->sampleRate, music->ctxFlac->bitsPerSample, music->ctxFlac->channels);
|
||||
music->totalSamples = (unsigned int)music->ctxFlac->totalSampleCount;
|
||||
music->samplesLeft = music->totalSamples;
|
||||
music->ctxType = MUSIC_AUDIO_FLAC;
|
||||
music->loop = true; // We loop by default
|
||||
|
||||
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 channels: %i", fileName, music->ctxFlac->channels);
|
||||
}
|
||||
}
|
||||
else if (strcmp(GetExtension(fileName), "xm") == 0)
|
||||
{
|
||||
int result = jar_xm_create_context_from_file(&music->ctxXm, 48000, fileName);
|
||||
@ -739,6 +764,7 @@ void UnloadMusicStream(Music music)
|
||||
CloseAudioStream(music->stream);
|
||||
|
||||
if (music->ctxType == MUSIC_AUDIO_OGG) stb_vorbis_close(music->ctxOgg);
|
||||
else if (music->ctxType == MUSIC_AUDIO_FLAC) drflac_free(music->ctxFlac);
|
||||
else if (music->ctxType == MUSIC_MODULE_XM) jar_xm_free_context(music->ctxXm);
|
||||
else if (music->ctxType == MUSIC_MODULE_MOD) jar_mod_unload(&music->ctxMod);
|
||||
|
||||
@ -818,6 +844,20 @@ void UpdateMusicStream(Music music)
|
||||
UpdateAudioStream(music->stream, pcm, numSamplesOgg*music->stream.channels);
|
||||
music->samplesLeft -= (numSamplesOgg*music->stream.channels);
|
||||
|
||||
} break;
|
||||
case MUSIC_AUDIO_FLAC:
|
||||
{
|
||||
if (music->samplesLeft >= AUDIO_BUFFER_SIZE) numSamples = AUDIO_BUFFER_SIZE;
|
||||
else numSamples = music->samplesLeft;
|
||||
|
||||
int pcmi[AUDIO_BUFFER_SIZE];
|
||||
|
||||
// NOTE: Returns the number of samples to process (should be the same as numSamples)
|
||||
unsigned int numSamplesFlac = (unsigned int)drflac_read_s32(music->ctxFlac, numSamples, pcmi);
|
||||
|
||||
UpdateAudioStream(music->stream, pcmi, numSamplesFlac*music->stream.channels);
|
||||
music->samplesLeft -= (numSamples*music->stream.channels);
|
||||
|
||||
} break;
|
||||
case MUSIC_MODULE_XM:
|
||||
{
|
||||
@ -1197,7 +1237,7 @@ static Wave LoadOGG(const char *fileName)
|
||||
|
||||
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);
|
||||
|
||||
int totalSamples = totalSeconds*info.sample_rate*info.channels;
|
||||
int totalSamples = (int)(totalSeconds*info.sample_rate*info.channels);
|
||||
wave.sampleCount = totalSamples;
|
||||
|
||||
wave.data = (short *)malloc(totalSamplesLength*sizeof(short));
|
||||
@ -1214,6 +1254,24 @@ static Wave LoadOGG(const char *fileName)
|
||||
return wave;
|
||||
}
|
||||
|
||||
// Load FLAC file into Wave structure
|
||||
// NOTE: Using dr_flac library
|
||||
static Wave LoadFLAC(const char *fileName)
|
||||
{
|
||||
Wave wave;
|
||||
|
||||
// Decode an entire FLAC file in one go
|
||||
uint64_t totalSampleCount;
|
||||
wave.data = drflac_open_and_decode_file_s32(fileName, &wave.channels, &wave.sampleRate, &totalSampleCount);
|
||||
|
||||
wave.sampleCount = (int)totalSampleCount;
|
||||
wave.sampleSize = 32;
|
||||
|
||||
if (wave.data == NULL) TraceLog(WARNING, "[%s] FLAC data could not be loaded", fileName);
|
||||
|
||||
return wave;
|
||||
}
|
||||
|
||||
// Some required functions for audio standalone module version
|
||||
#if defined(AUDIO_STANDALONE)
|
||||
// Get the extension for a filename
|
||||
|
447
src/core.c
447
src/core.c
@ -18,7 +18,11 @@
|
||||
*
|
||||
* On PLATFORM_RPI, graphic device is managed by EGL and input system is coded in raw mode.
|
||||
*
|
||||
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
|
||||
* Module Configuration Flags:
|
||||
*
|
||||
* RL_LOAD_DEFAULT_FONT - Use external module functions to load default raylib font (module: text)
|
||||
*
|
||||
* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||
* will the authors be held liable for any damages arising from the use of this software.
|
||||
@ -54,12 +58,12 @@
|
||||
#endif
|
||||
|
||||
#include <stdio.h> // Standard input / output lib
|
||||
#include <stdlib.h> // Declares malloc() and free() for memory management, rand(), atexit()
|
||||
#include <stdint.h> // Required for typedef unsigned long long int uint64_t, used by hi-res timer
|
||||
#include <time.h> // Useful to initialize random seed - Android/RPI hi-res timer (NOTE: Linux only!)
|
||||
#include <math.h> // Math related functions, tan() used to set perspective
|
||||
#include <string.h> // String function definitions, memset()
|
||||
#include <errno.h> // Macros for reporting and retrieving error conditions through error codes
|
||||
#include <stdlib.h> // Required for: malloc(), free(), rand(), atexit()
|
||||
#include <stdint.h> // Required for: typedef unsigned long long int uint64_t, used by hi-res timer
|
||||
#include <time.h> // Required for: time() - Android/RPI hi-res timer (NOTE: Linux only!)
|
||||
#include <math.h> // Required for: tan() [Used in Begin3dMode() to set perspective]
|
||||
#include <string.h> // Required for: strcmp()
|
||||
//#include <errno.h> // Macros for reporting and retrieving error conditions through error codes
|
||||
|
||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
||||
//#define GLFW_INCLUDE_NONE // Disable the standard OpenGL header inclusion on GLFW3
|
||||
@ -75,8 +79,7 @@
|
||||
#endif
|
||||
|
||||
#if defined(PLATFORM_ANDROID)
|
||||
#include <jni.h> // Java native interface
|
||||
#include <android/sensor.h> // Android sensors functions
|
||||
//#include <android/sensor.h> // Android sensors functions (accelerometer, gyroscope, light...)
|
||||
#include <android/window.h> // Defines AWINDOW_FLAG_FULLSCREEN and others
|
||||
#include <android_native_app_glue.h> // Defines basic app state struct and manages activity
|
||||
|
||||
@ -124,12 +127,14 @@
|
||||
//#define DEFAULT_GAMEPAD_DEV "/dev/input/eventN"
|
||||
|
||||
#define MOUSE_SENSITIVITY 0.8f
|
||||
|
||||
#define MAX_GAMEPADS 2 // Max number of gamepads supported
|
||||
#define MAX_GAMEPAD_BUTTONS 11 // Max bumber of buttons supported (per gamepad)
|
||||
#define MAX_GAMEPAD_AXIS 8 // Max number of axis supported (per gamepad)
|
||||
#endif
|
||||
|
||||
#define MAX_GAMEPADS 4 // Max number of gamepads supported
|
||||
#define MAX_GAMEPAD_BUTTONS 32 // Max bumber of buttons supported (per gamepad)
|
||||
#define MAX_GAMEPAD_AXIS 8 // Max number of axis supported (per gamepad)
|
||||
|
||||
#define RL_LOAD_DEFAULT_FONT // Load default font on window initialization (module: text)
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
@ -152,9 +157,6 @@ static const char *internalDataPath; // Android internal data path to
|
||||
static bool windowReady = false; // Used to detect display initialization
|
||||
static bool appEnabled = true; // Used to detec if app is active
|
||||
static bool contextRebindRequired = false; // Used to know context rebind required
|
||||
|
||||
static int previousButtonState[128] = { 1 }; // Required to check if button pressed/released once
|
||||
static int currentButtonState[128] = { 1 }; // Required to check if button pressed/released once
|
||||
#endif
|
||||
|
||||
#if defined(PLATFORM_RPI)
|
||||
@ -168,15 +170,11 @@ static int defaultKeyboardMode; // Used to store default keyboar
|
||||
// Mouse input variables
|
||||
static int mouseStream = -1; // Mouse device file descriptor
|
||||
static bool mouseReady = false; // Flag to know if mouse is ready
|
||||
pthread_t mouseThreadId; // Mouse reading thread id
|
||||
static pthread_t mouseThreadId; // Mouse reading thread id
|
||||
|
||||
// Gamepad input variables
|
||||
static int gamepadStream[MAX_GAMEPADS] = { -1 }; // Gamepad device file descriptor (two gamepads supported)
|
||||
static bool gamepadReady[MAX_GAMEPADS] = { false }; // Flag to know if gamepad is ready (two gamepads supported)
|
||||
pthread_t gamepadThreadId; // Gamepad reading thread id
|
||||
|
||||
int gamepadButtons[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Gamepad buttons state
|
||||
float gamepadAxisValues[MAX_GAMEPADS][MAX_GAMEPAD_AXIS]; // Gamepad axis state
|
||||
static int gamepadStream[MAX_GAMEPADS] = { -1 };// Gamepad device file descriptor
|
||||
static pthread_t gamepadThreadId; // Gamepad reading thread id
|
||||
#endif
|
||||
|
||||
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
|
||||
@ -200,25 +198,32 @@ static Matrix downscaleView; // Matrix to downscale view (in case
|
||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
|
||||
static const char *windowTitle; // Window text title...
|
||||
static bool cursorOnScreen = false; // Tracks if cursor is inside client area
|
||||
static bool cursorHidden = false; // Track if cursor is hidden
|
||||
|
||||
static char previousKeyState[512] = { 0 }; // Required to check if key pressed/released once
|
||||
static char currentKeyState[512] = { 0 }; // Required to check if key pressed/released once
|
||||
// Register mouse states
|
||||
static char previousMouseState[3] = { 0 }; // Registers previous mouse button state
|
||||
static char currentMouseState[3] = { 0 }; // Registers current mouse button state
|
||||
static int previousMouseWheelY = 0; // Registers previous mouse wheel variation
|
||||
static int currentMouseWheelY = 0; // Registers current mouse wheel variation
|
||||
|
||||
static char previousGamepadState[32] = {0}; // Required to check if gamepad btn pressed/released once
|
||||
static char currentGamepadState[32] = {0}; // Required to check if gamepad btn pressed/released once
|
||||
|
||||
static char previousMouseState[3] = { 0 }; // Required to check if mouse btn pressed/released once
|
||||
static char currentMouseState[3] = { 0 }; // Required to check if mouse btn pressed/released once
|
||||
|
||||
static int previousMouseWheelY = 0; // Required to track mouse wheel variation
|
||||
static int currentMouseWheelY = 0; // Required to track mouse wheel variation
|
||||
// Register gamepads states
|
||||
static bool gamepadReady[MAX_GAMEPADS] = { false }; // Flag to know if gamepad is ready
|
||||
static float gamepadAxisState[MAX_GAMEPADS][MAX_GAMEPAD_AXIS]; // Gamepad axis state
|
||||
static char previousGamepadState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Previous gamepad buttons state
|
||||
static char currentGamepadState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Current gamepad buttons state
|
||||
|
||||
// Keyboard configuration
|
||||
static int exitKey = KEY_ESCAPE; // Default exit key (ESC)
|
||||
static int lastKeyPressed = -1; // Register last key pressed
|
||||
|
||||
static bool cursorHidden; // Track if cursor is hidden
|
||||
#endif
|
||||
|
||||
// Register keyboard states
|
||||
static char previousKeyState[512] = { 0 }; // Registers previous frame key state
|
||||
static char currentKeyState[512] = { 0 }; // Registers current frame key state
|
||||
|
||||
static int lastKeyPressed = -1; // Register last key pressed
|
||||
static int lastGamepadButtonPressed = -1; // Register last gamepad button pressed
|
||||
static int gamepadAxisCount = 0; // Register number of available gamepad axis
|
||||
|
||||
static Vector2 mousePosition; // Mouse position on screen
|
||||
static Vector2 touchPosition[MAX_TOUCH_POINTS]; // Touch position on screen
|
||||
|
||||
@ -238,11 +243,10 @@ static bool showLogo = false; // Track if showing logo at init is
|
||||
//----------------------------------------------------------------------------------
|
||||
// Other Modules Functions Declaration (required by core)
|
||||
//----------------------------------------------------------------------------------
|
||||
#if defined(RL_LOAD_DEFAULT_FONT)
|
||||
extern void LoadDefaultFont(void); // [Module: text] Loads default font on InitWindow()
|
||||
extern void UnloadDefaultFont(void); // [Module: text] Unloads default font from GPU memory
|
||||
|
||||
extern void ProcessGestureEvent(GestureEvent event); // [Module: gestures] Process gesture event and translate it into gestures
|
||||
extern void UpdateGestures(void); // [Module: gestures] Update gestures detected (called in PollInputEvents())
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module specific Functions Declaration
|
||||
@ -311,9 +315,11 @@ void InitWindow(int width, int height, const char *title)
|
||||
// Init graphics device (display device and OpenGL context)
|
||||
InitGraphicsDevice(width, height);
|
||||
|
||||
// Load default font for convenience
|
||||
#if defined(RL_LOAD_DEFAULT_FONT)
|
||||
// Load default font
|
||||
// NOTE: External function (defined in module: text)
|
||||
LoadDefaultFont();
|
||||
#endif
|
||||
|
||||
// Init hi-res timer
|
||||
InitTimer();
|
||||
@ -355,7 +361,7 @@ void InitWindow(int width, int height, const char *title)
|
||||
|
||||
#if defined(PLATFORM_ANDROID)
|
||||
// Android activity initialization
|
||||
void InitWindow(int width, int height, struct android_app *state)
|
||||
void InitWindow(int width, int height, void *state)
|
||||
{
|
||||
TraceLog(INFO, "Initializing raylib (v1.6.0)");
|
||||
|
||||
@ -364,7 +370,7 @@ void InitWindow(int width, int height, struct android_app *state)
|
||||
screenWidth = width;
|
||||
screenHeight = height;
|
||||
|
||||
app = state;
|
||||
app = (struct android_app *)state;
|
||||
internalDataPath = app->activity->internalDataPath;
|
||||
|
||||
// Set desired windows flags before initializing anything
|
||||
@ -420,7 +426,9 @@ void InitWindow(int width, int height, struct android_app *state)
|
||||
// Close Window and Terminate Context
|
||||
void CloseWindow(void)
|
||||
{
|
||||
#if defined(RL_LOAD_DEFAULT_FONT)
|
||||
UnloadDefaultFont();
|
||||
#endif
|
||||
|
||||
rlglClose(); // De-init rlgl
|
||||
|
||||
@ -456,6 +464,9 @@ void CloseWindow(void)
|
||||
// Wait for mouse and gamepad threads to finish before closing
|
||||
// NOTE: Those threads should already have finished at this point
|
||||
// because they are controlled by windowShouldClose variable
|
||||
|
||||
windowShouldClose = true; // Added to force threads to exit when the close window is called
|
||||
|
||||
pthread_join(mouseThreadId, NULL);
|
||||
pthread_join(gamepadThreadId, NULL);
|
||||
#endif
|
||||
@ -516,6 +527,65 @@ int GetScreenHeight(void)
|
||||
return screenHeight;
|
||||
}
|
||||
|
||||
#if !defined(PLATFORM_ANDROID)
|
||||
// Show mouse cursor
|
||||
void ShowCursor()
|
||||
{
|
||||
#if defined(PLATFORM_DESKTOP)
|
||||
#ifdef __linux
|
||||
XUndefineCursor(glfwGetX11Display(), glfwGetX11Window(window));
|
||||
#else
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
#endif
|
||||
#endif
|
||||
cursorHidden = false;
|
||||
}
|
||||
|
||||
// Hide mouse cursor
|
||||
void HideCursor()
|
||||
{
|
||||
#if defined(PLATFORM_DESKTOP)
|
||||
#ifdef __linux
|
||||
XColor Col;
|
||||
const char Nil[] = {0};
|
||||
|
||||
Pixmap Pix = XCreateBitmapFromData(glfwGetX11Display(), glfwGetX11Window(window), Nil, 1, 1);
|
||||
Cursor Cur = XCreatePixmapCursor(glfwGetX11Display(), Pix, Pix, &Col, &Col, 0, 0);
|
||||
|
||||
XDefineCursor(glfwGetX11Display(), glfwGetX11Window(window), Cur);
|
||||
XFreeCursor(glfwGetX11Display(), Cur);
|
||||
#else
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
||||
#endif
|
||||
#endif
|
||||
cursorHidden = true;
|
||||
}
|
||||
|
||||
// Check if mouse cursor is hidden
|
||||
bool IsCursorHidden()
|
||||
{
|
||||
return cursorHidden;
|
||||
}
|
||||
|
||||
// Enable mouse cursor
|
||||
void EnableCursor()
|
||||
{
|
||||
#if defined(PLATFORM_DESKTOP)
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
#endif
|
||||
cursorHidden = false;
|
||||
}
|
||||
|
||||
// Disable mouse cursor
|
||||
void DisableCursor()
|
||||
{
|
||||
#if defined(PLATFORM_DESKTOP)
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
#endif
|
||||
cursorHidden = true;
|
||||
}
|
||||
#endif // !defined(PLATFORM_ANDROID)
|
||||
|
||||
// Sets Background Color
|
||||
void ClearBackground(Color color)
|
||||
{
|
||||
@ -1034,7 +1104,6 @@ Matrix GetCameraMatrix(Camera camera)
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition - Input (Keyboard, Mouse, Gamepad) Functions
|
||||
//----------------------------------------------------------------------------------
|
||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
|
||||
// Detect if a key has been pressed once
|
||||
bool IsKeyPressed(int key)
|
||||
{
|
||||
@ -1057,7 +1126,7 @@ bool IsKeyDown(int key)
|
||||
bool IsKeyReleased(int key)
|
||||
{
|
||||
bool released = false;
|
||||
|
||||
|
||||
if ((currentKeyState[key] != previousKeyState[key]) && (currentKeyState[key] == 0)) released = true;
|
||||
else released = false;
|
||||
|
||||
@ -1081,64 +1150,9 @@ int GetKeyPressed(void)
|
||||
// NOTE: default exitKey is ESCAPE
|
||||
void SetExitKey(int key)
|
||||
{
|
||||
#if !defined(PLATFORM_ANDROID)
|
||||
exitKey = key;
|
||||
}
|
||||
|
||||
// Hide mouse cursor
|
||||
void HideCursor()
|
||||
{
|
||||
#if defined(PLATFORM_DESKTOP)
|
||||
#ifdef __linux
|
||||
XColor Col;
|
||||
const char Nil[] = {0};
|
||||
|
||||
Pixmap Pix = XCreateBitmapFromData(glfwGetX11Display(), glfwGetX11Window(window), Nil, 1, 1);
|
||||
Cursor Cur = XCreatePixmapCursor(glfwGetX11Display(), Pix, Pix, &Col, &Col, 0, 0);
|
||||
|
||||
XDefineCursor(glfwGetX11Display(), glfwGetX11Window(window), Cur);
|
||||
XFreeCursor(glfwGetX11Display(), Cur);
|
||||
#else
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
||||
#endif
|
||||
#endif
|
||||
cursorHidden = true;
|
||||
}
|
||||
|
||||
// Show mouse cursor
|
||||
void ShowCursor()
|
||||
{
|
||||
#if defined(PLATFORM_DESKTOP)
|
||||
#ifdef __linux
|
||||
XUndefineCursor(glfwGetX11Display(), glfwGetX11Window(window));
|
||||
#else
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
#endif
|
||||
#endif
|
||||
cursorHidden = false;
|
||||
}
|
||||
|
||||
// Disable mouse cursor
|
||||
void DisableCursor()
|
||||
{
|
||||
#if defined(PLATFORM_DESKTOP)
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
#endif
|
||||
cursorHidden = true;
|
||||
}
|
||||
|
||||
// Enable mouse cursor
|
||||
void EnableCursor()
|
||||
{
|
||||
#if defined(PLATFORM_DESKTOP)
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
#endif
|
||||
cursorHidden = false;
|
||||
}
|
||||
|
||||
// Check if mouse cursor is hidden
|
||||
bool IsCursorHidden()
|
||||
{
|
||||
return cursorHidden;
|
||||
}
|
||||
|
||||
// NOTE: Gamepad support not implemented in emscripten GLFW3 (PLATFORM_WEB)
|
||||
@ -1147,33 +1161,51 @@ bool IsCursorHidden()
|
||||
bool IsGamepadAvailable(int gamepad)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
#if defined(PLATFORM_RPI)
|
||||
|
||||
#if !defined(PLATFORM_ANDROID)
|
||||
if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad]) result = true;
|
||||
#else
|
||||
if (glfwJoystickPresent(gamepad) == 1) result = true;
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Check gamepad name (if available)
|
||||
bool IsGamepadName(int gamepad, const char *name)
|
||||
{
|
||||
bool result = false;
|
||||
const char *gamepadName = NULL;
|
||||
|
||||
if (gamepadReady[gamepad]) gamepadName = GetGamepadName(gamepad);
|
||||
|
||||
if ((name != NULL) && (gamepadName != NULL)) result = (strcmp(name, gamepadName) == 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Return gamepad internal name id
|
||||
const char *GetGamepadName(int gamepad)
|
||||
{
|
||||
#if defined(PLATFORM_DESKTOP)
|
||||
if (gamepadReady[gamepad]) return glfwGetJoystickName(gamepad);
|
||||
else return NULL;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Return gamepad axis count
|
||||
int GetGamepadAxisCount(int gamepad)
|
||||
{
|
||||
return gamepadAxisCount;
|
||||
}
|
||||
|
||||
// Return axis movement vector for a gamepad
|
||||
float GetGamepadAxisMovement(int gamepad, int axis)
|
||||
{
|
||||
float value = 0;
|
||||
|
||||
#if defined(PLATFORM_RPI)
|
||||
if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad])
|
||||
{
|
||||
if (axis < MAX_GAMEPAD_AXIS) value = gamepadAxisValues[gamepad][axis];
|
||||
}
|
||||
#else
|
||||
const float *axes;
|
||||
int axisCount = 0;
|
||||
|
||||
axes = glfwGetJoystickAxes(gamepad, &axisCount);
|
||||
|
||||
if (axis < axisCount) value = axes[axis];
|
||||
|
||||
#if !defined(PLATFORM_ANDROID)
|
||||
if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (axis < MAX_GAMEPAD_AXIS)) value = gamepadAxisState[gamepad][axis];
|
||||
#endif
|
||||
|
||||
return value;
|
||||
@ -1184,14 +1216,11 @@ bool IsGamepadButtonPressed(int gamepad, int button)
|
||||
{
|
||||
bool pressed = false;
|
||||
|
||||
currentGamepadState[button] = IsGamepadButtonDown(gamepad, button);
|
||||
|
||||
if (currentGamepadState[button] != previousGamepadState[button])
|
||||
{
|
||||
if (currentGamepadState[button]) pressed = true;
|
||||
previousGamepadState[button] = currentGamepadState[button];
|
||||
}
|
||||
else pressed = false;
|
||||
#if !defined(PLATFORM_ANDROID)
|
||||
if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (button < MAX_GAMEPAD_BUTTONS) &&
|
||||
(currentGamepadState[gamepad][button] != previousGamepadState[gamepad][button]) &&
|
||||
(currentGamepadState[gamepad][button] == 1)) pressed = true;
|
||||
#endif
|
||||
|
||||
return pressed;
|
||||
}
|
||||
@ -1201,18 +1230,9 @@ bool IsGamepadButtonDown(int gamepad, int button)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
#if defined(PLATFORM_RPI)
|
||||
// Get gamepad buttons information
|
||||
if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (gamepadButtons[gamepad][button] == 1)) result = true;
|
||||
else result = false;
|
||||
#else
|
||||
const unsigned char *buttons;
|
||||
int buttonsCount;
|
||||
|
||||
buttons = glfwGetJoystickButtons(gamepad, &buttonsCount);
|
||||
|
||||
if ((buttons != NULL) && (buttons[button] == GLFW_PRESS)) result = true;
|
||||
else result = false;
|
||||
#if !defined(PLATFORM_ANDROID)
|
||||
if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (button < MAX_GAMEPAD_BUTTONS) &&
|
||||
(currentGamepadState[gamepad][button] == 1)) result = true;
|
||||
#endif
|
||||
|
||||
return result;
|
||||
@ -1222,15 +1242,12 @@ bool IsGamepadButtonDown(int gamepad, int button)
|
||||
bool IsGamepadButtonReleased(int gamepad, int button)
|
||||
{
|
||||
bool released = false;
|
||||
|
||||
currentGamepadState[button] = IsGamepadButtonUp(gamepad, button);
|
||||
|
||||
if (currentGamepadState[button] != previousGamepadState[button])
|
||||
{
|
||||
if (currentGamepadState[button]) released = true;
|
||||
previousGamepadState[button] = currentGamepadState[button];
|
||||
}
|
||||
else released = false;
|
||||
|
||||
#if !defined(PLATFORM_ANDROID)
|
||||
if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (button < MAX_GAMEPAD_BUTTONS) &&
|
||||
(currentGamepadState[gamepad][button] != previousGamepadState[gamepad][button]) &&
|
||||
(currentGamepadState[gamepad][button] == 0)) released = true;
|
||||
#endif
|
||||
|
||||
return released;
|
||||
}
|
||||
@ -1240,24 +1257,19 @@ bool IsGamepadButtonUp(int gamepad, int button)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
#if defined(PLATFORM_RPI)
|
||||
// Get gamepad buttons information
|
||||
if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (gamepadButtons[gamepad][button] == 0)) result = true;
|
||||
else result = false;
|
||||
#else
|
||||
const unsigned char *buttons;
|
||||
int buttonsCount;
|
||||
|
||||
buttons = glfwGetJoystickButtons(gamepad, &buttonsCount);
|
||||
|
||||
if ((buttons != NULL) && (buttons[button] == GLFW_RELEASE)) result = true;
|
||||
else result = false;
|
||||
#if !defined(PLATFORM_ANDROID)
|
||||
if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (button < MAX_GAMEPAD_BUTTONS) &&
|
||||
(currentGamepadState[gamepad][button] == 0)) result = true;
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif //defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
|
||||
|
||||
// Get the last gamepad button pressed
|
||||
int GetGamepadButtonPressed(void)
|
||||
{
|
||||
return lastGamepadButtonPressed;
|
||||
}
|
||||
|
||||
// Detect if a mouse button has been pressed once
|
||||
bool IsMouseButtonPressed(int button)
|
||||
@ -1411,37 +1423,6 @@ Vector2 GetTouchPosition(int index)
|
||||
return position;
|
||||
}
|
||||
|
||||
#if defined(PLATFORM_ANDROID)
|
||||
// Detect if a button has been pressed once
|
||||
bool IsButtonPressed(int button)
|
||||
{
|
||||
bool pressed = false;
|
||||
|
||||
if ((currentButtonState[button] != previousButtonState[button]) && (currentButtonState[button] == 0)) pressed = true;
|
||||
else pressed = false;
|
||||
|
||||
return pressed;
|
||||
}
|
||||
|
||||
// Detect if a button is being pressed (button held down)
|
||||
bool IsButtonDown(int button)
|
||||
{
|
||||
if (currentButtonState[button] == 0) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
// Detect if a button has been released once
|
||||
bool IsButtonReleased(int button)
|
||||
{
|
||||
bool released = false;
|
||||
|
||||
if ((currentButtonState[button] != previousButtonState[button]) && (currentButtonState[button] == 1)) released = true;
|
||||
else released = false;
|
||||
|
||||
return released;
|
||||
}
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module specific Functions Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
@ -1924,8 +1905,9 @@ static bool GetKeyStatus(int key)
|
||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
||||
return glfwGetKey(window, key);
|
||||
#elif defined(PLATFORM_ANDROID)
|
||||
// TODO: Check for virtual keyboard
|
||||
return false;
|
||||
// NOTE: Android supports up to 260 keys
|
||||
if (key < 0 || key > 260) return false;
|
||||
else return currentKeyState[key];
|
||||
#elif defined(PLATFORM_RPI)
|
||||
// NOTE: Keys states are filled in PollInputEvents()
|
||||
if (key < 0 || key > 511) return false;
|
||||
@ -1953,6 +1935,13 @@ static void PollInputEvents(void)
|
||||
// NOTE: Gestures update must be called every frame to reset gestures correctly
|
||||
// because ProcessGestureEvent() is just called on an event, not every frame
|
||||
UpdateGestures();
|
||||
|
||||
// Reset last key pressed registered
|
||||
lastKeyPressed = -1;
|
||||
|
||||
// Reset last gamepad button pressed registered
|
||||
lastGamepadButtonPressed = -1;
|
||||
gamepadAxisCount = 0;
|
||||
|
||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
||||
// Mouse input polling
|
||||
@ -1963,9 +1952,8 @@ static void PollInputEvents(void)
|
||||
|
||||
mousePosition.x = (float)mouseX;
|
||||
mousePosition.y = (float)mouseY;
|
||||
|
||||
|
||||
// Keyboard input polling (automatically managed by GLFW3 through callback)
|
||||
lastKeyPressed = -1;
|
||||
|
||||
// Register previous keys states
|
||||
for (int i = 0; i < 512; i++) previousKeyState[i] = currentKeyState[i];
|
||||
@ -1975,13 +1963,62 @@ static void PollInputEvents(void)
|
||||
|
||||
previousMouseWheelY = currentMouseWheelY;
|
||||
currentMouseWheelY = 0;
|
||||
|
||||
// Check if gamepads are ready
|
||||
// NOTE: We do it here in case of disconection
|
||||
for (int i = 0; i < MAX_GAMEPADS; i++)
|
||||
{
|
||||
if (glfwJoystickPresent(i)) gamepadReady[i] = true;
|
||||
else gamepadReady[i] = false;
|
||||
}
|
||||
|
||||
// Register gamepads buttons events
|
||||
for (int i = 0; i < MAX_GAMEPADS; i++)
|
||||
{
|
||||
if (gamepadReady[i]) // Check if gamepad is available
|
||||
{
|
||||
// Register previous gamepad states
|
||||
for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) previousGamepadState[i][k] = currentGamepadState[i][k];
|
||||
|
||||
// Get current gamepad state
|
||||
// NOTE: There is no callback available, so we get it manually
|
||||
const unsigned char *buttons;
|
||||
int buttonsCount;
|
||||
|
||||
glfwPollEvents(); // Register keyboard/mouse events... and window events!
|
||||
buttons = glfwGetJoystickButtons(i, &buttonsCount);
|
||||
|
||||
for (int k = 0; (buttons != NULL) && (k < buttonsCount) && (buttonsCount < MAX_GAMEPAD_BUTTONS); k++)
|
||||
{
|
||||
if (buttons[k] == GLFW_PRESS)
|
||||
{
|
||||
currentGamepadState[i][k] = 1;
|
||||
lastGamepadButtonPressed = k;
|
||||
}
|
||||
else currentGamepadState[i][k] = 0;
|
||||
}
|
||||
|
||||
// Get current axis state
|
||||
const float *axes;
|
||||
int axisCount = 0;
|
||||
|
||||
axes = glfwGetJoystickAxes(i, &axisCount);
|
||||
|
||||
for (int k = 0; (axes != NULL) && (k < axisCount) && (k < MAX_GAMEPAD_AXIS); k++)
|
||||
{
|
||||
gamepadAxisState[i][k] = axes[k];
|
||||
}
|
||||
|
||||
gamepadAxisCount = axisCount;
|
||||
}
|
||||
}
|
||||
|
||||
glfwPollEvents(); // Register keyboard/mouse events (callbacks)... and window events!
|
||||
#endif
|
||||
|
||||
#if defined(PLATFORM_ANDROID)
|
||||
// Register previous keys states
|
||||
for (int i = 0; i < 128; i++) previousButtonState[i] = currentButtonState[i];
|
||||
// NOTE: Android supports up to 260 keys
|
||||
for (int i = 0; i < 260; i++) previousKeyState[i] = currentKeyState[i];
|
||||
|
||||
// Poll Events (registered events)
|
||||
// NOTE: Activity is paused if not enabled (appEnabled)
|
||||
@ -2245,9 +2282,11 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
|
||||
// Init graphics device (display device and OpenGL context)
|
||||
InitGraphicsDevice(screenWidth, screenHeight);
|
||||
|
||||
// Load default font for convenience
|
||||
#if defined(RL_LOAD_DEFAULT_FONT)
|
||||
// Load default font
|
||||
// NOTE: External function (defined in module: text)
|
||||
LoadDefaultFont();
|
||||
#endif
|
||||
|
||||
// TODO: GPU assets reload in case of lost focus (lost context)
|
||||
// NOTE: This problem has been solved just unbinding and rebinding context from display
|
||||
@ -2356,7 +2395,13 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
||||
//int32_t AKeyEvent_getMetaState(event);
|
||||
|
||||
// Save current button and its state
|
||||
currentButtonState[keycode] = AKeyEvent_getAction(event); // Down = 0, Up = 1
|
||||
// NOTE: Android key action is 0 for down and 1 for up
|
||||
if (AKeyEvent_getAction(event) == 0)
|
||||
{
|
||||
currentKeyState[keycode] = 1; // Key down
|
||||
lastKeyPressed = keycode;
|
||||
}
|
||||
else currentKeyState[keycode] = 0; // Key up
|
||||
|
||||
if (keycode == AKEYCODE_POWER)
|
||||
{
|
||||
@ -2802,7 +2847,9 @@ static void *GamepadThread(void *arg)
|
||||
if (gamepadEvent.number < MAX_GAMEPAD_BUTTONS)
|
||||
{
|
||||
// 1 - button pressed, 0 - button released
|
||||
gamepadButtons[i][gamepadEvent.number] = (int)gamepadEvent.value;
|
||||
currentGamepadState[i][gamepadEvent.number] = (int)gamepadEvent.value;
|
||||
|
||||
if ((int)gamepadEvent.value == 1) lastGamepadButtonPressed = gamepadEvent.number;
|
||||
}
|
||||
}
|
||||
else if (gamepadEvent.type == JS_EVENT_AXIS)
|
||||
@ -2812,7 +2859,7 @@ static void *GamepadThread(void *arg)
|
||||
if (gamepadEvent.number < MAX_GAMEPAD_AXIS)
|
||||
{
|
||||
// NOTE: Scaling of gamepadEvent.value to get values between -1..1
|
||||
gamepadAxisValues[i][gamepadEvent.number] = (float)gamepadEvent.value/32768;
|
||||
gamepadAxisState[i][gamepadEvent.number] = (float)gamepadEvent.value/32768;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
4395
src/external/dr_flac.h
vendored
Normal file
4395
src/external/dr_flac.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
5
src/external/openal_soft/include/AL/alext.h
vendored
5
src/external/openal_soft/include/AL/alext.h
vendored
@ -431,6 +431,11 @@ ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCi
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef AL_SOFT_gain_clamp_ex
|
||||
#define AL_SOFT_gain_clamp_ex 1
|
||||
#define AL_GAIN_LIMIT_SOFT 0x200E
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
BIN
src/external/openal_soft/lib/win32/libOpenAL32.a
vendored
Normal file
BIN
src/external/openal_soft/lib/win32/libOpenAL32.a
vendored
Normal file
Binary file not shown.
118
src/models.c
118
src/models.c
@ -4,7 +4,7 @@
|
||||
*
|
||||
* Basic functions to draw 3d shapes and load/draw 3d models (.OBJ)
|
||||
*
|
||||
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||
* will the authors be held liable for any damages arising from the use of this software.
|
||||
@ -87,8 +87,8 @@ void DrawCircle3D(Vector3 center, float radius, float rotationAngle, Vector3 rot
|
||||
{
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
|
||||
rlVertex3f(sin(DEG2RAD*i)*radius, cos(DEG2RAD*i)*radius, 0.0f);
|
||||
rlVertex3f(sin(DEG2RAD*(i + 10))*radius, cos(DEG2RAD*(i + 10))*radius, 0.0f);
|
||||
rlVertex3f(sinf(DEG2RAD*i)*radius, cosf(DEG2RAD*i)*radius, 0.0f);
|
||||
rlVertex3f(sinf(DEG2RAD*(i + 10))*radius, cosf(DEG2RAD*(i + 10))*radius, 0.0f);
|
||||
}
|
||||
rlEnd();
|
||||
rlPopMatrix();
|
||||
@ -325,25 +325,25 @@ void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color
|
||||
{
|
||||
for (int j = 0; j < slices; j++)
|
||||
{
|
||||
rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i))*sin(DEG2RAD*(j*360/slices)),
|
||||
sin(DEG2RAD*(270+(180/(rings + 1))*i)),
|
||||
cos(DEG2RAD*(270+(180/(rings + 1))*i))*cos(DEG2RAD*(j*360/slices)));
|
||||
rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sin(DEG2RAD*((j+1)*360/slices)),
|
||||
sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))),
|
||||
cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cos(DEG2RAD*((j+1)*360/slices)));
|
||||
rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sin(DEG2RAD*(j*360/slices)),
|
||||
sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))),
|
||||
cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cos(DEG2RAD*(j*360/slices)));
|
||||
rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*i))*sinf(DEG2RAD*(j*360/slices)),
|
||||
sinf(DEG2RAD*(270+(180/(rings + 1))*i)),
|
||||
cosf(DEG2RAD*(270+(180/(rings + 1))*i))*cosf(DEG2RAD*(j*360/slices)));
|
||||
rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*((j+1)*360/slices)),
|
||||
sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))),
|
||||
cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*((j+1)*360/slices)));
|
||||
rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*(j*360/slices)),
|
||||
sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))),
|
||||
cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*(j*360/slices)));
|
||||
|
||||
rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i))*sin(DEG2RAD*(j*360/slices)),
|
||||
sin(DEG2RAD*(270+(180/(rings + 1))*i)),
|
||||
cos(DEG2RAD*(270+(180/(rings + 1))*i))*cos(DEG2RAD*(j*360/slices)));
|
||||
rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i)))*sin(DEG2RAD*((j+1)*360/slices)),
|
||||
sin(DEG2RAD*(270+(180/(rings + 1))*(i))),
|
||||
cos(DEG2RAD*(270+(180/(rings + 1))*(i)))*cos(DEG2RAD*((j+1)*360/slices)));
|
||||
rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sin(DEG2RAD*((j+1)*360/slices)),
|
||||
sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))),
|
||||
cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cos(DEG2RAD*((j+1)*360/slices)));
|
||||
rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*i))*sinf(DEG2RAD*(j*360/slices)),
|
||||
sinf(DEG2RAD*(270+(180/(rings + 1))*i)),
|
||||
cosf(DEG2RAD*(270+(180/(rings + 1))*i))*cosf(DEG2RAD*(j*360/slices)));
|
||||
rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i)))*sinf(DEG2RAD*((j+1)*360/slices)),
|
||||
sinf(DEG2RAD*(270+(180/(rings + 1))*(i))),
|
||||
cosf(DEG2RAD*(270+(180/(rings + 1))*(i)))*cosf(DEG2RAD*((j+1)*360/slices)));
|
||||
rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*((j+1)*360/slices)),
|
||||
sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))),
|
||||
cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*((j+1)*360/slices)));
|
||||
}
|
||||
}
|
||||
rlEnd();
|
||||
@ -364,26 +364,26 @@ void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Col
|
||||
{
|
||||
for (int j = 0; j < slices; j++)
|
||||
{
|
||||
rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i))*sin(DEG2RAD*(j*360/slices)),
|
||||
sin(DEG2RAD*(270+(180/(rings + 1))*i)),
|
||||
cos(DEG2RAD*(270+(180/(rings + 1))*i))*cos(DEG2RAD*(j*360/slices)));
|
||||
rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sin(DEG2RAD*((j+1)*360/slices)),
|
||||
sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))),
|
||||
cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cos(DEG2RAD*((j+1)*360/slices)));
|
||||
rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*i))*sinf(DEG2RAD*(j*360/slices)),
|
||||
sinf(DEG2RAD*(270+(180/(rings + 1))*i)),
|
||||
cosf(DEG2RAD*(270+(180/(rings + 1))*i))*cosf(DEG2RAD*(j*360/slices)));
|
||||
rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*((j+1)*360/slices)),
|
||||
sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))),
|
||||
cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*((j+1)*360/slices)));
|
||||
|
||||
rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sin(DEG2RAD*((j+1)*360/slices)),
|
||||
sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))),
|
||||
cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cos(DEG2RAD*((j+1)*360/slices)));
|
||||
rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sin(DEG2RAD*(j*360/slices)),
|
||||
sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))),
|
||||
cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cos(DEG2RAD*(j*360/slices)));
|
||||
rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*((j+1)*360/slices)),
|
||||
sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))),
|
||||
cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*((j+1)*360/slices)));
|
||||
rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*(j*360/slices)),
|
||||
sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))),
|
||||
cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*(j*360/slices)));
|
||||
|
||||
rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sin(DEG2RAD*(j*360/slices)),
|
||||
sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))),
|
||||
cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cos(DEG2RAD*(j*360/slices)));
|
||||
rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i))*sin(DEG2RAD*(j*360/slices)),
|
||||
sin(DEG2RAD*(270+(180/(rings + 1))*i)),
|
||||
cos(DEG2RAD*(270+(180/(rings + 1))*i))*cos(DEG2RAD*(j*360/slices)));
|
||||
rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*(j*360/slices)),
|
||||
sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))),
|
||||
cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*(j*360/slices)));
|
||||
rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*i))*sinf(DEG2RAD*(j*360/slices)),
|
||||
sinf(DEG2RAD*(270+(180/(rings + 1))*i)),
|
||||
cosf(DEG2RAD*(270+(180/(rings + 1))*i))*cosf(DEG2RAD*(j*360/slices)));
|
||||
}
|
||||
}
|
||||
rlEnd();
|
||||
@ -407,21 +407,21 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h
|
||||
// Draw Body -------------------------------------------------------------------------------------
|
||||
for (int i = 0; i < 360; i += 360/sides)
|
||||
{
|
||||
rlVertex3f(sin(DEG2RAD*i)*radiusBottom, 0, cos(DEG2RAD*i)*radiusBottom); //Bottom Left
|
||||
rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusBottom, 0, cos(DEG2RAD*(i+360/sides))*radiusBottom); //Bottom Right
|
||||
rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusTop, height, cos(DEG2RAD*(i+360/sides))*radiusTop); //Top Right
|
||||
rlVertex3f(sinf(DEG2RAD*i)*radiusBottom, 0, cosf(DEG2RAD*i)*radiusBottom); //Bottom Left
|
||||
rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusBottom, 0, cosf(DEG2RAD*(i+360/sides))*radiusBottom); //Bottom Right
|
||||
rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusTop, height, cosf(DEG2RAD*(i+360/sides))*radiusTop); //Top Right
|
||||
|
||||
rlVertex3f(sin(DEG2RAD*i)*radiusTop, height, cos(DEG2RAD*i)*radiusTop); //Top Left
|
||||
rlVertex3f(sin(DEG2RAD*i)*radiusBottom, 0, cos(DEG2RAD*i)*radiusBottom); //Bottom Left
|
||||
rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusTop, height, cos(DEG2RAD*(i+360/sides))*radiusTop); //Top Right
|
||||
rlVertex3f(sinf(DEG2RAD*i)*radiusTop, height, cosf(DEG2RAD*i)*radiusTop); //Top Left
|
||||
rlVertex3f(sinf(DEG2RAD*i)*radiusBottom, 0, cosf(DEG2RAD*i)*radiusBottom); //Bottom Left
|
||||
rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusTop, height, cosf(DEG2RAD*(i+360/sides))*radiusTop); //Top Right
|
||||
}
|
||||
|
||||
// Draw Cap --------------------------------------------------------------------------------------
|
||||
for (int i = 0; i < 360; i += 360/sides)
|
||||
{
|
||||
rlVertex3f(0, height, 0);
|
||||
rlVertex3f(sin(DEG2RAD*i)*radiusTop, height, cos(DEG2RAD*i)*radiusTop);
|
||||
rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusTop, height, cos(DEG2RAD*(i+360/sides))*radiusTop);
|
||||
rlVertex3f(sinf(DEG2RAD*i)*radiusTop, height, cosf(DEG2RAD*i)*radiusTop);
|
||||
rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusTop, height, cosf(DEG2RAD*(i+360/sides))*radiusTop);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -430,8 +430,8 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h
|
||||
for (int i = 0; i < 360; i += 360/sides)
|
||||
{
|
||||
rlVertex3f(0, height, 0);
|
||||
rlVertex3f(sin(DEG2RAD*i)*radiusBottom, 0, cos(DEG2RAD*i)*radiusBottom);
|
||||
rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusBottom, 0, cos(DEG2RAD*(i+360/sides))*radiusBottom);
|
||||
rlVertex3f(sinf(DEG2RAD*i)*radiusBottom, 0, cosf(DEG2RAD*i)*radiusBottom);
|
||||
rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusBottom, 0, cosf(DEG2RAD*(i+360/sides))*radiusBottom);
|
||||
}
|
||||
}
|
||||
|
||||
@ -439,8 +439,8 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h
|
||||
for (int i = 0; i < 360; i += 360/sides)
|
||||
{
|
||||
rlVertex3f(0, 0, 0);
|
||||
rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusBottom, 0, cos(DEG2RAD*(i+360/sides))*radiusBottom);
|
||||
rlVertex3f(sin(DEG2RAD*i)*radiusBottom, 0, cos(DEG2RAD*i)*radiusBottom);
|
||||
rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusBottom, 0, cosf(DEG2RAD*(i+360/sides))*radiusBottom);
|
||||
rlVertex3f(sinf(DEG2RAD*i)*radiusBottom, 0, cosf(DEG2RAD*i)*radiusBottom);
|
||||
}
|
||||
rlEnd();
|
||||
rlPopMatrix();
|
||||
@ -460,17 +460,17 @@ void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, fl
|
||||
|
||||
for (int i = 0; i < 360; i += 360/sides)
|
||||
{
|
||||
rlVertex3f(sin(DEG2RAD*i)*radiusBottom, 0, cos(DEG2RAD*i)*radiusBottom);
|
||||
rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusBottom, 0, cos(DEG2RAD*(i+360/sides))*radiusBottom);
|
||||
rlVertex3f(sinf(DEG2RAD*i)*radiusBottom, 0, cosf(DEG2RAD*i)*radiusBottom);
|
||||
rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusBottom, 0, cosf(DEG2RAD*(i+360/sides))*radiusBottom);
|
||||
|
||||
rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusBottom, 0, cos(DEG2RAD*(i+360/sides))*radiusBottom);
|
||||
rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusTop, height, cos(DEG2RAD*(i+360/sides))*radiusTop);
|
||||
rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusBottom, 0, cosf(DEG2RAD*(i+360/sides))*radiusBottom);
|
||||
rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusTop, height, cosf(DEG2RAD*(i+360/sides))*radiusTop);
|
||||
|
||||
rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusTop, height, cos(DEG2RAD*(i+360/sides))*radiusTop);
|
||||
rlVertex3f(sin(DEG2RAD*i)*radiusTop, height, cos(DEG2RAD*i)*radiusTop);
|
||||
rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusTop, height, cosf(DEG2RAD*(i+360/sides))*radiusTop);
|
||||
rlVertex3f(sinf(DEG2RAD*i)*radiusTop, height, cosf(DEG2RAD*i)*radiusTop);
|
||||
|
||||
rlVertex3f(sin(DEG2RAD*i)*radiusTop, height, cos(DEG2RAD*i)*radiusTop);
|
||||
rlVertex3f(sin(DEG2RAD*i)*radiusBottom, 0, cos(DEG2RAD*i)*radiusBottom);
|
||||
rlVertex3f(sinf(DEG2RAD*i)*radiusTop, height, cosf(DEG2RAD*i)*radiusTop);
|
||||
rlVertex3f(sinf(DEG2RAD*i)*radiusBottom, 0, cosf(DEG2RAD*i)*radiusBottom);
|
||||
}
|
||||
rlEnd();
|
||||
rlPopMatrix();
|
||||
|
140
src/raylib.h
140
src/raylib.h
@ -77,10 +77,6 @@
|
||||
#define PLATFORM_DESKTOP
|
||||
#endif
|
||||
|
||||
#if defined(PLATFORM_ANDROID)
|
||||
typedef struct android_app; // Define android_app struct (android_native_app_glue.h)
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && defined(BUILDING_DLL)
|
||||
#define RLAPI __declspec(dllexport) // We are building raylib as a Win32 DLL
|
||||
#elif defined(_WIN32) && defined(RAYLIB_DLL)
|
||||
@ -93,7 +89,7 @@
|
||||
// Some basic Defines
|
||||
//----------------------------------------------------------------------------------
|
||||
#ifndef PI
|
||||
#define PI 3.14159265358979323846
|
||||
#define PI 3.14159265358979323846f
|
||||
#endif
|
||||
|
||||
#define DEG2RAD (PI/180.0f)
|
||||
@ -174,15 +170,18 @@
|
||||
#define KEY_Y 89
|
||||
#define KEY_Z 90
|
||||
|
||||
#if defined(PLATFORM_ANDROID)
|
||||
// Android Physical Buttons
|
||||
#define KEY_BACK 4
|
||||
#define KEY_MENU 82
|
||||
#define KEY_VOLUME_UP 24
|
||||
#define KEY_VOLUME_DOWN 25
|
||||
#endif
|
||||
|
||||
// Mouse Buttons
|
||||
#define MOUSE_LEFT_BUTTON 0
|
||||
#if defined(PLATFORM_WEB)
|
||||
#define MOUSE_RIGHT_BUTTON 2
|
||||
#define MOUSE_MIDDLE_BUTTON 1
|
||||
#else
|
||||
#define MOUSE_RIGHT_BUTTON 1
|
||||
#define MOUSE_MIDDLE_BUTTON 2
|
||||
#endif
|
||||
#define MOUSE_RIGHT_BUTTON 1
|
||||
#define MOUSE_MIDDLE_BUTTON 2
|
||||
|
||||
// Touch points registered
|
||||
#define MAX_TOUCH_POINTS 2
|
||||
@ -190,24 +189,35 @@
|
||||
// Gamepad Number
|
||||
#define GAMEPAD_PLAYER1 0
|
||||
#define GAMEPAD_PLAYER2 1
|
||||
#define GAMEPAD_PLAYER3 2 // Not supported
|
||||
#define GAMEPAD_PLAYER4 3 // Not supported
|
||||
#define GAMEPAD_PLAYER3 2
|
||||
#define GAMEPAD_PLAYER4 3
|
||||
|
||||
// Gamepad Buttons
|
||||
// Gamepad Buttons/Axis
|
||||
|
||||
// PS3 USB Controller
|
||||
#define GAMEPAD_PS3_BUTTON_A 2
|
||||
#define GAMEPAD_PS3_BUTTON_B 1
|
||||
#define GAMEPAD_PS3_BUTTON_X 3
|
||||
#define GAMEPAD_PS3_BUTTON_Y 4
|
||||
#define GAMEPAD_PS3_BUTTON_R1 7
|
||||
#define GAMEPAD_PS3_BUTTON_R2 5
|
||||
// PS3 USB Controller Buttons
|
||||
#define GAMEPAD_PS3_BUTTON_TRIANGLE 0
|
||||
#define GAMEPAD_PS3_BUTTON_CIRCLE 1
|
||||
#define GAMEPAD_PS3_BUTTON_CROSS 2
|
||||
#define GAMEPAD_PS3_BUTTON_SQUARE 3
|
||||
#define GAMEPAD_PS3_BUTTON_L1 6
|
||||
#define GAMEPAD_PS3_BUTTON_L2 8
|
||||
#define GAMEPAD_PS3_BUTTON_R1 7
|
||||
#define GAMEPAD_PS3_BUTTON_L2 4
|
||||
#define GAMEPAD_PS3_BUTTON_R2 5
|
||||
#define GAMEPAD_PS3_BUTTON_START 8
|
||||
#define GAMEPAD_PS3_BUTTON_SELECT 9
|
||||
#define GAMEPAD_PS3_BUTTON_START 10
|
||||
#define GAMEPAD_PS3_BUTTON_UP 24
|
||||
#define GAMEPAD_PS3_BUTTON_RIGHT 25
|
||||
#define GAMEPAD_PS3_BUTTON_DOWN 26
|
||||
#define GAMEPAD_PS3_BUTTON_LEFT 27
|
||||
#define GAMEPAD_PS3_BUTTON_PS 12
|
||||
|
||||
// TODO: Add PS3 d-pad axis
|
||||
// PS3 USB Controller Axis
|
||||
#define GAMEPAD_PS3_AXIS_LEFT_X 0
|
||||
#define GAMEPAD_PS3_AXIS_LEFT_Y 1
|
||||
#define GAMEPAD_PS3_AXIS_RIGHT_X 2
|
||||
#define GAMEPAD_PS3_AXIS_RIGHT_Y 5
|
||||
#define GAMEPAD_PS3_AXIS_L2 3 // 1.0(not pressed) --> -1.0(completely pressed)
|
||||
#define GAMEPAD_PS3_AXIS_R2 4 // 1.0(not pressed) --> -1.0(completely pressed)
|
||||
|
||||
// Xbox360 USB Controller Buttons
|
||||
#define GAMEPAD_XBOX_BUTTON_A 0
|
||||
@ -218,32 +228,31 @@
|
||||
#define GAMEPAD_XBOX_BUTTON_RB 5
|
||||
#define GAMEPAD_XBOX_BUTTON_SELECT 6
|
||||
#define GAMEPAD_XBOX_BUTTON_START 7
|
||||
#define GAMEPAD_XBOX_BUTTON_UP 10
|
||||
#define GAMEPAD_XBOX_BUTTON_RIGHT 11
|
||||
#define GAMEPAD_XBOX_BUTTON_DOWN 12
|
||||
#define GAMEPAD_XBOX_BUTTON_LEFT 13
|
||||
#define GAMEPAD_XBOX_BUTTON_HOME 9
|
||||
|
||||
// Xbox360 USB Controller Axis
|
||||
#define GAMEPAD_XBOX_AXIS_LEFT_X 0
|
||||
#define GAMEPAD_XBOX_AXIS_LEFT_Y 1
|
||||
#define GAMEPAD_XBOX_AXIS_RIGHT_X 2
|
||||
#define GAMEPAD_XBOX_AXIS_RIGHT_Y 3
|
||||
#define GAMEPAD_XBOX_AXIS_LT 4 // -1.0(not pressed) --> 1.0(completely pressed)
|
||||
#define GAMEPAD_XBOX_AXIS_RT 5 // -1.0(not pressed) --> 1.0(completely pressed)
|
||||
|
||||
/*
|
||||
// NOTE: For Raspberry Pi, axis must be reconfigured
|
||||
#if defined(PLATFORM_RPI)
|
||||
#define GAMEPAD_XBOX_AXIS_DPAD_X 7
|
||||
#define GAMEPAD_XBOX_AXIS_DPAD_Y 6
|
||||
#define GAMEPAD_XBOX_AXIS_LEFT_X 7
|
||||
#define GAMEPAD_XBOX_AXIS_LEFT_Y 6
|
||||
#define GAMEPAD_XBOX_AXIS_RIGHT_X 3
|
||||
#define GAMEPAD_XBOX_AXIS_RIGHT_Y 4
|
||||
#define GAMEPAD_XBOX_AXIS_LT 2
|
||||
#define GAMEPAD_XBOX_AXIS_RT 5
|
||||
#else
|
||||
#define GAMEPAD_XBOX_BUTTON_UP 10
|
||||
#define GAMEPAD_XBOX_BUTTON_DOWN 12
|
||||
#define GAMEPAD_XBOX_BUTTON_LEFT 13
|
||||
#define GAMEPAD_XBOX_BUTTON_RIGHT 11
|
||||
#define GAMEPAD_XBOX_AXIS_RIGHT_X 4
|
||||
#define GAMEPAD_XBOX_AXIS_RIGHT_Y 3
|
||||
#define GAMEPAD_XBOX_AXIS_LT_RT 2
|
||||
#endif
|
||||
|
||||
#define GAMEPAD_XBOX_AXIS_LEFT_X 0
|
||||
#define GAMEPAD_XBOX_AXIS_LEFT_Y 1
|
||||
|
||||
// Android Physic Buttons
|
||||
#define ANDROID_BACK 4
|
||||
#define ANDROID_MENU 82
|
||||
#define ANDROID_VOLUME_UP 24
|
||||
#define ANDROID_VOLUME_DOWN 25
|
||||
*/
|
||||
|
||||
// NOTE: MSC C++ compiler does not support compound literals (C99 feature)
|
||||
// Plain structures in C++ (without constructors) can be initialized from { } initializers.
|
||||
@ -540,6 +549,21 @@ typedef enum {
|
||||
COMPRESSED_ASTC_8x8_RGBA // 2 bpp
|
||||
} TextureFormat;
|
||||
|
||||
// Texture parameters: filter mode
|
||||
// NOTE 1: Filtering considers mipmaps if available in the texture
|
||||
// NOTE 2: Filter is accordingly set for minification and magnification
|
||||
typedef enum {
|
||||
FILTER_POINT = 0, // No filter, just pixel aproximation
|
||||
FILTER_BILINEAR, // Linear filtering
|
||||
FILTER_TRILINEAR, // Trilinear filtering (linear with mipmaps)
|
||||
FILTER_ANISOTROPIC_4X, // Anisotropic filtering 4x
|
||||
FILTER_ANISOTROPIC_8X, // Anisotropic filtering 8x
|
||||
FILTER_ANISOTROPIC_16X, // Anisotropic filtering 16x
|
||||
} TextureFilterMode;
|
||||
|
||||
// Texture parameters: wrap mode
|
||||
typedef enum { WRAP_REPEAT = 0, WRAP_CLAMP, WRAP_MIRROR } TextureWrapMode;
|
||||
|
||||
// Color blending modes (pre-defined)
|
||||
typedef enum { BLEND_ALPHA = 0, BLEND_ADDITIVE, BLEND_MULTIPLIED } BlendMode;
|
||||
|
||||
@ -594,7 +618,7 @@ extern "C" { // Prevents name mangling of functions
|
||||
// Window and Graphics Device Functions (Module: core)
|
||||
//------------------------------------------------------------------------------------
|
||||
#if defined(PLATFORM_ANDROID)
|
||||
RLAPI void InitWindow(int width, int height, struct android_app *state); // Init Android Activity and OpenGL Graphics
|
||||
RLAPI void InitWindow(int width, int height, void *state); // Init Android Activity and OpenGL Graphics (struct android_app)
|
||||
#elif defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
|
||||
RLAPI void InitWindow(int width, int height, const char *title); // Initialize Window and OpenGL Graphics
|
||||
#endif
|
||||
@ -606,11 +630,13 @@ RLAPI void ToggleFullscreen(void); // Fullscreen
|
||||
RLAPI int GetScreenWidth(void); // Get current screen width
|
||||
RLAPI int GetScreenHeight(void); // Get current screen height
|
||||
|
||||
#if !defined(PLATFORM_ANDROID)
|
||||
RLAPI void ShowCursor(void); // Shows cursor
|
||||
RLAPI void HideCursor(void); // Hides cursor
|
||||
RLAPI bool IsCursorHidden(void); // Returns true if cursor is not visible
|
||||
RLAPI void EnableCursor(void); // Enables cursor
|
||||
RLAPI void DisableCursor(void); // Disables cursor
|
||||
#endif
|
||||
|
||||
RLAPI void ClearBackground(Color color); // Sets Background Color
|
||||
RLAPI void BeginDrawing(void); // Setup drawing canvas to start drawing
|
||||
@ -653,7 +679,6 @@ RLAPI int StorageLoadValue(int position); // Storage loa
|
||||
//------------------------------------------------------------------------------------
|
||||
// Input Handling Functions (Module: core)
|
||||
//------------------------------------------------------------------------------------
|
||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
|
||||
RLAPI bool IsKeyPressed(int key); // Detect if a key has been pressed once
|
||||
RLAPI bool IsKeyDown(int key); // Detect if a key is being pressed
|
||||
RLAPI bool IsKeyReleased(int key); // Detect if a key has been released once
|
||||
@ -662,12 +687,15 @@ RLAPI int GetKeyPressed(void); // Get latest key
|
||||
RLAPI void SetExitKey(int key); // Set a custom key to exit program (default is ESC)
|
||||
|
||||
RLAPI bool IsGamepadAvailable(int gamepad); // Detect if a gamepad is available
|
||||
RLAPI float GetGamepadAxisMovement(int gamepad, int axis); // Return axis movement value for a gamepad axis
|
||||
RLAPI bool IsGamepadName(int gamepad, const char *name); // Check gamepad name (if available)
|
||||
RLAPI const char *GetGamepadName(int gamepad); // Return gamepad internal name id
|
||||
RLAPI bool IsGamepadButtonPressed(int gamepad, int button); // Detect if a gamepad button has been pressed once
|
||||
RLAPI bool IsGamepadButtonDown(int gamepad, int button); // Detect if a gamepad button is being pressed
|
||||
RLAPI bool IsGamepadButtonReleased(int gamepad, int button); // Detect if a gamepad button has been released once
|
||||
RLAPI bool IsGamepadButtonUp(int gamepad, int button); // Detect if a gamepad button is NOT being pressed
|
||||
#endif
|
||||
RLAPI int GetGamepadButtonPressed(void); // Get the last gamepad button pressed
|
||||
RLAPI int GetGamepadAxisCount(int gamepad); // Return gamepad axis count for a gamepad
|
||||
RLAPI float GetGamepadAxisMovement(int gamepad, int axis); // Return axis movement value for a gamepad axis
|
||||
|
||||
RLAPI bool IsMouseButtonPressed(int button); // Detect if a mouse button has been pressed once
|
||||
RLAPI bool IsMouseButtonDown(int button); // Detect if a mouse button is being pressed
|
||||
@ -683,12 +711,6 @@ RLAPI int GetTouchX(void); // Returns touch p
|
||||
RLAPI int GetTouchY(void); // Returns touch position Y for touch point 0 (relative to screen size)
|
||||
RLAPI Vector2 GetTouchPosition(int index); // Returns touch position XY for a touch point index (relative to screen size)
|
||||
|
||||
#if defined(PLATFORM_ANDROID)
|
||||
bool IsButtonPressed(int button); // Detect if an android physic button has been pressed
|
||||
bool IsButtonDown(int button); // Detect if an android physic button is being pressed
|
||||
bool IsButtonReleased(int button); // Detect if an android physic button has been released
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Gestures and Touch Handling Functions (Module: gestures)
|
||||
//------------------------------------------------------------------------------------
|
||||
@ -762,6 +784,7 @@ RLAPI void UnloadTexture(Texture2D texture);
|
||||
RLAPI void UnloadRenderTexture(RenderTexture2D target); // Unload render texture from GPU memory
|
||||
RLAPI Color *GetImageData(Image image); // Get pixel data from image as a Color struct array
|
||||
RLAPI Image GetTextureData(Texture2D texture); // Get pixel data from GPU texture and return an Image
|
||||
RLAPI void UpdateTexture(Texture2D texture, void *pixels); // Update GPU texture with new data
|
||||
RLAPI void ImageToPOT(Image *image, Color fillColor); // Convert image to POT (power-of-two)
|
||||
RLAPI void ImageFormat(Image *image, int newFormat); // Convert image data to desired format
|
||||
RLAPI void ImageAlphaMask(Image *image, Image alphaMask); // Apply alpha mask to image
|
||||
@ -783,7 +806,8 @@ RLAPI void ImageColorGrayscale(Image *image);
|
||||
RLAPI void ImageColorContrast(Image *image, float contrast); // Modify image color: contrast (-100 to 100)
|
||||
RLAPI void ImageColorBrightness(Image *image, int brightness); // Modify image color: brightness (-255 to 255)
|
||||
RLAPI void GenTextureMipmaps(Texture2D texture); // Generate GPU mipmaps for a texture
|
||||
RLAPI void UpdateTexture(Texture2D texture, void *pixels); // Update GPU texture with new data
|
||||
RLAPI void SetTextureFilter(Texture2D texture, int filterMode); // Set texture scaling filter mode
|
||||
RLAPI void SetTextureWrap(Texture2D texture, int wrapMode); // Set texture wrapping mode
|
||||
|
||||
RLAPI void DrawTexture(Texture2D texture, int posX, int posY, Color tint); // Draw a Texture2D
|
||||
RLAPI void DrawTextureV(Texture2D texture, Vector2 position, Color tint); // Draw a Texture2D with position defined as Vector2
|
||||
@ -797,6 +821,7 @@ RLAPI void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle dest
|
||||
//------------------------------------------------------------------------------------
|
||||
RLAPI SpriteFont GetDefaultFont(void); // Get the default SpriteFont
|
||||
RLAPI SpriteFont LoadSpriteFont(const char *fileName); // Load a SpriteFont image into GPU memory
|
||||
RLAPI SpriteFont LoadSpriteFontTTF(const char *fileName, int fontSize, int numChars, int *fontChars); // Load a SpriteFont from TTF font with parameters
|
||||
RLAPI void UnloadSpriteFont(SpriteFont spriteFont); // Unload SpriteFont from GPU memory
|
||||
|
||||
RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font)
|
||||
@ -896,7 +921,8 @@ RLAPI void DestroyLight(Light light); // Des
|
||||
RLAPI void InitVrDevice(int vdDevice); // Init VR device
|
||||
RLAPI void CloseVrDevice(void); // Close VR device
|
||||
RLAPI bool IsVrDeviceReady(void); // Detect if VR device (or simulator) is ready
|
||||
RLAPI void UpdateVrTracking(void); // Update VR tracking (position and orientation)
|
||||
RLAPI bool IsVrSimulator(void); // Detect if VR simulator is running
|
||||
RLAPI void UpdateVrTracking(Camera *camera); // Update VR tracking (position and orientation) and camera
|
||||
RLAPI void ToggleVrMode(void); // Enable/Disable VR experience (device or simulator)
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
@ -912,7 +938,7 @@ RLAPI Sound LoadSound(const char *fileName); // Load so
|
||||
RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound to memory from wave data
|
||||
RLAPI Sound LoadSoundFromRES(const char *rresName, int resId); // Load sound to memory from rRES file (raylib Resource)
|
||||
RLAPI void UpdateSound(Sound sound, void *data, int numSamples); // Update sound buffer with new data
|
||||
RLAPI void UnloadWave(Wave wave);
|
||||
RLAPI void UnloadWave(Wave wave); // Unload wave data
|
||||
RLAPI void UnloadSound(Sound sound); // Unload sound
|
||||
RLAPI void PlaySound(Sound sound); // Play a sound
|
||||
RLAPI void PauseSound(Sound sound); // Pause a sound
|
||||
|
115
src/rlgl.c
115
src/rlgl.c
@ -35,7 +35,7 @@
|
||||
#include <math.h> // Required for: atan2()
|
||||
|
||||
#ifndef RLGL_STANDALONE
|
||||
#include "raymath.h" // Required for Vector3 and Matrix functions
|
||||
#include "raymath.h" // Required for: Vector3 and Matrix functions
|
||||
#endif
|
||||
|
||||
#if defined(GRAPHICS_API_OPENGL_11)
|
||||
@ -140,6 +140,14 @@
|
||||
#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93b7
|
||||
#endif
|
||||
|
||||
#ifndef GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT
|
||||
#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
|
||||
#endif
|
||||
|
||||
#ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT
|
||||
#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
|
||||
#endif
|
||||
|
||||
#if defined(GRAPHICS_API_OPENGL_11)
|
||||
#define GL_UNSIGNED_SHORT_5_6_5 0x8363
|
||||
#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
|
||||
@ -283,14 +291,21 @@ static Shader standardShader; // Shader with support for lighting
|
||||
static Shader currentShader; // Shader to be used on rendering (by default, defaultShader)
|
||||
static bool standardShaderLoaded = false; // Flag to track if standard shader has been loaded
|
||||
|
||||
// Flags for supported extensions
|
||||
// Extension supported flag: VAO
|
||||
static bool vaoSupported = false; // VAO support (OpenGL ES2 could not support VAO extension)
|
||||
|
||||
// Compressed textures support flags
|
||||
// Extension supported flag: Compressed textures
|
||||
static bool texCompETC1Supported = false; // ETC1 texture compression support
|
||||
static bool texCompETC2Supported = false; // ETC2/EAC texture compression support
|
||||
static bool texCompPVRTSupported = false; // PVR texture compression support
|
||||
static bool texCompASTCSupported = false; // ASTC texture compression support
|
||||
|
||||
// Extension supported flag: Anisotropic filtering
|
||||
static bool texAnisotropicFilterSupported = false; // Anisotropic texture filtering support
|
||||
static float maxAnisotropicLevel = 0.0f; // Maximum anisotropy level supported (minimum is 2.0f)
|
||||
|
||||
// Extension supported flag: Clamp mirror wrap mode
|
||||
static bool texClampMirrorSupported = false; // Clamp mirror wrap mode supported
|
||||
#endif
|
||||
|
||||
#if defined(RLGL_OCULUS_SUPPORT)
|
||||
@ -372,11 +387,11 @@ static char *ReadTextFile(const char *fileName); // Read chars array from
|
||||
|
||||
#if defined(RLGL_OCULUS_SUPPORT)
|
||||
#if !defined(RLGL_STANDALONE)
|
||||
static bool InitOculusDevice(void); // Initialize Oculus device (returns true if success)
|
||||
static void CloseOculusDevice(void); // Close Oculus device
|
||||
static void UpdateOculusTracking(void); // Update Oculus head position-orientation tracking
|
||||
static void BeginOculusDrawing(void); // Setup Oculus buffers for drawing
|
||||
static void EndOculusDrawing(void); // Finish Oculus drawing and blit framebuffer to mirror
|
||||
static bool InitOculusDevice(void); // Initialize Oculus device (returns true if success)
|
||||
static void CloseOculusDevice(void); // Close Oculus device
|
||||
static void UpdateOculusTracking(Camera *camera); // Update Oculus head position-orientation tracking
|
||||
static void BeginOculusDrawing(void); // Setup Oculus buffers for drawing
|
||||
static void EndOculusDrawing(void); // Finish Oculus drawing and blit framebuffer to mirror
|
||||
#endif
|
||||
|
||||
static OculusBuffer LoadOculusBuffer(ovrSession session, int width, int height); // Load Oculus required buffers
|
||||
@ -871,6 +886,37 @@ void rlDisableTexture(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
// Set texture parameters (wrap mode/filter mode)
|
||||
void rlTextureParameters(unsigned int id, int param, int value)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, id);
|
||||
|
||||
switch (param)
|
||||
{
|
||||
case RL_TEXTURE_WRAP_S:
|
||||
case RL_TEXTURE_WRAP_T:
|
||||
{
|
||||
if ((value == RL_WRAP_CLAMP_MIRROR) && !texClampMirrorSupported) TraceLog(WARNING, "Clamp mirror wrap mode not supported");
|
||||
else glTexParameteri(GL_TEXTURE_2D, param, value);
|
||||
} break;
|
||||
case RL_TEXTURE_MAG_FILTER:
|
||||
case RL_TEXTURE_MIN_FILTER: glTexParameteri(GL_TEXTURE_2D, param, value); break;
|
||||
case RL_TEXTURE_ANISOTROPIC_FILTER:
|
||||
{
|
||||
if (value <= maxAnisotropicLevel) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, value);
|
||||
else if (maxAnisotropicLevel > 0.0f)
|
||||
{
|
||||
TraceLog(WARNING, "[TEX ID %i] Maximum anisotropic filter level supported is %iX", id, maxAnisotropicLevel);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, value);
|
||||
}
|
||||
else TraceLog(WARNING, "Anisotropic filtering not supported");
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
// Enable rendering to texture (fbo)
|
||||
void rlEnableRenderTexture(unsigned int id)
|
||||
{
|
||||
@ -1124,7 +1170,7 @@ void rlglInit(int width, int height)
|
||||
// Check NPOT textures support
|
||||
// NOTE: Only check on OpenGL ES, OpenGL 3.3 has NPOT textures full support as core feature
|
||||
if (strcmp(extList[i], (const char *)"GL_OES_texture_npot") == 0) npotSupported = true;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// DDS texture compression support
|
||||
if ((strcmp(extList[i], (const char *)"GL_EXT_texture_compression_s3tc") == 0) ||
|
||||
@ -1143,6 +1189,16 @@ void rlglInit(int width, int height)
|
||||
|
||||
// ASTC texture compression support
|
||||
if (strcmp(extList[i], (const char *)"GL_KHR_texture_compression_astc_hdr") == 0) texCompASTCSupported = true;
|
||||
|
||||
// Anisotropic texture filter support
|
||||
if (strcmp(extList[i], (const char *)"GL_EXT_texture_filter_anisotropic") == 0)
|
||||
{
|
||||
texAnisotropicFilterSupported = true;
|
||||
glGetFloatv(0x84FF, &maxAnisotropicLevel); // GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT
|
||||
}
|
||||
|
||||
// Clamp mirror wrap mode supported
|
||||
if (strcmp(extList[i], (const char *)"GL_EXT_texture_mirror_clamp") == 0) texClampMirrorSupported = true;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
@ -1162,6 +1218,9 @@ void rlglInit(int width, int height)
|
||||
if (texCompETC2Supported) TraceLog(INFO, "[EXTENSION] ETC2/EAC compressed textures supported");
|
||||
if (texCompPVRTSupported) TraceLog(INFO, "[EXTENSION] PVRT compressed textures supported");
|
||||
if (texCompASTCSupported) TraceLog(INFO, "[EXTENSION] ASTC compressed textures supported");
|
||||
|
||||
if (texAnisotropicFilterSupported) TraceLog(INFO, "[EXTENSION] Anisotropic textures filtering supported (max: %.0fX)", maxAnisotropicLevel);
|
||||
if (texClampMirrorSupported) TraceLog(INFO, "[EXTENSION] Clamp mirror wrap texture mode supported");
|
||||
|
||||
// Initialize buffers, default shaders and default textures
|
||||
//----------------------------------------------------------
|
||||
@ -1522,7 +1581,7 @@ RenderTexture2D rlglLoadRenderTexture(int width, int height)
|
||||
target.texture.id = 0;
|
||||
target.texture.width = width;
|
||||
target.texture.height = height;
|
||||
target.texture.format = UNCOMPRESSED_R8G8B8;
|
||||
target.texture.format = UNCOMPRESSED_R8G8B8A8;
|
||||
target.texture.mipmaps = 1;
|
||||
|
||||
target.depth.id = 0;
|
||||
@ -1539,7 +1598,7 @@ RenderTexture2D rlglLoadRenderTexture(int width, int height)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
#if defined(GRAPHICS_API_OPENGL_33)
|
||||
@ -1687,6 +1746,7 @@ void rlglGenerateMipmaps(Texture2D texture)
|
||||
#endif
|
||||
|
||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
//glHint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE); // Hint for mipmaps generation algorythm: GL_FASTEST, GL_NICEST, GL_DONT_CARE
|
||||
glGenerateMipmap(GL_TEXTURE_2D); // Generate mipmaps automatically
|
||||
TraceLog(INFO, "[TEX ID %i] Mipmaps generated automatically", texture.id);
|
||||
|
||||
@ -2653,7 +2713,7 @@ void InitVrDevice(int vrDevice)
|
||||
hmd.hResolution = 2160; // HMD horizontal resolution in pixels
|
||||
hmd.vResolution = 1200; // HMD vertical resolution in pixels
|
||||
hmd.hScreenSize = 0.133793f; // HMD horizontal size in meters
|
||||
hmd.vScreenSize = 0.0669; // HMD vertical size in meters
|
||||
hmd.vScreenSize = 0.0669f; // HMD vertical size in meters
|
||||
hmd.vScreenCenter = 0.04678f; // HMD screen center in meters
|
||||
hmd.eyeToScreenDistance = 0.041f; // HMD distance between eye and display in meters
|
||||
hmd.lensSeparationDistance = 0.07f; // HMD lens separation distance in meters
|
||||
@ -2710,6 +2770,12 @@ bool IsVrDeviceReady(void)
|
||||
return (vrDeviceReady || vrSimulator) && vrEnabled;
|
||||
}
|
||||
|
||||
// Detect if VR simulator is running
|
||||
bool IsVrSimulator(void)
|
||||
{
|
||||
return vrSimulator;
|
||||
}
|
||||
|
||||
// Enable/Disable VR experience (device or simulator)
|
||||
void ToggleVrMode(void)
|
||||
{
|
||||
@ -2728,16 +2794,13 @@ void ToggleVrMode(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
// Update VR tracking (position and orientation)
|
||||
void UpdateVrTracking(void)
|
||||
// Update VR tracking (position and orientation) and camera
|
||||
// NOTE: Camera (position, target, up) gets update with head tracking information
|
||||
void UpdateVrTracking(Camera *camera)
|
||||
{
|
||||
#if defined(RLGL_OCULUS_SUPPORT)
|
||||
if (vrDeviceReady) UpdateOculusTracking();
|
||||
else
|
||||
if (vrDeviceReady) UpdateOculusTracking(camera);
|
||||
#endif
|
||||
{
|
||||
// TODO: Use alternative inputs (mouse, keyboard) to simulate tracking data (eyes position/orientation)
|
||||
}
|
||||
}
|
||||
|
||||
// Begin Oculus drawing configuration
|
||||
@ -3779,8 +3842,8 @@ static void SetStereoConfig(VrDeviceInfo hmd)
|
||||
|
||||
// Compute lens parameters
|
||||
float lensShift = (hmd.hScreenSize*0.25f - hmd.lensSeparationDistance*0.5f)/hmd.hScreenSize;
|
||||
float leftLensCenter[2] = { 0.25 + lensShift, 0.5f };
|
||||
float rightLensCenter[2] = { 0.75 - lensShift, 0.5f };
|
||||
float leftLensCenter[2] = { 0.25f + lensShift, 0.5f };
|
||||
float rightLensCenter[2] = { 0.75f - lensShift, 0.5f };
|
||||
float leftScreenCenter[2] = { 0.25f, 0.5f };
|
||||
float rightScreenCenter[2] = { 0.75f, 0.5f };
|
||||
|
||||
@ -3797,8 +3860,8 @@ static void SetStereoConfig(VrDeviceInfo hmd)
|
||||
|
||||
float normScreenWidth = 0.5f;
|
||||
float normScreenHeight = 1.0f;
|
||||
float scaleIn[2] = { 2/normScreenWidth, 2/normScreenHeight/aspect };
|
||||
float scale[2] = { normScreenWidth*0.5/distortionScale, normScreenHeight*0.5*aspect/distortionScale };
|
||||
float scaleIn[2] = { 2.0f/normScreenWidth, 2.0f/normScreenHeight/aspect };
|
||||
float scale[2] = { normScreenWidth*0.5f/distortionScale, normScreenHeight*0.5f*aspect/distortionScale };
|
||||
|
||||
TraceLog(DEBUG, "VR: Distortion Shader: LeftLensCenter = { %f, %f }", leftLensCenter[0], leftLensCenter[1]);
|
||||
TraceLog(DEBUG, "VR: Distortion Shader: RightLensCenter = { %f, %f }", rightLensCenter[0], rightLensCenter[1]);
|
||||
@ -4076,7 +4139,7 @@ OCULUSAPI void CloseOculusDevice(void)
|
||||
}
|
||||
|
||||
// Update Oculus head position-orientation tracking
|
||||
OCULUSAPI void UpdateOculusTracking(void)
|
||||
OCULUSAPI void UpdateOculusTracking(Camera *camera)
|
||||
{
|
||||
frameIndex++;
|
||||
|
||||
@ -4086,6 +4149,10 @@ OCULUSAPI void UpdateOculusTracking(void)
|
||||
layer.eyeLayer.RenderPose[0] = eyePoses[0];
|
||||
layer.eyeLayer.RenderPose[1] = eyePoses[1];
|
||||
|
||||
// TODO: Update external camera with eyePoses data (position, orientation)
|
||||
// NOTE: We can simplify to simple camera if we consider IPD and HMD device configuration again later
|
||||
// it will be useful for the user to draw, lets say, billboards oriented to camera
|
||||
|
||||
// Get session status information
|
||||
ovrSessionStatus sessionStatus;
|
||||
ovr_GetSessionStatus(session, &sessionStatus);
|
||||
|
42
src/rlgl.h
42
src/rlgl.h
@ -90,15 +90,33 @@
|
||||
#define MAX_QUADS_BATCH 1024 // Be careful with text, every letter maps a quad
|
||||
#endif
|
||||
|
||||
// Texture parameters (equivalent to OpenGL defines)
|
||||
#define RL_TEXTURE_WRAP_S 0x2802 // GL_TEXTURE_WRAP_S
|
||||
#define RL_TEXTURE_WRAP_T 0x2803 // GL_TEXTURE_WRAP_T
|
||||
#define RL_TEXTURE_MAG_FILTER 0x2800 // GL_TEXTURE_MAG_FILTER
|
||||
#define RL_TEXTURE_MIN_FILTER 0x2801 // GL_TEXTURE_MIN_FILTER
|
||||
#define RL_TEXTURE_ANISOTROPIC_FILTER 0x3000 // Anisotropic filter (custom identifier)
|
||||
|
||||
#define RL_FILTER_NEAREST 0x2600 // GL_NEAREST
|
||||
#define RL_FILTER_LINEAR 0x2601 // GL_LINEAR
|
||||
#define RL_FILTER_MIP_NEAREST 0x2700 // GL_NEAREST_MIPMAP_NEAREST
|
||||
#define RL_FILTER_NEAREST_MIP_LINEAR 0x2702 // GL_NEAREST_MIPMAP_LINEAR
|
||||
#define RL_FILTER_LINEAR_MIP_NEAREST 0x2701 // GL_LINEAR_MIPMAP_NEAREST
|
||||
#define RL_FILTER_MIP_LINEAR 0x2703 // GL_LINEAR_MIPMAP_LINEAR
|
||||
|
||||
#define RL_WRAP_REPEAT 0x2901 // GL_REPEAT
|
||||
#define RL_WRAP_CLAMP 0x812F // GL_CLAMP_TO_EDGE
|
||||
#define RL_WRAP_CLAMP_MIRROR 0x8742 // GL_MIRROR_CLAMP_EXT
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
typedef enum { OPENGL_11 = 1, OPENGL_21, OPENGL_33, OPENGL_ES_20 } GlVersion;
|
||||
|
||||
typedef enum { RL_PROJECTION, RL_MODELVIEW, RL_TEXTURE } MatrixMode;
|
||||
|
||||
typedef enum { RL_LINES, RL_TRIANGLES, RL_QUADS } DrawMode;
|
||||
|
||||
typedef enum { OPENGL_11 = 1, OPENGL_21, OPENGL_33, OPENGL_ES_20 } GlVersion;
|
||||
|
||||
#if defined(RLGL_STANDALONE)
|
||||
#ifndef __cplusplus
|
||||
// Boolean type
|
||||
@ -236,6 +254,21 @@ typedef enum { OPENGL_11 = 1, OPENGL_21, OPENGL_33, OPENGL_ES_20 } GlVersion;
|
||||
|
||||
// Light types
|
||||
typedef enum { LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT } LightType;
|
||||
|
||||
// Texture parameters: filter mode
|
||||
// NOTE 1: Filtering considers mipmaps if available in the texture
|
||||
// NOTE 2: Filter is accordingly set for minification and magnification
|
||||
typedef enum {
|
||||
FILTER_POINT = 0, // No filter, just pixel aproximation
|
||||
FILTER_BILINEAR, // Linear filtering
|
||||
FILTER_TRILINEAR, // Trilinear filtering (linear with mipmaps)
|
||||
FILTER_ANISOTROPIC_4X, // Anisotropic filtering 4x
|
||||
FILTER_ANISOTROPIC_8X, // Anisotropic filtering 8x
|
||||
FILTER_ANISOTROPIC_16X, // Anisotropic filtering 16x
|
||||
} TextureFilterMode;
|
||||
|
||||
// Texture parameters: wrap mode
|
||||
typedef enum { WRAP_REPEAT = 0, WRAP_CLAMP, WRAP_MIRROR } TextureWrapMode;
|
||||
|
||||
// Color blending modes (pre-defined)
|
||||
typedef enum { BLEND_ALPHA = 0, BLEND_ADDITIVE, BLEND_MULTIPLIED } BlendMode;
|
||||
@ -296,6 +329,7 @@ void rlColor4f(float x, float y, float z, float w); // Define one vertex (color)
|
||||
//------------------------------------------------------------------------------------
|
||||
void rlEnableTexture(unsigned int id); // Enable texture usage
|
||||
void rlDisableTexture(void); // Disable texture usage
|
||||
void rlTextureParameters(unsigned int id, int param, int value); // Set texture parameters (filter, wrap)
|
||||
void rlEnableRenderTexture(unsigned int id); // Enable render texture (fbo)
|
||||
void rlDisableRenderTexture(void); // Disable render texture (fbo), return to default framebuffer
|
||||
void rlEnableDepthTest(void); // Enable depth test
|
||||
@ -375,13 +409,13 @@ float *MatrixToFloat(Matrix mat);
|
||||
void InitVrDevice(int vrDevice); // Init VR device
|
||||
void CloseVrDevice(void); // Close VR device
|
||||
bool IsVrDeviceReady(void); // Detect if VR device (or simulator) is ready
|
||||
void UpdateVrTracking(void); // Update VR tracking (position and orientation)
|
||||
void UpdateVrTracking(Camera *camera); // Update VR tracking (position and orientation) and camera
|
||||
void ToggleVrMode(void); // Enable/Disable VR experience (device or simulator)
|
||||
|
||||
// Oculus Rift API for direct access the device (no simulator)
|
||||
bool InitOculusDevice(void); // Initialize Oculus device (returns true if success)
|
||||
void CloseOculusDevice(void); // Close Oculus device
|
||||
void UpdateOculusTracking(void); // Update Oculus head position-orientation tracking
|
||||
void UpdateOculusTracking(Camera *camera); // Update Oculus head position-orientation tracking (and camera)
|
||||
void BeginOculusDrawing(void); // Setup Oculus buffers for drawing
|
||||
void EndOculusDrawing(void); // Finish Oculus drawing and blit framebuffer to mirror
|
||||
#endif
|
||||
|
83
src/rlua.h
83
src/rlua.h
@ -2824,6 +2824,28 @@ int lua_IsAudioDeviceReady(lua_State* L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua_LoadWave(lua_State* L)
|
||||
{
|
||||
const char * arg1 = LuaGetArgument_string(L, 1);
|
||||
Wave result = LoadWave((char *)arg1);
|
||||
LuaPush_Wave(L, result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua_LoadWaveEx(lua_State* L)
|
||||
{
|
||||
// TODO: Wave LoadWaveEx(float *data, int sampleCount, int sampleRate, int sampleSize, int channels);
|
||||
|
||||
int arg1 = 0;
|
||||
int arg2 = LuaGetArgument_int(L, 2);
|
||||
int arg3 = LuaGetArgument_int(L, 3);
|
||||
int arg4 = LuaGetArgument_int(L, 4);
|
||||
int arg5 = LuaGetArgument_int(L, 5);
|
||||
Wave result = LoadWaveEx(arg1, arg2, arg3, arg4, arg5);
|
||||
LuaPush_Wave(L, result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua_LoadSound(lua_State* L)
|
||||
{
|
||||
const char * arg1 = LuaGetArgument_string(L, 1);
|
||||
@ -2849,6 +2871,22 @@ int lua_LoadSoundFromRES(lua_State* L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua_UpdateSound(lua_State* L)
|
||||
{
|
||||
Sound arg1 = LuaGetArgument_Sound(L, 1);
|
||||
const char * arg2 = LuaGetArgument_string(L, 2);
|
||||
int * arg3 = LuaGetArgument_int(L, 3);
|
||||
UpdateSound(arg1, arg2, arg3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_UnloadWave(lua_State* L)
|
||||
{
|
||||
Wave arg1 = LuaGetArgument_Wave(L, 1);
|
||||
UnloadWave(arg1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_UnloadSound(lua_State* L)
|
||||
{
|
||||
Sound arg1 = LuaGetArgument_Sound(L, 1);
|
||||
@ -2908,6 +2946,43 @@ int lua_SetSoundPitch(lua_State* L)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_WaveFormat(lua_State* L)
|
||||
{
|
||||
Wave arg1 = LuaGetArgument_Wave(L, 1);
|
||||
int arg2 = LuaGetArgument_int(L, 2);
|
||||
int arg3 = LuaGetArgument_int(L, 3);
|
||||
int arg4 = LuaGetArgument_int(L, 4);
|
||||
WaveFormat(arg1, arg2, arg3, arg4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_LoadMusicStream(lua_State* L)
|
||||
{
|
||||
Wave arg1 = LuaGetArgument_Wave(L, 1);
|
||||
Wave result = WaveCopy(arg1);
|
||||
LuaPush_Wave(L, result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua_WaveCrop(lua_State* L)
|
||||
{
|
||||
Wave arg1 = LuaGetArgument_Wave(L, 1);
|
||||
int arg2 = LuaGetArgument_int(L, 2);
|
||||
int arg3 = LuaGetArgument_int(L, 3);
|
||||
WaveCrop(arg1, arg2, arg3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_GetWaveData(lua_State* L)
|
||||
{
|
||||
// TODO: float *GetWaveData(Wave wave);
|
||||
|
||||
Wave arg1 = LuaGetArgument_Wave(L, 1);
|
||||
float result = GetWaveData(arg1);
|
||||
LuaPush_float(L, result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua_LoadMusicStream(lua_State* L)
|
||||
{
|
||||
const char * arg1 = LuaGetArgument_string(L, 1);
|
||||
@ -3799,9 +3874,13 @@ static luaL_Reg raylib_functions[] = {
|
||||
REG(InitAudioDevice)
|
||||
REG(CloseAudioDevice)
|
||||
REG(IsAudioDeviceReady)
|
||||
REG(LoadWave)
|
||||
REG(LoadWaveEx)
|
||||
REG(LoadSound)
|
||||
REG(LoadSoundFromWave)
|
||||
REG(LoadSoundFromRES)
|
||||
REG(UpdateSound)
|
||||
REG(UnloadWave)
|
||||
REG(UnloadSound)
|
||||
REG(PlaySound)
|
||||
REG(PauseSound)
|
||||
@ -3810,6 +3889,10 @@ static luaL_Reg raylib_functions[] = {
|
||||
REG(IsSoundPlaying)
|
||||
REG(SetSoundVolume)
|
||||
REG(SetSoundPitch)
|
||||
REG(WaveFormat)
|
||||
REG(WaveCopy)
|
||||
REG(WaveCrop)
|
||||
REG(GetWaveData)
|
||||
|
||||
REG(LoadMusicStream)
|
||||
REG(UnloadMusicStream)
|
||||
|
@ -90,7 +90,7 @@ static const char fStandardShaderStr[] =
|
||||
" if (diff > 0.0)\n"
|
||||
" {\n"
|
||||
" vec3 h = normalize(-l.direction + v);\n"
|
||||
" spec = pow(dot(n, h), 3.0 + glossiness)*s;\n"
|
||||
" spec = pow(abs(dot(n, h)), 3.0 + glossiness)*s;\n"
|
||||
" }\n"
|
||||
" return (diff*l.diffuse.rgb + spec*colSpecular.rgb);\n"
|
||||
"}\n"
|
||||
@ -103,7 +103,7 @@ static const char fStandardShaderStr[] =
|
||||
" if (diff > 0.0)\n"
|
||||
" {\n"
|
||||
" vec3 h = normalize(lightDir + v);\n"
|
||||
" spec = pow(dot(n, h), 3.0 + glossiness)*s;\n"
|
||||
" spec = pow(abs(dot(n, h)), 3.0 + glossiness)*s;\n"
|
||||
" }\n"
|
||||
" return (diff*l.intensity*l.diffuse.rgb + spec*colSpecular.rgb);\n"
|
||||
"}\n"
|
||||
@ -124,7 +124,7 @@ static const char fStandardShaderStr[] =
|
||||
" if (diffAttenuation > 0.0)\n"
|
||||
" {\n"
|
||||
" vec3 h = normalize(lightDir + v);\n"
|
||||
" spec = pow(dot(n, h), 3.0 + glossiness)*s;\n"
|
||||
" spec = pow(abs(dot(n, h)), 3.0 + glossiness)*s;\n"
|
||||
" }\n"
|
||||
" return (falloff*(diffAttenuation*l.diffuse.rgb + spec*colSpecular.rgb));\n"
|
||||
"}\n"
|
||||
@ -152,9 +152,9 @@ static const char fStandardShaderStr[] =
|
||||
" }\n"
|
||||
" float spec = 1.0;\n"
|
||||
#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21)
|
||||
" if (useSpecular == 1) spec *= normalize(texture2D(texture2, fragTexCoord).r);\n"
|
||||
" if (useSpecular == 1) spec = texture2D(texture2, fragTexCoord).r;\n"
|
||||
#elif defined(GRAPHICS_API_OPENGL_33)
|
||||
" if (useSpecular == 1) spec *= normalize(texture(texture2, fragTexCoord).r);\n"
|
||||
" if (useSpecular == 1) spec = texture(texture2, fragTexCoord).r;\n"
|
||||
#endif
|
||||
" for (int i = 0; i < maxLights; i++)\n"
|
||||
" {\n"
|
||||
|
43
src/shapes.c
43
src/shapes.c
@ -4,7 +4,7 @@
|
||||
*
|
||||
* Basic functions to draw 2d Shapes and check collisions
|
||||
*
|
||||
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||
* will the authors be held liable for any damages arising from the use of this software.
|
||||
@ -25,9 +25,8 @@
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include <stdlib.h> // Required for abs() function
|
||||
#include <math.h> // Math related functions, sin() and cos() used on DrawCircle*
|
||||
// sqrt() and pow() and abs() used on CheckCollision*
|
||||
#include <stdlib.h> // Required for: abs()
|
||||
#include <math.h> // Required for: sinf(), cosf(), sqrtf()
|
||||
|
||||
#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2
|
||||
|
||||
@ -71,7 +70,7 @@ void DrawPixelV(Vector2 position, Color color)
|
||||
rlBegin(RL_LINES);
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlVertex2f(position.x, position.y);
|
||||
rlVertex2i(position.x + 1, position.y + 1);
|
||||
rlVertex2f(position.x + 1.0f, position.y + 1.0f);
|
||||
rlEnd();
|
||||
}
|
||||
|
||||
@ -98,7 +97,7 @@ void DrawLineV(Vector2 startPos, Vector2 endPos, Color color)
|
||||
// Draw a color-filled circle
|
||||
void DrawCircle(int centerX, int centerY, float radius, Color color)
|
||||
{
|
||||
DrawCircleV((Vector2){ centerX, centerY }, radius, color);
|
||||
DrawCircleV((Vector2){ (float)centerX, (float)centerY }, radius, color);
|
||||
}
|
||||
|
||||
// Draw a gradient-filled circle
|
||||
@ -111,9 +110,9 @@ void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Co
|
||||
rlColor4ub(color1.r, color1.g, color1.b, color1.a);
|
||||
rlVertex2i(centerX, centerY);
|
||||
rlColor4ub(color2.r, color2.g, color2.b, color2.a);
|
||||
rlVertex2f(centerX + sin(DEG2RAD*i)*radius, centerY + cos(DEG2RAD*i)*radius);
|
||||
rlVertex2f(centerX + sinf(DEG2RAD*i)*radius, centerY + cosf(DEG2RAD*i)*radius);
|
||||
rlColor4ub(color2.r, color2.g, color2.b, color2.a);
|
||||
rlVertex2f(centerX + sin(DEG2RAD*(i + 10))*radius, centerY + cos(DEG2RAD*(i + 10))*radius);
|
||||
rlVertex2f(centerX + sinf(DEG2RAD*(i + 10))*radius, centerY + cosf(DEG2RAD*(i + 10))*radius);
|
||||
}
|
||||
rlEnd();
|
||||
}
|
||||
@ -129,9 +128,9 @@ void DrawCircleV(Vector2 center, float radius, Color color)
|
||||
{
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
|
||||
rlVertex2i(center.x, center.y);
|
||||
rlVertex2f(center.x + sin(DEG2RAD*i)*radius, center.y + cos(DEG2RAD*i)*radius);
|
||||
rlVertex2f(center.x + sin(DEG2RAD*(i + 10))*radius, center.y + cos(DEG2RAD*(i + 10))*radius);
|
||||
rlVertex2f(center.x, center.y);
|
||||
rlVertex2f(center.x + sinf(DEG2RAD*i)*radius, center.y + cosf(DEG2RAD*i)*radius);
|
||||
rlVertex2f(center.x + sinf(DEG2RAD*(i + 10))*radius, center.y + cosf(DEG2RAD*(i + 10))*radius);
|
||||
}
|
||||
rlEnd();
|
||||
}
|
||||
@ -144,10 +143,10 @@ void DrawCircleV(Vector2 center, float radius, Color color)
|
||||
{
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
|
||||
rlVertex2i(center.x, center.y);
|
||||
rlVertex2f(center.x + sin(DEG2RAD*i)*radius, center.y + cos(DEG2RAD*i)*radius);
|
||||
rlVertex2f(center.x + sin(DEG2RAD*(i + 10))*radius, center.y + cos(DEG2RAD*(i + 10))*radius);
|
||||
rlVertex2f(center.x + sin(DEG2RAD*(i + 20))*radius, center.y + cos(DEG2RAD*(i + 20))*radius);
|
||||
rlVertex2f(center.x, center.y);
|
||||
rlVertex2f(center.x + sinf(DEG2RAD*i)*radius, center.y + cosf(DEG2RAD*i)*radius);
|
||||
rlVertex2f(center.x + sinf(DEG2RAD*(i + 10))*radius, center.y + cosf(DEG2RAD*(i + 10))*radius);
|
||||
rlVertex2f(center.x + sinf(DEG2RAD*(i + 20))*radius, center.y + cosf(DEG2RAD*(i + 20))*radius);
|
||||
}
|
||||
rlEnd();
|
||||
|
||||
@ -164,8 +163,8 @@ void DrawCircleLines(int centerX, int centerY, float radius, Color color)
|
||||
// NOTE: Circle outline is drawn pixel by pixel every degree (0 to 360)
|
||||
for (int i = 0; i < 360; i += 10)
|
||||
{
|
||||
rlVertex2f(centerX + sin(DEG2RAD*i)*radius, centerY + cos(DEG2RAD*i)*radius);
|
||||
rlVertex2f(centerX + sin(DEG2RAD*(i + 10))*radius, centerY + cos(DEG2RAD*(i + 10))*radius);
|
||||
rlVertex2f(centerX + sinf(DEG2RAD*i)*radius, centerY + cosf(DEG2RAD*i)*radius);
|
||||
rlVertex2f(centerX + sinf(DEG2RAD*(i + 10))*radius, centerY + cosf(DEG2RAD*(i + 10))*radius);
|
||||
}
|
||||
rlEnd();
|
||||
}
|
||||
@ -330,9 +329,9 @@ void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color col
|
||||
{
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
|
||||
rlVertex2i(0, 0);
|
||||
rlVertex2f(sin(DEG2RAD*i)*radius, cos(DEG2RAD*i)*radius);
|
||||
rlVertex2f(sin(DEG2RAD*(i + 360/sides))*radius, cos(DEG2RAD*(i + 360/sides))*radius);
|
||||
rlVertex2f(0, 0);
|
||||
rlVertex2f(sinf(DEG2RAD*i)*radius, cosf(DEG2RAD*i)*radius);
|
||||
rlVertex2f(sinf(DEG2RAD*(i + 360/sides))*radius, cosf(DEG2RAD*(i + 360/sides))*radius);
|
||||
}
|
||||
rlEnd();
|
||||
rlPopMatrix();
|
||||
@ -434,7 +433,7 @@ bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, floa
|
||||
float dx = center2.x - center1.x; // X distance between centers
|
||||
float dy = center2.y - center1.y; // Y distance between centers
|
||||
|
||||
float distance = sqrt(dx*dx + dy*dy); // Distance between centers
|
||||
float distance = sqrtf(dx*dx + dy*dy); // Distance between centers
|
||||
|
||||
if (distance <= (radius1 + radius2)) collision = true;
|
||||
|
||||
@ -457,7 +456,7 @@ bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec)
|
||||
if (dx <= (rec.width/2)) { return true; }
|
||||
if (dy <= (rec.height/2)) { return true; }
|
||||
|
||||
float cornerDistanceSq = pow(dx - rec.width/2, 2) + pow(dy - rec.height/2, 2);
|
||||
float cornerDistanceSq = (dx - rec.width/2)*(dx - rec.width/2) + (dy - rec.height/2)*(dy - rec.height/2);
|
||||
|
||||
return (cornerDistanceSq <= (radius*radius));
|
||||
}
|
||||
|
212
src/text.c
212
src/text.c
@ -4,7 +4,7 @@
|
||||
*
|
||||
* Basic functions to load SpriteFonts and draw Text
|
||||
*
|
||||
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||
* will the authors be held liable for any damages arising from the use of this software.
|
||||
@ -30,9 +30,10 @@
|
||||
#include <stdarg.h> // Required for: va_list, va_start(), vfprintf(), va_end()
|
||||
#include <stdio.h> // Required for: FILE, fopen(), fclose(), fscanf(), feof(), rewind(), fgets()
|
||||
|
||||
#include "utils.h" // Required for: GetExtension()
|
||||
#include "utils.h" // Required for: GetExtension(), GetNextPOT()
|
||||
|
||||
// Following libs are used on LoadTTF()
|
||||
//#define STBTT_STATIC
|
||||
#define STB_TRUETYPE_IMPLEMENTATION
|
||||
#include "external/stb_truetype.h" // Required for: stbtt_BakeFontBitmap()
|
||||
|
||||
@ -43,7 +44,6 @@
|
||||
//----------------------------------------------------------------------------------
|
||||
// Defines and Macros
|
||||
//----------------------------------------------------------------------------------
|
||||
#define FONT_FIRST_CHAR 32 // NOTE: Expected first char for a sprite font
|
||||
#define MAX_FORMATTEXT_LENGTH 64
|
||||
#define MAX_SUBTEXT_LENGTH 64
|
||||
|
||||
@ -68,12 +68,12 @@ static SpriteFont defaultFont; // Default font provided by raylib
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module specific Functions Declaration
|
||||
//----------------------------------------------------------------------------------
|
||||
static int GetCharIndex(SpriteFont font, int letter);
|
||||
|
||||
static SpriteFont LoadImageFont(Image image, Color key, int firstChar); // Load a Image font file (XNA style)
|
||||
static SpriteFont LoadRBMF(const char *fileName); // Load a rBMF font file (raylib BitMap Font)
|
||||
static SpriteFont LoadBMFont(const char *fileName); // Load a BMFont file (AngelCode font file)
|
||||
|
||||
// Generate a sprite font image from TTF data
|
||||
static SpriteFont LoadTTF(const char *fileName, int fontSize, int firstChar, int numChars);
|
||||
static SpriteFont LoadTTF(const char *fileName, int fontSize, int numChars, int *fontChars); // Load spritefont from TTF data
|
||||
|
||||
extern void LoadDefaultFont(void);
|
||||
extern void UnloadDefaultFont(void);
|
||||
@ -198,7 +198,7 @@ extern void LoadDefaultFont(void)
|
||||
|
||||
for (int i = 0; i < defaultFont.numChars; i++)
|
||||
{
|
||||
defaultFont.charValues[i] = FONT_FIRST_CHAR + i; // First char is 32
|
||||
defaultFont.charValues[i] = 32 + i; // First char is 32
|
||||
|
||||
defaultFont.charRecs[i].x = currentPosX;
|
||||
defaultFont.charRecs[i].y = charsDivisor + currentLine*(charsHeight + charsDivisor);
|
||||
@ -249,17 +249,18 @@ SpriteFont LoadSpriteFont(const char *fileName)
|
||||
// Default hardcoded values for ttf file loading
|
||||
#define DEFAULT_TTF_FONTSIZE 32 // Font first character (32 - space)
|
||||
#define DEFAULT_TTF_NUMCHARS 95 // ASCII 32..126 is 95 glyphs
|
||||
#define DEFAULT_FIRST_CHAR 32 // Expected first char for image spritefont
|
||||
|
||||
SpriteFont spriteFont = { 0 };
|
||||
|
||||
// Check file extension
|
||||
if (strcmp(GetExtension(fileName),"rbmf") == 0) spriteFont = LoadRBMF(fileName);
|
||||
else if (strcmp(GetExtension(fileName),"ttf") == 0) spriteFont = LoadTTF(fileName, DEFAULT_TTF_FONTSIZE, FONT_FIRST_CHAR, DEFAULT_TTF_NUMCHARS);
|
||||
else if (strcmp(GetExtension(fileName),"ttf") == 0) spriteFont = LoadSpriteFontTTF(fileName, DEFAULT_TTF_FONTSIZE, 0, NULL);
|
||||
else if (strcmp(GetExtension(fileName),"fnt") == 0) spriteFont = LoadBMFont(fileName);
|
||||
else
|
||||
{
|
||||
Image image = LoadImage(fileName);
|
||||
if (image.data != NULL) spriteFont = LoadImageFont(image, MAGENTA, FONT_FIRST_CHAR);
|
||||
if (image.data != NULL) spriteFont = LoadImageFont(image, MAGENTA, DEFAULT_FIRST_CHAR);
|
||||
UnloadImage(image);
|
||||
}
|
||||
|
||||
@ -268,6 +269,38 @@ SpriteFont LoadSpriteFont(const char *fileName)
|
||||
TraceLog(WARNING, "[%s] SpriteFont could not be loaded, using default font", fileName);
|
||||
spriteFont = GetDefaultFont();
|
||||
}
|
||||
else SetTextureFilter(spriteFont.texture, FILTER_POINT); // By default we set point filter (best performance)
|
||||
|
||||
return spriteFont;
|
||||
}
|
||||
|
||||
// Load SpriteFont from TTF file with custom parameters
|
||||
// NOTE: You can pass an array with desired characters, those characters should be available in the font
|
||||
// if array is NULL, default char set is selected 32..126
|
||||
SpriteFont LoadSpriteFontTTF(const char *fileName, int fontSize, int numChars, int *fontChars)
|
||||
{
|
||||
SpriteFont spriteFont = { 0 };
|
||||
|
||||
if (strcmp(GetExtension(fileName),"ttf") == 0)
|
||||
{
|
||||
if ((fontChars == NULL) || (numChars == 0))
|
||||
{
|
||||
int totalChars = 95; // Default charset [32..126]
|
||||
|
||||
int *defaultFontChars = (int *)malloc(totalChars*sizeof(int));
|
||||
|
||||
for (int i = 0; i < totalChars; i++) defaultFontChars[i] = i + 32; // Default first character: SPACE[32]
|
||||
|
||||
spriteFont = LoadTTF(fileName, fontSize, totalChars, defaultFontChars);
|
||||
}
|
||||
else spriteFont = LoadTTF(fileName, fontSize, numChars, fontChars);
|
||||
}
|
||||
|
||||
if (spriteFont.texture.id == 0)
|
||||
{
|
||||
TraceLog(WARNING, "[%s] SpriteFont could not be generated, using default font", fileName);
|
||||
spriteFont = GetDefaultFont();
|
||||
}
|
||||
|
||||
return spriteFont;
|
||||
}
|
||||
@ -293,13 +326,17 @@ void UnloadSpriteFont(SpriteFont spriteFont)
|
||||
// NOTE: chars spacing is proportional to fontSize
|
||||
void DrawText(const char *text, int posX, int posY, int fontSize, Color color)
|
||||
{
|
||||
Vector2 position = { (float)posX, (float)posY };
|
||||
// Check if default font has been loaded
|
||||
if (defaultFont.texture.id != 0)
|
||||
{
|
||||
Vector2 position = { (float)posX, (float)posY };
|
||||
|
||||
int defaultFontSize = 10; // Default Font chars height in pixel
|
||||
if (fontSize < defaultFontSize) fontSize = defaultFontSize;
|
||||
int spacing = fontSize/defaultFontSize;
|
||||
int defaultFontSize = 10; // Default Font chars height in pixel
|
||||
if (fontSize < defaultFontSize) fontSize = defaultFontSize;
|
||||
int spacing = fontSize/defaultFontSize;
|
||||
|
||||
DrawTextEx(defaultFont, text, position, (float)fontSize, spacing, color);
|
||||
DrawTextEx(GetDefaultFont(), text, position, (float)fontSize, spacing, color);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw text using SpriteFont
|
||||
@ -321,22 +358,18 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
// TODO: Right now we are supposing characters that follow a continous order and start at FONT_FIRST_CHAR,
|
||||
// this sytem can be improved to support any characters order and init value...
|
||||
// An intermediate table could be created to link char values with predefined char position index in chars rectangle array
|
||||
|
||||
if ((unsigned char)text[i] == 0xc2) // UTF-8 encoding identification HACK!
|
||||
{
|
||||
// Support UTF-8 encoded values from [0xc2 0x80] -> [0xc2 0xbf](¿)
|
||||
letter = (unsigned char)text[i + 1];
|
||||
rec = spriteFont.charRecs[letter - FONT_FIRST_CHAR];
|
||||
rec = spriteFont.charRecs[GetCharIndex(spriteFont, (int)letter)];
|
||||
i++;
|
||||
}
|
||||
else if ((unsigned char)text[i] == 0xc3) // UTF-8 encoding identification HACK!
|
||||
{
|
||||
// Support UTF-8 encoded values from [0xc3 0x80](À) -> [0xc3 0xbf](ÿ)
|
||||
letter = (unsigned char)text[i + 1];
|
||||
rec = spriteFont.charRecs[letter - FONT_FIRST_CHAR + 64];
|
||||
rec = spriteFont.charRecs[GetCharIndex(spriteFont, (int)letter + 64)];
|
||||
i++;
|
||||
}
|
||||
else
|
||||
@ -348,17 +381,19 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float
|
||||
textOffsetX = 0;
|
||||
rec.x = -1;
|
||||
}
|
||||
else rec = spriteFont.charRecs[(int)text[i] - FONT_FIRST_CHAR];
|
||||
else rec = spriteFont.charRecs[GetCharIndex(spriteFont, (int)text[i])];
|
||||
}
|
||||
|
||||
if (rec.x > 0)
|
||||
if (rec.x >= 0)
|
||||
{
|
||||
DrawTexturePro(spriteFont.texture, rec, (Rectangle){ position.x + textOffsetX + spriteFont.charOffsets[(int)text[i] - FONT_FIRST_CHAR].x*scaleFactor,
|
||||
position.y + textOffsetY + spriteFont.charOffsets[(int)text[i] - FONT_FIRST_CHAR].y*scaleFactor,
|
||||
int index = GetCharIndex(spriteFont, (int)text[i]);
|
||||
|
||||
DrawTexturePro(spriteFont.texture, rec, (Rectangle){ position.x + textOffsetX + spriteFont.charOffsets[index].x*scaleFactor,
|
||||
position.y + textOffsetY + spriteFont.charOffsets[index].y*scaleFactor,
|
||||
rec.width*scaleFactor, rec.height*scaleFactor} , (Vector2){ 0, 0 }, 0.0f, tint);
|
||||
|
||||
if (spriteFont.charAdvanceX[(int)text[i] - FONT_FIRST_CHAR] == 0) textOffsetX += (rec.width*scaleFactor + spacing);
|
||||
else textOffsetX += (spriteFont.charAdvanceX[(int)text[i] - FONT_FIRST_CHAR]*scaleFactor + spacing);
|
||||
if (spriteFont.charAdvanceX[index] == 0) textOffsetX += (rec.width*scaleFactor + spacing);
|
||||
else textOffsetX += (spriteFont.charAdvanceX[index]*scaleFactor + spacing);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -404,13 +439,17 @@ const char *SubText(const char *text, int position, int length)
|
||||
// Measure string width for default font
|
||||
int MeasureText(const char *text, int fontSize)
|
||||
{
|
||||
Vector2 vec;
|
||||
Vector2 vec = { 0.0f, 0.0f };
|
||||
|
||||
int defaultFontSize = 10; // Default Font chars height in pixel
|
||||
if (fontSize < defaultFontSize) fontSize = defaultFontSize;
|
||||
int spacing = fontSize/defaultFontSize;
|
||||
// Check if default font has been loaded
|
||||
if (defaultFont.texture.id != 0)
|
||||
{
|
||||
int defaultFontSize = 10; // Default Font chars height in pixel
|
||||
if (fontSize < defaultFontSize) fontSize = defaultFontSize;
|
||||
int spacing = fontSize/defaultFontSize;
|
||||
|
||||
vec = MeasureTextEx(defaultFont, text, fontSize, spacing);
|
||||
vec = MeasureTextEx(GetDefaultFont(), text, fontSize, spacing);
|
||||
}
|
||||
|
||||
return (int)vec.x;
|
||||
}
|
||||
@ -434,8 +473,10 @@ Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, int fontSize, int
|
||||
|
||||
if (text[i] != '\n')
|
||||
{
|
||||
if (spriteFont.charAdvanceX[(int)text[i] - FONT_FIRST_CHAR] != 0) textWidth += spriteFont.charAdvanceX[(int)text[i] - FONT_FIRST_CHAR];
|
||||
else textWidth += (spriteFont.charRecs[(int)text[i] - FONT_FIRST_CHAR].width + spriteFont.charOffsets[(int)text[i] - FONT_FIRST_CHAR].x);
|
||||
int index = GetCharIndex(spriteFont, (int)text[i]);
|
||||
|
||||
if (spriteFont.charAdvanceX[index] != 0) textWidth += spriteFont.charAdvanceX[index];
|
||||
else textWidth += (spriteFont.charRecs[index].width + spriteFont.charOffsets[index].x);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -492,7 +533,28 @@ void DrawFPS(int posX, int posY)
|
||||
// Module specific Functions Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Load a Image font file (XNA style)
|
||||
static int GetCharIndex(SpriteFont font, int letter)
|
||||
{
|
||||
//#define UNORDERED_CHARSET
|
||||
#if defined(UNORDERED_CHARSET)
|
||||
int index = 0;
|
||||
|
||||
for (int i = 0; i < font.numChars; i++)
|
||||
{
|
||||
if (font.charValues[i] == letter)
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return index;
|
||||
#else
|
||||
return (letter - 32);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Load an Image font file (XNA style)
|
||||
static SpriteFont LoadImageFont(Image image, Color key, int firstChar)
|
||||
{
|
||||
#define COLOR_EQUAL(col1, col2) ((col1.r == col2.r)&&(col1.g == col2.g)&&(col1.b == col2.b)&&(col1.a == col2.a))
|
||||
@ -503,8 +565,8 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar)
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
// Default number of characters expected supported
|
||||
#define MAX_FONTCHARS 128
|
||||
// Default number of characters supported
|
||||
#define MAX_FONTCHARS 256
|
||||
|
||||
// We allocate a temporal arrays for chars data measures,
|
||||
// once we get the actual number of chars, we copy data to a sized arrays
|
||||
@ -565,15 +627,24 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar)
|
||||
xPosToRead = charSpacing;
|
||||
}
|
||||
|
||||
free(pixels);
|
||||
|
||||
TraceLog(DEBUG, "SpriteFont data parsed correctly from image");
|
||||
|
||||
// NOTE: We need to remove key color borders from image to avoid weird
|
||||
// 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;
|
||||
|
||||
// Create a new image with the processed color data (key color replaced by BLANK)
|
||||
Image fontClear = LoadImageEx(pixels, image.width, image.height);
|
||||
|
||||
free(pixels); // Free pixels array memory
|
||||
|
||||
// Create spritefont with all data parsed from image
|
||||
SpriteFont spriteFont = { 0 };
|
||||
|
||||
spriteFont.texture = LoadTextureFromImage(image); // Convert loaded image to OpenGL texture
|
||||
spriteFont.texture = LoadTextureFromImage(fontClear); // Convert processed image to OpenGL texture
|
||||
spriteFont.numChars = index;
|
||||
|
||||
UnloadImage(fontClear); // Unload processed image once converted to texture
|
||||
|
||||
// We got tempCharValues and tempCharsRecs populated with chars data
|
||||
// Now we move temp data to sized charValues and charRecs arrays
|
||||
@ -803,8 +874,13 @@ static SpriteFont LoadBMFont(const char *fileName)
|
||||
strncat(texPath, texFileName, strlen(texFileName));
|
||||
|
||||
TraceLog(DEBUG, "[%s] Font texture loading path: %s", fileName, texPath);
|
||||
|
||||
Image imFont = LoadImage(texPath);
|
||||
|
||||
font.texture = LoadTexture(texPath);
|
||||
if (imFont.format == UNCOMPRESSED_GRAYSCALE) ImageAlphaMask(&imFont, imFont);
|
||||
|
||||
font.texture = LoadTextureFromImage(imFont);
|
||||
|
||||
font.size = fontSize;
|
||||
font.numChars = numChars;
|
||||
font.charValues = (int *)malloc(numChars*sizeof(int));
|
||||
@ -812,22 +888,18 @@ static SpriteFont LoadBMFont(const char *fileName)
|
||||
font.charOffsets = (Vector2 *)malloc(numChars*sizeof(Vector2));
|
||||
font.charAdvanceX = (int *)malloc(numChars*sizeof(int));
|
||||
|
||||
UnloadImage(imFont);
|
||||
|
||||
free(texPath);
|
||||
|
||||
int charId, charX, charY, charWidth, charHeight, charOffsetX, charOffsetY, charAdvanceX;
|
||||
|
||||
bool unorderedChars = false;
|
||||
int firstChar = 0;
|
||||
|
||||
for (int i = 0; i < numChars; i++)
|
||||
{
|
||||
fgets(buffer, MAX_BUFFER_SIZE, fntFile);
|
||||
sscanf(buffer, "char id=%i x=%i y=%i width=%i height=%i xoffset=%i yoffset=%i xadvance=%i",
|
||||
&charId, &charX, &charY, &charWidth, &charHeight, &charOffsetX, &charOffsetY, &charAdvanceX);
|
||||
|
||||
if (i == 0) firstChar = charId;
|
||||
else if (i != (charId - firstChar)) unorderedChars = true;
|
||||
|
||||
// Save data properly in sprite font
|
||||
font.charValues[i] = charId;
|
||||
font.charRecs[i] = (Rectangle){ charX, charY, charWidth, charHeight };
|
||||
@ -837,11 +909,7 @@ static SpriteFont LoadBMFont(const char *fileName)
|
||||
|
||||
fclose(fntFile);
|
||||
|
||||
if (firstChar != FONT_FIRST_CHAR) TraceLog(WARNING, "BMFont not supported: expected SPACE(32) as first character, falling back to default font");
|
||||
else if (unorderedChars) TraceLog(WARNING, "BMFont not supported: unordered chars data, falling back to default font");
|
||||
|
||||
// NOTE: Font data could be not ordered by charId: 32,33,34,35... raylib does not support unordered BMFonts
|
||||
if ((firstChar != FONT_FIRST_CHAR) || (unorderedChars) || (font.texture.id == 0))
|
||||
if (font.texture.id == 0)
|
||||
{
|
||||
UnloadSpriteFont(font);
|
||||
font = GetDefaultFont();
|
||||
@ -853,14 +921,17 @@ static SpriteFont LoadBMFont(const char *fileName)
|
||||
|
||||
// Generate a sprite font from TTF file data (font size required)
|
||||
// TODO: Review texture packing method and generation (use oversampling)
|
||||
static SpriteFont LoadTTF(const char *fileName, int fontSize, int firstChar, int numChars)
|
||||
static SpriteFont LoadTTF(const char *fileName, int fontSize, int numChars, int *fontChars)
|
||||
{
|
||||
// NOTE: Generated font uses some hardcoded values
|
||||
#define FONT_TEXTURE_WIDTH 512 // Font texture width
|
||||
#define FONT_TEXTURE_HEIGHT 512 // Font texture height
|
||||
// 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)
|
||||
// and a maximum character width of 3/4 of fontSize... it worked ok with all my tests...
|
||||
int textureSize = GetNextPOT(ceil((float)fontSize*3/4)*ceil(sqrtf((float)numChars)));
|
||||
|
||||
TraceLog(INFO, "TTF spritefont loading: Predicted texture size: %ix%i", textureSize, textureSize);
|
||||
|
||||
unsigned char *ttfBuffer = (unsigned char *)malloc(1 << 25);
|
||||
unsigned char *dataBitmap = (unsigned char *)malloc(FONT_TEXTURE_WIDTH*FONT_TEXTURE_HEIGHT*sizeof(unsigned char)); // One channel bitmap returned!
|
||||
unsigned char *dataBitmap = (unsigned char *)malloc(textureSize*textureSize*sizeof(unsigned char)); // One channel bitmap returned!
|
||||
stbtt_bakedchar *charData = (stbtt_bakedchar *)malloc(sizeof(stbtt_bakedchar)*numChars);
|
||||
|
||||
SpriteFont font = { 0 };
|
||||
@ -869,40 +940,47 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize, int firstChar, int
|
||||
|
||||
if (ttfFile == NULL)
|
||||
{
|
||||
TraceLog(WARNING, "[%s] FNT file could not be opened", fileName);
|
||||
TraceLog(WARNING, "[%s] TTF file could not be opened", fileName);
|
||||
return font;
|
||||
}
|
||||
|
||||
fread(ttfBuffer, 1, 1<<25, ttfFile);
|
||||
|
||||
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...
|
||||
stbtt_BakeFontBitmap(ttfBuffer,0, fontSize, dataBitmap, FONT_TEXTURE_WIDTH, FONT_TEXTURE_HEIGHT, firstChar, numChars, charData);
|
||||
// TODO: Replace this function by a proper packing method and support random chars order,
|
||||
// we already receive a list (fontChars) with the ordered expected characters
|
||||
int result = stbtt_BakeFontBitmap(ttfBuffer, 0, fontSize, dataBitmap, textureSize, textureSize, fontChars[0], numChars, charData);
|
||||
|
||||
//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");
|
||||
|
||||
free(ttfBuffer);
|
||||
|
||||
// Convert image data from grayscale to to UNCOMPRESSED_GRAY_ALPHA
|
||||
unsigned char *dataGrayAlpha = (unsigned char *)malloc(FONT_TEXTURE_WIDTH*FONT_TEXTURE_HEIGHT*sizeof(unsigned char)*2); // Two channels
|
||||
int k = 0;
|
||||
unsigned char *dataGrayAlpha = (unsigned char *)malloc(textureSize*textureSize*sizeof(unsigned char)*2); // Two channels
|
||||
|
||||
for (int i = 0; i < FONT_TEXTURE_WIDTH*FONT_TEXTURE_HEIGHT; i++)
|
||||
for (int i = 0, k = 0; i < textureSize*textureSize; i++, k += 2)
|
||||
{
|
||||
dataGrayAlpha[k] = 255;
|
||||
dataGrayAlpha[k + 1] = dataBitmap[i];
|
||||
|
||||
k += 2;
|
||||
}
|
||||
|
||||
free(dataBitmap);
|
||||
|
||||
// Sprite font generation from TTF extracted data
|
||||
Image image;
|
||||
image.width = FONT_TEXTURE_WIDTH;
|
||||
image.height = FONT_TEXTURE_HEIGHT;
|
||||
image.width = textureSize;
|
||||
image.height = textureSize;
|
||||
image.mipmaps = 1;
|
||||
image.format = UNCOMPRESSED_GRAY_ALPHA;
|
||||
image.data = dataGrayAlpha;
|
||||
|
||||
|
||||
font.texture = LoadTextureFromImage(image);
|
||||
|
||||
//WritePNG("generated_ttf_image.png", (unsigned char *)image.data, image.width, image.height, 2);
|
||||
|
||||
UnloadImage(image); // Unloads dataGrayAlpha
|
||||
|
||||
font.size = fontSize;
|
||||
@ -914,7 +992,7 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize, int firstChar, int
|
||||
|
||||
for (int i = 0; i < font.numChars; i++)
|
||||
{
|
||||
font.charValues[i] = i + firstChar;
|
||||
font.charValues[i] = fontChars[i];
|
||||
|
||||
font.charRecs[i].x = (int)charData[i].x0;
|
||||
font.charRecs[i].y = (int)charData[i].y0;
|
||||
|
145
src/textures.c
145
src/textures.c
@ -8,7 +8,7 @@
|
||||
* stb_image - Multiple formats image loading (JPEG, PNG, BMP, TGA, PSD, GIF, PIC)
|
||||
* NOTE: stb_image has been slightly modified, original library: https://github.com/nothings/stb
|
||||
*
|
||||
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||
* will the authors be held liable for any damages arising from the use of this software.
|
||||
@ -229,7 +229,7 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int
|
||||
// TODO: Review function to support multiple color modes
|
||||
Image LoadImageFromRES(const char *rresName, int resId)
|
||||
{
|
||||
Image image;
|
||||
Image image = { 0 };
|
||||
bool found = false;
|
||||
|
||||
char id[4]; // rRES file identifier
|
||||
@ -442,6 +442,96 @@ void UnloadRenderTexture(RenderTexture2D target)
|
||||
if (target.id != 0) rlDeleteRenderTextures(target);
|
||||
}
|
||||
|
||||
// Set texture scaling filter mode
|
||||
void SetTextureFilter(Texture2D texture, int filterMode)
|
||||
{
|
||||
switch (filterMode)
|
||||
{
|
||||
case FILTER_POINT:
|
||||
{
|
||||
if (texture.mipmaps > 1)
|
||||
{
|
||||
// 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);
|
||||
|
||||
// RL_FILTER_NEAREST - tex filter: POINT (no filter), no mipmaps
|
||||
rlTextureParameters(texture.id, RL_TEXTURE_MAG_FILTER, RL_FILTER_NEAREST);
|
||||
}
|
||||
else
|
||||
{
|
||||
// RL_FILTER_NEAREST - tex filter: POINT (no filter), no mipmaps
|
||||
rlTextureParameters(texture.id, RL_TEXTURE_MIN_FILTER, RL_FILTER_NEAREST);
|
||||
rlTextureParameters(texture.id, RL_TEXTURE_MAG_FILTER, RL_FILTER_NEAREST);
|
||||
}
|
||||
} break;
|
||||
case FILTER_BILINEAR:
|
||||
{
|
||||
if (texture.mipmaps > 1)
|
||||
{
|
||||
// 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)
|
||||
rlTextureParameters(texture.id, RL_TEXTURE_MIN_FILTER, RL_FILTER_LINEAR_MIP_NEAREST);
|
||||
|
||||
// RL_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps
|
||||
rlTextureParameters(texture.id, RL_TEXTURE_MAG_FILTER, RL_FILTER_LINEAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
// RL_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps
|
||||
rlTextureParameters(texture.id, RL_TEXTURE_MIN_FILTER, RL_FILTER_LINEAR);
|
||||
rlTextureParameters(texture.id, RL_TEXTURE_MAG_FILTER, RL_FILTER_LINEAR);
|
||||
}
|
||||
} break;
|
||||
case FILTER_TRILINEAR:
|
||||
{
|
||||
if (texture.mipmaps > 1)
|
||||
{
|
||||
// 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);
|
||||
|
||||
// RL_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps
|
||||
rlTextureParameters(texture.id, RL_TEXTURE_MAG_FILTER, RL_FILTER_LINEAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
TraceLog(WARNING, "[TEX ID %i] No mipmaps available for TRILINEAR texture filtering", texture.id);
|
||||
|
||||
// RL_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps
|
||||
rlTextureParameters(texture.id, RL_TEXTURE_MIN_FILTER, RL_FILTER_LINEAR);
|
||||
rlTextureParameters(texture.id, RL_TEXTURE_MAG_FILTER, RL_FILTER_LINEAR);
|
||||
}
|
||||
} break;
|
||||
case FILTER_ANISOTROPIC_4X: rlTextureParameters(texture.id, RL_TEXTURE_ANISOTROPIC_FILTER, 4); break;
|
||||
case FILTER_ANISOTROPIC_8X: rlTextureParameters(texture.id, RL_TEXTURE_ANISOTROPIC_FILTER, 8); break;
|
||||
case FILTER_ANISOTROPIC_16X: rlTextureParameters(texture.id, RL_TEXTURE_ANISOTROPIC_FILTER, 16); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
// Set texture wrapping mode
|
||||
void SetTextureWrap(Texture2D texture, int wrapMode)
|
||||
{
|
||||
switch (wrapMode)
|
||||
{
|
||||
case WRAP_REPEAT:
|
||||
{
|
||||
rlTextureParameters(texture.id, RL_TEXTURE_WRAP_S, RL_WRAP_REPEAT);
|
||||
rlTextureParameters(texture.id, RL_TEXTURE_WRAP_T, RL_WRAP_REPEAT);
|
||||
} break;
|
||||
case WRAP_CLAMP:
|
||||
{
|
||||
rlTextureParameters(texture.id, RL_TEXTURE_WRAP_S, RL_WRAP_CLAMP);
|
||||
rlTextureParameters(texture.id, RL_TEXTURE_WRAP_T, RL_WRAP_CLAMP);
|
||||
} break;
|
||||
case WRAP_MIRROR:
|
||||
{
|
||||
rlTextureParameters(texture.id, RL_TEXTURE_WRAP_S, RL_WRAP_CLAMP_MIRROR);
|
||||
rlTextureParameters(texture.id, RL_TEXTURE_WRAP_T, RL_WRAP_CLAMP_MIRROR);
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
// Get pixel data from image in the form of Color struct array
|
||||
Color *GetImageData(Image image)
|
||||
{
|
||||
@ -694,28 +784,45 @@ void ImageFormat(Image *image, int newFormat)
|
||||
}
|
||||
|
||||
// Apply alpha mask to image
|
||||
// NOTE 1: Returned image is RGBA - 32bit
|
||||
// NOTE 1: Returned image is GRAY_ALPHA (16bit) or RGBA (32bit)
|
||||
// NOTE 2: alphaMask should be same size as image
|
||||
void ImageAlphaMask(Image *image, Image alphaMask)
|
||||
{
|
||||
if (image->format >= COMPRESSED_DXT1_RGB)
|
||||
if ((image->width != alphaMask.width) || (image->height != alphaMask.height))
|
||||
{
|
||||
TraceLog(WARNING, "Alpha mask must be same size as image");
|
||||
}
|
||||
else if (image->format >= COMPRESSED_DXT1_RGB)
|
||||
{
|
||||
TraceLog(WARNING, "Alpha mask can not be applied to compressed data formats");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Force mask to be Grayscale
|
||||
Image mask = ImageCopy(alphaMask);
|
||||
ImageFormat(&mask, UNCOMPRESSED_GRAYSCALE);
|
||||
if (mask.format != UNCOMPRESSED_GRAYSCALE) ImageFormat(&mask, UNCOMPRESSED_GRAYSCALE);
|
||||
|
||||
// Convert image to RGBA
|
||||
if (image->format != UNCOMPRESSED_R8G8B8A8) ImageFormat(image, UNCOMPRESSED_R8G8B8A8);
|
||||
|
||||
// Apply alpha mask to alpha channel
|
||||
for (int i = 0, k = 3; (i < mask.width*mask.height) || (i < image->width*image->height); i++, k += 4)
|
||||
// In case image is only grayscale, we just add alpha channel
|
||||
if (image->format == UNCOMPRESSED_GRAYSCALE)
|
||||
{
|
||||
((unsigned char *)image->data)[k] = ((unsigned char *)mask.data)[i];
|
||||
ImageFormat(image, UNCOMPRESSED_GRAY_ALPHA);
|
||||
|
||||
// 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)
|
||||
{
|
||||
((unsigned char *)image->data)[k] = ((unsigned char *)mask.data)[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Convert image to RGBA
|
||||
if (image->format != UNCOMPRESSED_R8G8B8A8) ImageFormat(image, UNCOMPRESSED_R8G8B8A8);
|
||||
|
||||
// Apply alpha mask to alpha channel
|
||||
for (int i = 0, k = 3; (i < mask.width*mask.height) || (i < image->width*image->height); i++, k += 4)
|
||||
{
|
||||
((unsigned char *)image->data)[k] = ((unsigned char *)mask.data)[i];
|
||||
}
|
||||
}
|
||||
|
||||
UnloadImage(mask);
|
||||
@ -1118,7 +1225,7 @@ Image ImageText(const char *text, int fontSize, Color color)
|
||||
if (fontSize < defaultFontSize) fontSize = defaultFontSize;
|
||||
int spacing = fontSize/defaultFontSize;
|
||||
|
||||
Image imText = ImageTextEx(GetDefaultFont(), text, fontSize, spacing, color);
|
||||
Image imText = ImageTextEx(GetDefaultFont(), text, (float)fontSize, spacing, color);
|
||||
|
||||
return imText;
|
||||
}
|
||||
@ -1134,7 +1241,7 @@ Image ImageTextEx(SpriteFont font, const char *text, float fontSize, int spacing
|
||||
// NOTE: GetTextureData() not available in OpenGL ES
|
||||
Image imFont = GetTextureData(font.texture);
|
||||
|
||||
ImageFormat(&imFont, UNCOMPRESSED_R8G8B8A8); // Required for color tint
|
||||
ImageFormat(&imFont, UNCOMPRESSED_R8G8B8A8); // Convert to 32 bit for color tint
|
||||
ImageColorTint(&imFont, tint); // Apply color tint to font
|
||||
|
||||
Color *fontPixels = GetImageData(imFont);
|
||||
@ -1183,7 +1290,7 @@ Image ImageTextEx(SpriteFont font, const char *text, float fontSize, int spacing
|
||||
void ImageDrawText(Image *dst, Vector2 position, const char *text, int fontSize, Color color)
|
||||
{
|
||||
// NOTE: For default font, sapcing is set to desired font size / default font size (10)
|
||||
ImageDrawTextEx(dst, position, GetDefaultFont(), text, fontSize, fontSize/10, color);
|
||||
ImageDrawTextEx(dst, position, GetDefaultFont(), text, (float)fontSize, fontSize/10, color);
|
||||
}
|
||||
|
||||
// Draw text (custom sprite font) within an image (destination)
|
||||
@ -1317,7 +1424,7 @@ void ImageColorContrast(Image *image, float contrast)
|
||||
if (contrast < -100) contrast = -100;
|
||||
if (contrast > 100) contrast = 100;
|
||||
|
||||
contrast = (100.0 + contrast)/100.0;
|
||||
contrast = (100.0f + contrast)/100.0f;
|
||||
contrast *= contrast;
|
||||
|
||||
Color *pixels = GetImageData(*image);
|
||||
@ -1326,7 +1433,7 @@ void ImageColorContrast(Image *image, float contrast)
|
||||
{
|
||||
for (int x = 0; x < image->width; x++)
|
||||
{
|
||||
float pR = (float)pixels[y*image->width + x].r/255.0;
|
||||
float pR = (float)pixels[y*image->width + x].r/255.0f;
|
||||
pR -= 0.5;
|
||||
pR *= contrast;
|
||||
pR += 0.5;
|
||||
@ -1334,7 +1441,7 @@ void ImageColorContrast(Image *image, float contrast)
|
||||
if (pR < 0) pR = 0;
|
||||
if (pR > 255) pR = 255;
|
||||
|
||||
float pG = (float)pixels[y*image->width + x].g/255.0;
|
||||
float pG = (float)pixels[y*image->width + x].g/255.0f;
|
||||
pG -= 0.5;
|
||||
pG *= contrast;
|
||||
pG += 0.5;
|
||||
@ -1342,7 +1449,7 @@ void ImageColorContrast(Image *image, float contrast)
|
||||
if (pG < 0) pG = 0;
|
||||
if (pG > 255) pG = 255;
|
||||
|
||||
float pB = (float)pixels[y*image->width + x].b/255.0;
|
||||
float pB = (float)pixels[y*image->width + x].b/255.0f;
|
||||
pB -= 0.5;
|
||||
pB *= contrast;
|
||||
pB += 0.5;
|
||||
|
@ -8,7 +8,7 @@
|
||||
* tinfl - zlib DEFLATE algorithm decompression lib
|
||||
* stb_image_write - PNG writting functions
|
||||
*
|
||||
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||
* will the authors be held liable for any damages arising from the use of this software.
|
||||
|
Loading…
Reference in New Issue
Block a user