mirror of https://github.com/raysan5/raylib
commit
4123233f78
55
CHANGELOG
55
CHANGELOG
|
@ -1,10 +1,59 @@
|
|||
changelog
|
||||
---------
|
||||
|
||||
Current Release: raylib 1.5.0 (18 July 2016)
|
||||
Current Release: raylib 1.6.0 (20 November 2016)
|
||||
|
||||
NOTE: Only versions marked as 'Release' are available in installer, updates are only available as source.
|
||||
NOTE: Current Release includes all previous updates.
|
||||
-----------------------------------------------
|
||||
Release: raylib 1.6.0 (20 November 2016)
|
||||
-----------------------------------------------
|
||||
NOTE:
|
||||
This new raylib version commemorates raylib 3rd anniversary and represents another complete review of the library.
|
||||
It includes some interesting new features and is a stepping stone towards raylib future.
|
||||
|
||||
HUGE changes:
|
||||
[rlua] LUA BINDING: Complete raylib LUA binding, all raylib functions ported to LUA plus the +60 code examples.
|
||||
[audio] COMPLETE REDESIGN: Improved music support and also raw audio data processing and playing. FLAC support added.
|
||||
[physac] COMPLETE REWRITE: Improved performance, functionality and simplified usage, moved to own repository and added multiple examples!
|
||||
|
||||
other changes:
|
||||
|
||||
[core] Corrected issue on OSX with HighDPI display
|
||||
[core] Added flag to allow resizable window
|
||||
[core] Allow no default font loading
|
||||
[core] Corrected old issue with mouse buttons on web
|
||||
[core] Improved gamepad support, unified across platforms
|
||||
[core] Reviewed Android key inputs system, unified with desktop
|
||||
[rlgl] Redesigned lighting shader system
|
||||
[rlgl] Reviewed UpdateVrTracking() and rlglLoadRenderTexture()
|
||||
[rlgl] Updated standard shader for better performance
|
||||
[shapes] Corrected issue on DrawPolyEx()
|
||||
[textures] Simplified supported image formats support
|
||||
[textures] Improved text drawing within an image: ImageDrawText()
|
||||
[textures] Support image alpha mixing: ImageAlphaMask()
|
||||
[textures] Support textures filtering: SetTextureFilter()
|
||||
[textures] Support textures wrap modes: SetTextureWrap()
|
||||
[text] Improved TTF spritefont generation: LoadSpriteFontTTF()
|
||||
[text] Improved AngelCode fonts support
|
||||
[text] Reviewed spacing formatting
|
||||
[text] Added TraceLog info on image spritefont loading
|
||||
[text] Improved text measurement: MeasureTextEx()
|
||||
[models] Improved OBJ loading flexibility
|
||||
[models] Removed function: ResolveCollisionCubicmap()
|
||||
[camera] Redesigned camera system and ported to header-only
|
||||
[gestures] Redesigned gestures module to header-only
|
||||
[audio] Simplified Music loading and playing system
|
||||
[audio] Added trace on audio device closing
|
||||
[audio] Reviewed Wave struct for reter flexivility
|
||||
[audio] Support sound data update: UpdateSound()
|
||||
[audio] Added support for FLAC audio loading/streaming
|
||||
[raygui] Removed raygui from raylib repo (moved to own repo)
|
||||
[build] Added OpenAL static library
|
||||
[build] Added Visual Studio 2015 projects
|
||||
[build] Support shared/dynamic raylib compilation
|
||||
[*] Updated LibOVR to SDK version 1.8
|
||||
[*] Updated games to latest raylib version
|
||||
[*] Improved Android support
|
||||
[*] Improved examples and added new ones
|
||||
|
||||
-----------------------------------------------
|
||||
Release: raylib 1.5.0 (18 July 2016)
|
||||
|
|
26
README.md
26
README.md
|
@ -153,11 +153,33 @@ Up to 8 new code examples have been added to show the new raylib features and al
|
|||
|
||||
Lots of code changes (+400 commits) and lots of hours of hard work have concluded in this amazing new raylib 1.5.
|
||||
|
||||
notes on raylib 1.6
|
||||
-------------------
|
||||
|
||||
On November 2016, only 4 months after raylib 1.5, arrives raylib 1.6. This new version represents another big review of the library and includes some interesting additions. This version conmmemorates raylib 3rd anniversary (raylib 1.0 was published on November 2013) and it is a stepping stone for raylib future. raylib roadmap has been reviewed and redefined to focus on its primary objective: create a simple and easy-to-use library to learn videogames programming. Some of the new features:
|
||||
|
||||
Complete raylib LUA binding. All raylib functions plus the +60 code examples have been ported to LUA, now LUA users can enjoy coding videogames in LUA while using all the internal power of raylib. This addition also open the doors to LUA scripting support for a future raylib-based engine, being able to move game logic (Init, Update, Draw, De-Init) to LUA scripts while keep using raylib functionality.
|
||||
|
||||
Completely redesigned audio module. Based on the new direction taken in raylib 1.5, it has been further improved and more functionality added to allow raw audio processing and playing. FLAC file format support has also been added. In the same line, OpenAL Soft backend is now provided as a static library in Windows to allow static linking and get ride of OpenAL32.dll. Now raylib Windows games are completey self-contained, no external libraries required any more!
|
||||
|
||||
Camera and gestures modules have been reviewed, highly simplified and ported to single-file header-only libraries for easier portability and usage flexibility. Consequently, camera system usage has been simplified in all examples.
|
||||
|
||||
Improved Gamepad support on Windows and Raspberry Pi with the addition of new functions for custom gamepad configurations but supporting by default PS3 and Xbox-based gamepads.
|
||||
|
||||
Improved textures and text functionality, adding new functions for texture filtering control and better TTF/AngelCode fonts loading and generation support.
|
||||
|
||||
Physac module has been moved to its own repository and it has been improved A LOT, actually, library has been completely rewritten by @victorfisac, multiple samples have been added and countless new features to match current standard 2D physic libraries.
|
||||
|
||||
Build system improvement. Added support for raylib dynamic library generation (raylib.dll) for users that prefer dynamic library linking. Also thinking on advance users, it has been added pre-configured Visual Studio C++ 2015 solution with raylib project and C/C++ examples for users that prefer that professional IDE and compiler.
|
||||
|
||||
New examples, new functions, complete code-base review, multiple bugs corrected... this is raylib 1.6. Enjoy making games.
|
||||
|
||||
|
||||
features
|
||||
--------
|
||||
|
||||
* Written in plain C code (C99)
|
||||
* Uses C# PascalCase/camelCase notation
|
||||
* Uses PascalCase/camelCase notation
|
||||
* Hardware accelerated with OpenGL (1.1, 2.1, 3.3 or ES2)
|
||||
* Unique OpenGL abstraction layer (usable as standalone module): [rlgl](https://github.com/raysan5/raylib/blob/master/src/rlgl.c)
|
||||
* Powerful fonts module with multiple SpriteFonts formats support (XNA bitmap fonts, AngelCode fonts, TTF)
|
||||
|
@ -166,7 +188,7 @@ features
|
|||
* Materials (diffuse, normal, specular) and Lighting (point, directional, spot) support
|
||||
* Shaders support, including Model shaders and Postprocessing shaders
|
||||
* Powerful math module for Vector and Matrix operations: [raymath](https://github.com/raysan5/raylib/blob/master/src/raymath.c)
|
||||
* Audio loading and playing with streaming support and mixing channels (WAV, OGG, XM, MOD)
|
||||
* Audio loading and playing with streaming support and mixing channels (WAV, OGG, FLAC, XM, MOD)
|
||||
* VR stereo rendering support with configurable HMD device parameters
|
||||
* Multiple platforms support: Windows, Linux, Mac, **Android**, **Raspberry Pi**, **HTML5** and **Oculus Rift CV1**
|
||||
* Custom color palette for fancy visuals on raywhite background
|
||||
|
|
11
ROADMAP.md
11
ROADMAP.md
|
@ -4,16 +4,21 @@ roadmap
|
|||
Current version of raylib is quite complete and functional but there is still a lot of things to add and improve.
|
||||
Here it is a wish list of features I would like to add and functions to improve.
|
||||
|
||||
Note that around the raylib source code there are multiple TODO points with pending revisions/bugs. Check [GitHub Issues](https://github.com/raysan5/raylib/issues) for further details!
|
||||
Note raylib source code has multiple TODO points with pending things to review and improve. Check [GitHub Issues](https://github.com/raysan5/raylib/issues) for further details!
|
||||
|
||||
raylib 1.x
|
||||
|
||||
[IN PROGRESS] LUA scripting support (wrapper to lua lib)
|
||||
Basic GPU stats sytem (memory, draws, time...)
|
||||
Improved custom file-format (.rres) and packaging tool
|
||||
Procedural image generation functions (spot, gradient, noise...)
|
||||
Procedural mesh generation functions (cube, cone, sphere...)
|
||||
Touch-based camera controls for Android
|
||||
Skybox and Fog support
|
||||
Gamepad support on HTML5
|
||||
|
||||
raylib 1.6
|
||||
|
||||
[DONE] LUA scripting support (raylib lua wrapper)
|
||||
[DONE] Redesigned audio module
|
||||
|
||||
raylib 1.5
|
||||
|
||||
|
|
|
@ -3,17 +3,29 @@
|
|||
* raylib [core] example - Gamepad input
|
||||
*
|
||||
* NOTE: This example requires a Gamepad connected to the system
|
||||
* raylib is configured to work with Xbox 360 gamepad, check raylib.h for buttons configuration
|
||||
* raylib is configured to work with the following gamepads:
|
||||
* Xbox 360 Controller (Xbox 360, Xbox One)
|
||||
* PLAYSTATION(R)3 Controller
|
||||
* Check raylib.h for buttons configuration
|
||||
*
|
||||
* This example has been created using raylib 1.0 (www.raylib.com)
|
||||
* This example has been created using raylib 1.6 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
*
|
||||
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2013-2016 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
// NOTE: Gamepad name ID depends on drivers and OS
|
||||
#if defined(PLATFORM_RPI)
|
||||
#define XBOX360_NAME_ID "Microsoft X-Box 360 pad"
|
||||
#define PS3_NAME_ID "PLAYSTATION(R)3 Controller"
|
||||
#else
|
||||
#define XBOX360_NAME_ID "Xbox 360 Controller"
|
||||
#define PS3_NAME_ID "PLAYSTATION(R)3 Controller"
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
// Initialization
|
||||
|
@ -21,12 +33,14 @@ int main()
|
|||
int screenWidth = 800;
|
||||
int screenHeight = 450;
|
||||
|
||||
SetConfigFlags(FLAG_MSAA_4X_HINT); // Set MSAA 4X hint before windows creation
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - gamepad input");
|
||||
|
||||
Texture2D texPs3Pad = LoadTexture("resources/ps3.png");
|
||||
Texture2D texXboxPad = LoadTexture("resources/xbox.png");
|
||||
|
||||
Vector2 ballPosition = { (float)screenWidth/2, (float)screenHeight/2 };
|
||||
Vector2 gamepadMovement = { 0.0f, 0.0f };
|
||||
|
||||
SetTargetFPS(60); // Set target frames-per-second
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
|
@ -34,20 +48,7 @@ int main()
|
|||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsGamepadAvailable(GAMEPAD_PLAYER1))
|
||||
{
|
||||
gamepadMovement.x = GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_XBOX_AXIS_LEFT_X);
|
||||
gamepadMovement.y = GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_XBOX_AXIS_LEFT_Y);
|
||||
|
||||
ballPosition.x += gamepadMovement.x;
|
||||
ballPosition.y -= gamepadMovement.y;
|
||||
|
||||
if (IsGamepadButtonPressed(GAMEPAD_PLAYER1, GAMEPAD_BUTTON_A))
|
||||
{
|
||||
ballPosition.x = (float)screenWidth/2;
|
||||
ballPosition.y = (float)screenHeight/2;
|
||||
}
|
||||
}
|
||||
// ...
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
|
@ -55,10 +56,127 @@ int main()
|
|||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
if (IsGamepadAvailable(GAMEPAD_PLAYER1))
|
||||
{
|
||||
DrawText(FormatText("GP1: %s", GetGamepadName(GAMEPAD_PLAYER1)), 10, 10, 10, BLACK);
|
||||
|
||||
DrawText("move the ball with gamepad", 10, 10, 20, DARKGRAY);
|
||||
if (IsGamepadName(GAMEPAD_PLAYER1, XBOX360_NAME_ID))
|
||||
{
|
||||
DrawTexture(texXboxPad, 0, 0, DARKGRAY);
|
||||
|
||||
// Draw buttons: xbox home
|
||||
if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_HOME)) DrawCircle(394, 89, 19, RED);
|
||||
|
||||
DrawCircleV(ballPosition, 50, MAROON);
|
||||
// Draw buttons: basic
|
||||
if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_START)) DrawCircle(436, 150, 9, RED);
|
||||
if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_SELECT)) DrawCircle(352, 150, 9, RED);
|
||||
if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_X)) DrawCircle(501, 151, 15, BLUE);
|
||||
if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_A)) DrawCircle(536, 187, 15, LIME);
|
||||
if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_B)) DrawCircle(572, 151, 15, MAROON);
|
||||
if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_Y)) DrawCircle(536, 115, 15, GOLD);
|
||||
|
||||
// Draw buttons: d-pad
|
||||
DrawRectangle(317, 202, 19, 71, BLACK);
|
||||
DrawRectangle(293, 228, 69, 19, BLACK);
|
||||
if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_UP)) DrawRectangle(317, 202, 19, 26, RED);
|
||||
if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_DOWN)) DrawRectangle(317, 202 + 45, 19, 26, RED);
|
||||
if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_LEFT)) DrawRectangle(292, 228, 25, 19, RED);
|
||||
if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_RIGHT)) DrawRectangle(292 + 44, 228, 26, 19, RED);
|
||||
|
||||
// Draw buttons: left-right back
|
||||
if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_LB)) DrawCircle(259, 61, 20, RED);
|
||||
if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_RB)) DrawCircle(536, 61, 20, RED);
|
||||
|
||||
// Draw axis: left joystick
|
||||
DrawCircle(259, 152, 39, BLACK);
|
||||
DrawCircle(259, 152, 34, LIGHTGRAY);
|
||||
DrawCircle(259 + (GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_XBOX_AXIS_LEFT_X)*20),
|
||||
152 - (GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_XBOX_AXIS_LEFT_Y)*20), 25, BLACK);
|
||||
|
||||
// Draw axis: right joystick
|
||||
DrawCircle(461, 237, 38, BLACK);
|
||||
DrawCircle(461, 237, 33, LIGHTGRAY);
|
||||
DrawCircle(461 + (GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_XBOX_AXIS_RIGHT_X)*20),
|
||||
237 - (GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_XBOX_AXIS_RIGHT_Y)*20), 25, BLACK);
|
||||
|
||||
// Draw axis: left-right triggers
|
||||
DrawRectangle(170, 30, 15, 70, GRAY);
|
||||
DrawRectangle(604, 30, 15, 70, GRAY);
|
||||
DrawRectangle(170, 30, 15, (((1.0f + GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_XBOX_AXIS_LT))/2.0f)*70), RED);
|
||||
DrawRectangle(604, 30, 15, (((1.0f + GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_XBOX_AXIS_RT))/2.0f)*70), RED);
|
||||
|
||||
//DrawText(FormatText("Xbox axis LT: %02.02f", GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_XBOX_AXIS_LT)), 10, 40, 10, BLACK);
|
||||
//DrawText(FormatText("Xbox axis RT: %02.02f", GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_XBOX_AXIS_RT)), 10, 60, 10, BLACK);
|
||||
}
|
||||
else if (IsGamepadName(GAMEPAD_PLAYER1, PS3_NAME_ID))
|
||||
{
|
||||
DrawTexture(texPs3Pad, 0, 0, DARKGRAY);
|
||||
|
||||
// Draw buttons: ps
|
||||
if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_PS)) DrawCircle(396, 222, 13, RED);
|
||||
|
||||
// Draw buttons: basic
|
||||
if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_SELECT)) DrawRectangle(328, 170, 32, 13, RED);
|
||||
if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_START)) DrawTriangle((Vector2){ 436, 168 }, (Vector2){ 436, 185 }, (Vector2){ 464, 177 }, RED);
|
||||
if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_TRIANGLE)) DrawCircle(557, 144, 13, LIME);
|
||||
if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_CIRCLE)) DrawCircle(586, 173, 13, RED);
|
||||
if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_CROSS)) DrawCircle(557, 203, 13, VIOLET);
|
||||
if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_SQUARE)) DrawCircle(527, 173, 13, PINK);
|
||||
|
||||
// Draw buttons: d-pad
|
||||
DrawRectangle(225, 132, 24, 84, BLACK);
|
||||
DrawRectangle(195, 161, 84, 25, BLACK);
|
||||
if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_UP)) DrawRectangle(225, 132, 24, 29, RED);
|
||||
if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_DOWN)) DrawRectangle(225, 132 + 54, 24, 30, RED);
|
||||
if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_LEFT)) DrawRectangle(195, 161, 30, 25, RED);
|
||||
if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_RIGHT)) DrawRectangle(195 + 54, 161, 30, 25, RED);
|
||||
|
||||
// Draw buttons: left-right back buttons
|
||||
if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_L1)) DrawCircle(239, 82, 20, RED);
|
||||
if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_R1)) DrawCircle(557, 82, 20, RED);
|
||||
|
||||
// Draw axis: left joystick
|
||||
DrawCircle(319, 255, 35, BLACK);
|
||||
DrawCircle(319, 255, 31, LIGHTGRAY);
|
||||
DrawCircle(319 + (GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_PS3_AXIS_LEFT_X)*20),
|
||||
255 + (GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_PS3_AXIS_LEFT_Y)*20), 25, BLACK);
|
||||
|
||||
// Draw axis: right joystick
|
||||
DrawCircle(475, 255, 35, BLACK);
|
||||
DrawCircle(475, 255, 31, LIGHTGRAY);
|
||||
DrawCircle(475 + (GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_PS3_AXIS_RIGHT_X)*20),
|
||||
255 + (GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_PS3_AXIS_RIGHT_Y)*20), 25, BLACK);
|
||||
|
||||
// Draw axis: left-right triggers
|
||||
DrawRectangle(169, 48, 15, 70, GRAY);
|
||||
DrawRectangle(611, 48, 15, 70, GRAY);
|
||||
DrawRectangle(169, 48, 15, (((1.0f - GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_PS3_AXIS_L2))/2.0f)*70), RED);
|
||||
DrawRectangle(611, 48, 15, (((1.0f - GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_PS3_AXIS_R2))/2.0f)*70), RED);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawText("- GENERIC GAMEPAD -", 280, 180, 20, GRAY);
|
||||
|
||||
// TODO: Draw generic gamepad
|
||||
}
|
||||
|
||||
DrawText(FormatText("DETECTED AXIS [%i]:", GetGamepadAxisCount(GAMEPAD_PLAYER1)), 10, 50, 10, MAROON);
|
||||
|
||||
for (int i = 0; i < GetGamepadAxisCount(GAMEPAD_PLAYER1); i++)
|
||||
{
|
||||
DrawText(FormatText("AXIS %i: %.02f", i, GetGamepadAxisMovement(GAMEPAD_PLAYER1, i)), 20, 70 + 20*i, 10, DARKGRAY);
|
||||
}
|
||||
|
||||
if (GetGamepadButtonPressed() != -1) DrawText(FormatText("DETECTED BUTTON: %i", GetGamepadButtonPressed()), 10, 430, 10, RED);
|
||||
else DrawText("DETECTED BUTTON: NONE", 10, 430, 10, GRAY);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawText("GP1: NOT DETECTED", 10, 10, 10, GRAY);
|
||||
|
||||
DrawTexture(texXboxPad, 0, 0, LIGHTGRAY);
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -66,6 +184,9 @@ int main()
|
|||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadTexture(texPs3Pad);
|
||||
UnloadTexture(texXboxPad);
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
|
@ -32,7 +32,8 @@ int main()
|
|||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
framesCounter++;
|
||||
if (IsKeyDown(KEY_SPACE)) framesCounter += 8;
|
||||
else framesCounter++;
|
||||
|
||||
if (IsKeyPressed(KEY_ENTER)) framesCounter = 0;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -45,7 +46,8 @@ int main()
|
|||
|
||||
DrawText(SubText(message, 0, framesCounter/10), 210, 160, 20, MAROON);
|
||||
|
||||
DrawText("PRESS [ENTER] to RESTART!", 240, 280, 20, LIGHTGRAY);
|
||||
DrawText("PRESS [ENTER] to RESTART!", 240, 260, 20, LIGHTGRAY);
|
||||
DrawText("PRESS [SPACE] to SPEED UP!", 239, 300, 20, LIGHTGRAY);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
|
|
|
@ -706,7 +706,7 @@ Music LoadMusicStream(const char *fileName)
|
|||
else
|
||||
{
|
||||
music->stream = InitAudioStream(music->ctxFlac->sampleRate, music->ctxFlac->bitsPerSample, music->ctxFlac->channels);
|
||||
music->totalSamples = music->ctxFlac->totalSampleCount;
|
||||
music->totalSamples = (unsigned int)music->ctxFlac->totalSampleCount;
|
||||
music->samplesLeft = music->totalSamples;
|
||||
music->ctxType = MUSIC_AUDIO_FLAC;
|
||||
music->loop = true; // We loop by default
|
||||
|
@ -853,7 +853,7 @@ void UpdateMusicStream(Music music)
|
|||
int pcmi[AUDIO_BUFFER_SIZE];
|
||||
|
||||
// NOTE: Returns the number of samples to process (should be the same as numSamples)
|
||||
int numSamplesFlac = drflac_read_s32(music->ctxFlac, numSamples, pcmi);
|
||||
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);
|
||||
|
@ -1237,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));
|
||||
|
|
317
src/core.c
317
src/core.c
|
@ -22,7 +22,7 @@
|
|||
*
|
||||
* RL_LOAD_DEFAULT_FONT - Use external module functions to load default raylib font (module: 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.
|
||||
|
@ -58,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
|
||||
|
@ -79,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
|
||||
|
||||
|
@ -97,8 +96,8 @@
|
|||
#include <sys/ioctl.h> // UNIX System call for device-specific input/output operations - ioctl()
|
||||
#include <linux/kd.h> // Linux: KDSKBMODE, K_MEDIUMRAM constants definition
|
||||
#include <linux/input.h> // Linux: Keycodes constants definition (KEY_A, ...)
|
||||
#include <linux/joystick.h>
|
||||
|
||||
#include <linux/joystick.h> // Linux: Joystick support library
|
||||
|
||||
#include "bcm_host.h" // Raspberry Pi VideoCore IV access functions
|
||||
|
||||
#include "EGL/egl.h" // Khronos EGL library - Native platform display device control functions
|
||||
|
@ -131,7 +130,7 @@
|
|||
#endif
|
||||
|
||||
#define MAX_GAMEPADS 4 // Max number of gamepads supported
|
||||
#define MAX_GAMEPAD_BUTTONS 11 // Max bumber of buttons supported (per gamepad)
|
||||
#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)
|
||||
|
@ -158,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)
|
||||
|
@ -179,6 +175,7 @@ static pthread_t mouseThreadId; // Mouse reading thread id
|
|||
// Gamepad input variables
|
||||
static int gamepadStream[MAX_GAMEPADS] = { -1 };// Gamepad device file descriptor
|
||||
static pthread_t gamepadThreadId; // Gamepad reading thread id
|
||||
static char gamepadName[64]; // Gamepad name holder
|
||||
#endif
|
||||
|
||||
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
|
||||
|
@ -202,10 +199,7 @@ 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
|
||||
|
||||
// Register keyboard states
|
||||
static char previousKeyState[512] = { 0 }; // Registers previous frame key state
|
||||
static char currentKeyState[512] = { 0 }; // Registers current frame key state
|
||||
static bool cursorHidden = false; // Track if cursor is hidden
|
||||
|
||||
// Register mouse states
|
||||
static char previousMouseState[3] = { 0 }; // Registers previous mouse button state
|
||||
|
@ -216,16 +210,21 @@ static int currentMouseWheelY = 0; // Registers current mouse wheel var
|
|||
// 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] = { 0 };
|
||||
static char currentGamepadState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS] = { 0 };
|
||||
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
|
||||
|
||||
|
@ -363,7 +362,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)");
|
||||
|
||||
|
@ -372,7 +371,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
|
||||
|
@ -466,6 +465,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
|
||||
|
@ -526,6 +528,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)
|
||||
{
|
||||
|
@ -1044,7 +1105,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)
|
||||
{
|
||||
|
@ -1067,7 +1127,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;
|
||||
|
||||
|
@ -1091,64 +1151,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)
|
||||
|
@ -1157,32 +1162,61 @@ bool IsCursorHidden()
|
|||
bool IsGamepadAvailable(int gamepad)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
|
||||
#if !defined(PLATFORM_ANDROID)
|
||||
if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad]) 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 (glfwJoystickPresent(gamepad) == 1) return glfwGetJoystickName(gamepad);
|
||||
if (gamepadReady[gamepad]) return glfwGetJoystickName(gamepad);
|
||||
else return NULL;
|
||||
#elif defined(PLATFORM_RPI)
|
||||
if (gamepadReady[gamepad]) ioctl(gamepadStream[gamepad], JSIOCGNAME(64), &gamepadName);
|
||||
|
||||
return gamepadName;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Return gamepad axis count
|
||||
int GetGamepadAxisCount(int gamepad)
|
||||
{
|
||||
#if defined(PLATFORM_RPI)
|
||||
int axisCount = 0;
|
||||
if (gamepadReady[gamepad]) ioctl(gamepadStream[gamepad], JSIOCGAXES, &axisCount);
|
||||
gamepadAxisCount = axisCount;
|
||||
#endif
|
||||
return gamepadAxisCount;
|
||||
}
|
||||
|
||||
// Return axis movement vector for a gamepad
|
||||
float GetGamepadAxisMovement(int gamepad, int axis)
|
||||
{
|
||||
float value = 0;
|
||||
|
||||
if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (axis < MAX_GAMEPAD_AXIS))
|
||||
{
|
||||
value = gamepadAxisState[gamepad][axis];
|
||||
}
|
||||
|
||||
#if !defined(PLATFORM_ANDROID)
|
||||
if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (axis < MAX_GAMEPAD_AXIS)) value = gamepadAxisState[gamepad][axis];
|
||||
#endif
|
||||
|
||||
return value;
|
||||
}
|
||||
|
@ -1191,10 +1225,12 @@ float GetGamepadAxisMovement(int gamepad, int axis)
|
|||
bool IsGamepadButtonPressed(int gamepad, int button)
|
||||
{
|
||||
bool 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;
|
||||
}
|
||||
|
@ -1204,8 +1240,10 @@ bool IsGamepadButtonDown(int gamepad, int button)
|
|||
{
|
||||
bool result = false;
|
||||
|
||||
if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (button < MAX_GAMEPAD_BUTTONS) &&
|
||||
#if !defined(PLATFORM_ANDROID)
|
||||
if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (button < MAX_GAMEPAD_BUTTONS) &&
|
||||
(currentGamepadState[gamepad][button] == 1)) result = true;
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -1215,9 +1253,11 @@ bool IsGamepadButtonReleased(int gamepad, int button)
|
|||
{
|
||||
bool 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;
|
||||
}
|
||||
|
@ -1227,13 +1267,19 @@ bool IsGamepadButtonUp(int gamepad, int button)
|
|||
{
|
||||
bool 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)
|
||||
|
@ -1387,37 +1433,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
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -1900,8 +1915,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;
|
||||
|
@ -1929,6 +1945,15 @@ 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;
|
||||
|
||||
#if !defined(PLATFORM_RPI)
|
||||
// Reset last gamepad button/axis registered state
|
||||
lastGamepadButtonPressed = -1;
|
||||
gamepadAxisCount = 0;
|
||||
#endif
|
||||
|
||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
||||
// Mouse input polling
|
||||
|
@ -1939,9 +1964,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];
|
||||
|
@ -1952,13 +1976,19 @@ 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 (glfwJoystickPresent(i)) // Check if gamepad is available
|
||||
if (gamepadReady[i]) // Check if gamepad is available
|
||||
{
|
||||
gamepadReady[i] = true;
|
||||
|
||||
// Register previous gamepad states
|
||||
for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) previousGamepadState[i][k] = currentGamepadState[i][k];
|
||||
|
||||
|
@ -1971,7 +2001,11 @@ static void PollInputEvents(void)
|
|||
|
||||
for (int k = 0; (buttons != NULL) && (k < buttonsCount) && (buttonsCount < MAX_GAMEPAD_BUTTONS); k++)
|
||||
{
|
||||
if (buttons[i] == GLFW_PRESS) currentGamepadState[i][k] = 1;
|
||||
if (buttons[k] == GLFW_PRESS)
|
||||
{
|
||||
currentGamepadState[i][k] = 1;
|
||||
lastGamepadButtonPressed = k;
|
||||
}
|
||||
else currentGamepadState[i][k] = 0;
|
||||
}
|
||||
|
||||
|
@ -1985,8 +2019,9 @@ static void PollInputEvents(void)
|
|||
{
|
||||
gamepadAxisState[i][k] = axes[k];
|
||||
}
|
||||
|
||||
gamepadAxisCount = axisCount;
|
||||
}
|
||||
else gamepadReady[i] = false;
|
||||
}
|
||||
|
||||
glfwPollEvents(); // Register keyboard/mouse events (callbacks)... and window events!
|
||||
|
@ -1994,7 +2029,8 @@ static void PollInputEvents(void)
|
|||
|
||||
#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)
|
||||
|
@ -2371,7 +2407,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)
|
||||
{
|
||||
|
@ -2818,6 +2860,9 @@ static void *GamepadThread(void *arg)
|
|||
{
|
||||
// 1 - button pressed, 0 - button released
|
||||
currentGamepadState[i][gamepadEvent.number] = (int)gamepadEvent.value;
|
||||
|
||||
if ((int)gamepadEvent.value == 1) lastGamepadButtonPressed = gamepadEvent.number;
|
||||
else lastGamepadButtonPressed = -1;
|
||||
}
|
||||
}
|
||||
else if (gamepadEvent.type == JS_EVENT_AXIS)
|
||||
|
|
138
src/models.c
138
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();
|
||||
|
@ -1411,7 +1411,7 @@ bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB, floa
|
|||
float dy = centerA.y - centerB.y; // Y distance between centers
|
||||
float dz = centerA.z - centerB.z; // Y distance between centers
|
||||
|
||||
float distance = sqrt(dx*dx + dy*dy + dz*dz); // Distance between centers
|
||||
float distance = sqrtf(dx*dx + dy*dy + dz*dz); // Distance between centers
|
||||
|
||||
if (distance <= (radiusA + radiusB)) collision = true;
|
||||
|
||||
|
@ -1441,14 +1441,14 @@ bool CheckCollisionBoxSphere(BoundingBox box, Vector3 centerSphere, float radius
|
|||
|
||||
float dmin = 0;
|
||||
|
||||
if (centerSphere.x < box.min.x) dmin += pow(centerSphere.x - box.min.x, 2);
|
||||
else if (centerSphere.x > box.max.x) dmin += pow(centerSphere.x - box.max.x, 2);
|
||||
if (centerSphere.x < box.min.x) dmin += powf(centerSphere.x - box.min.x, 2);
|
||||
else if (centerSphere.x > box.max.x) dmin += powf(centerSphere.x - box.max.x, 2);
|
||||
|
||||
if (centerSphere.y < box.min.y) dmin += pow(centerSphere.y - box.min.y, 2);
|
||||
else if (centerSphere.y > box.max.y) dmin += pow(centerSphere.y - box.max.y, 2);
|
||||
if (centerSphere.y < box.min.y) dmin += powf(centerSphere.y - box.min.y, 2);
|
||||
else if (centerSphere.y > box.max.y) dmin += powf(centerSphere.y - box.max.y, 2);
|
||||
|
||||
if (centerSphere.z < box.min.z) dmin += pow(centerSphere.z - box.min.z, 2);
|
||||
else if (centerSphere.z > box.max.z) dmin += pow(centerSphere.z - box.max.z, 2);
|
||||
if (centerSphere.z < box.min.z) dmin += powf(centerSphere.z - box.min.z, 2);
|
||||
else if (centerSphere.z > box.max.z) dmin += powf(centerSphere.z - box.max.z, 2);
|
||||
|
||||
if (dmin <= (radiusSphere*radiusSphere)) collision = true;
|
||||
|
||||
|
@ -1487,8 +1487,8 @@ bool CheckCollisionRaySphereEx(Ray ray, Vector3 spherePosition, float sphereRadi
|
|||
float collisionDistance = 0;
|
||||
|
||||
// Check if ray origin is inside the sphere to calculate the correct collision point
|
||||
if (distance < sphereRadius) collisionDistance = vector + sqrt(d);
|
||||
else collisionDistance = vector - sqrt(d);
|
||||
if (distance < sphereRadius) collisionDistance = vector + sqrtf(d);
|
||||
else collisionDistance = vector - sqrtf(d);
|
||||
|
||||
VectorScale(&offset, collisionDistance);
|
||||
Vector3 cPoint = VectorAdd(ray.position, offset);
|
||||
|
@ -1811,7 +1811,7 @@ static Material LoadMTL(const char *fileName)
|
|||
|
||||
char buffer[MAX_BUFFER_SIZE];
|
||||
Vector3 color = { 1.0f, 1.0f, 1.0f };
|
||||
char *mapFileName = NULL;
|
||||
char mapFileName[128];
|
||||
|
||||
FILE *mtlFile;
|
||||
|
||||
|
|
127
src/raylib.h
127
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,6 +170,14 @@
|
|||
#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
|
||||
#define MOUSE_RIGHT_BUTTON 1
|
||||
|
@ -188,21 +192,32 @@
|
|||
#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..-1] (pressure-level)
|
||||
#define GAMEPAD_PS3_AXIS_R2 4 // [1..-1] (pressure-level)
|
||||
|
||||
// Xbox360 USB Controller Buttons
|
||||
#define GAMEPAD_XBOX_BUTTON_A 0
|
||||
|
@ -213,33 +228,30 @@
|
|||
#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 8
|
||||
|
||||
// Xbox360 USB Controller Axis
|
||||
// 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_RIGHT_X 3
|
||||
#define GAMEPAD_XBOX_AXIS_RIGHT_Y 4
|
||||
#define GAMEPAD_XBOX_AXIS_LT 2
|
||||
#define GAMEPAD_XBOX_AXIS_RT 5
|
||||
#define GAMEPAD_XBOX_AXIS_LEFT_X 0 // [-1..1] (left->right)
|
||||
#define GAMEPAD_XBOX_AXIS_LEFT_Y 1 // [-1..1] (up->down)
|
||||
#define GAMEPAD_XBOX_AXIS_RIGHT_X 3 // [-1..1] (left->right)
|
||||
#define GAMEPAD_XBOX_AXIS_RIGHT_Y 4 // [-1..1] (up->down)
|
||||
#define GAMEPAD_XBOX_AXIS_LT 2 // [-1..1] (pressure-level)
|
||||
#define GAMEPAD_XBOX_AXIS_RT 5 // [-1..1] (pressure-level)
|
||||
#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
|
||||
#define GAMEPAD_XBOX_AXIS_LEFT_X 0 // [-1..1] (left->right)
|
||||
#define GAMEPAD_XBOX_AXIS_LEFT_Y 1 // [1..-1] (up->down)
|
||||
#define GAMEPAD_XBOX_AXIS_RIGHT_X 2 // [-1..1] (left->right)
|
||||
#define GAMEPAD_XBOX_AXIS_RIGHT_Y 3 // [1..-1] (up->down)
|
||||
#define GAMEPAD_XBOX_AXIS_LT 4 // [-1..1] (pressure-level)
|
||||
#define GAMEPAD_XBOX_AXIS_RT 5 // [-1..1] (pressure-level)
|
||||
#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.
|
||||
#ifdef __cplusplus
|
||||
|
@ -535,6 +547,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;
|
||||
|
||||
|
@ -589,7 +616,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
|
||||
|
@ -601,11 +628,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
|
||||
|
@ -648,7 +677,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
|
||||
|
@ -657,13 +685,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 bool IsGamepadName(int gamepad, const char *name); // Check gamepad name (if available)
|
||||
RLAPI const char *GetGamepadName(int gamepad); // Return gamepad internal name id
|
||||
RLAPI float GetGamepadAxisMovement(int gamepad, int axis); // Return axis movement value for a gamepad axis
|
||||
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
|
||||
|
@ -679,12 +709,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)
|
||||
//------------------------------------------------------------------------------------
|
||||
|
@ -758,6 +782,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
|
||||
|
@ -779,7 +804,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
|
||||
|
@ -793,13 +819,14 @@ 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)
|
||||
RLAPI void DrawTextEx(SpriteFont spriteFont, const char* text, Vector2 position, // Draw text using SpriteFont and additional parameters
|
||||
float fontSize, int spacing, Color tint);
|
||||
RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font
|
||||
RLAPI Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, int fontSize, int spacing); // Measure string size for SpriteFont
|
||||
RLAPI Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, float fontSize, int spacing); // Measure string size for SpriteFont
|
||||
|
||||
RLAPI void DrawFPS(int posX, int posY); // Shows current FPS on top-left corner
|
||||
RLAPI const char *FormatText(const char *text, ...); // Formatting of text with variables to 'embed'
|
||||
|
|
104
src/rlgl.c
104
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
|
||||
//----------------------------------------------------------
|
||||
|
@ -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
|
||||
|
@ -2735,15 +2795,11 @@ void ToggleVrMode(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();
|
||||
|
||||
// TODO: Update camera data (position, target, up) with tracking data
|
||||
}
|
||||
if (vrDeviceReady) UpdateOculusTracking(camera);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -3786,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 };
|
||||
|
||||
|
@ -3804,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]);
|
||||
|
@ -3826,7 +3882,7 @@ static void SetStereoConfig(VrDeviceInfo hmd)
|
|||
// Fovy is normally computed with: 2*atan2(hmd.vScreenSize, 2*hmd.eyeToScreenDistance)*RAD2DEG
|
||||
// ...but with lens distortion it is increased (see Oculus SDK Documentation)
|
||||
//float fovy = 2.0f*atan2(hmd.vScreenSize*0.5f*distortionScale, hmd.eyeToScreenDistance)*RAD2DEG; // Really need distortionScale?
|
||||
float fovy = 2.0f*atan2(hmd.vScreenSize*0.5f, hmd.eyeToScreenDistance)*RAD2DEG;
|
||||
float fovy = 2.0f*(float)atan2(hmd.vScreenSize*0.5f, hmd.eyeToScreenDistance)*RAD2DEG;
|
||||
|
||||
// Compute camera projection matrices
|
||||
float projOffset = 4.0f*lensShift; // Scaled to projection space coordinates [-1..1]
|
||||
|
@ -4083,7 +4139,7 @@ OCULUSAPI void CloseOculusDevice(void)
|
|||
}
|
||||
|
||||
// Update Oculus head position-orientation tracking
|
||||
OCULUSAPI void UpdateOculusTracking(void)
|
||||
OCULUSAPI void UpdateOculusTracking(Camera *camera)
|
||||
{
|
||||
frameIndex++;
|
||||
|
||||
|
@ -4093,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);
|
||||
|
|
40
src/rlgl.h
40
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
|
||||
|
@ -381,7 +415,7 @@ void ToggleVrMode(void); // Enable/Disable VR experience (dev
|
|||
// 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
|
||||
|
|
37
src/shapes.c
37
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();
|
||||
}
|
||||
|
@ -130,8 +129,8 @@ void DrawCircleV(Vector2 center, float radius, Color color)
|
|||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
|
||||
rlVertex2f(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 + 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();
|
||||
}
|
||||
|
@ -145,9 +144,9 @@ void DrawCircleV(Vector2 center, float radius, Color color)
|
|||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
|
||||
rlVertex2f(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 + 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();
|
||||
}
|
||||
|
@ -331,8 +330,8 @@ void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color col
|
|||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
|
||||
rlVertex2f(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(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));
|
||||
}
|
||||
|
|
237
src/text.c
237
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;
|
||||
}
|
||||
|
@ -311,13 +344,13 @@ void DrawText(const char *text, int posX, int posY, int fontSize, Color color)
|
|||
void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float fontSize, int spacing, Color tint)
|
||||
{
|
||||
int length = strlen(text);
|
||||
int textOffsetX = 0;
|
||||
int textOffsetY = 0; // Line break!
|
||||
int textOffsetX = 0; // Offset between characters
|
||||
int textOffsetY = 0; // Required for line break!
|
||||
float scaleFactor;
|
||||
unsigned char letter;
|
||||
|
||||
Rectangle rec;
|
||||
|
||||
|
||||
unsigned char letter; // Current character
|
||||
int index; // Index position in sprite font
|
||||
|
||||
scaleFactor = fontSize/spriteFont.size;
|
||||
|
||||
// NOTE: Some ugly hacks are made to support Latin-1 Extended characters directly
|
||||
|
@ -325,44 +358,38 @@ 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!
|
||||
if ((unsigned char)text[i] == '\n')
|
||||
{
|
||||
// Support UTF-8 encoded values from [0xc2 0x80] -> [0xc2 0xbf](¿)
|
||||
letter = (unsigned char)text[i + 1];
|
||||
rec = spriteFont.charRecs[letter - FONT_FIRST_CHAR];
|
||||
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];
|
||||
i++;
|
||||
// NOTE: Fixed line spacing of 1.5 lines
|
||||
textOffsetY += ((spriteFont.size + spriteFont.size/2)*scaleFactor);
|
||||
textOffsetX = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((unsigned char)text[i] == '\n')
|
||||
if ((unsigned char)text[i] == 0xc2) // UTF-8 encoding identification HACK!
|
||||
{
|
||||
// NOTE: Fixed line spacing of 1.5 lines
|
||||
textOffsetY += ((spriteFont.size + spriteFont.size/2)*scaleFactor);
|
||||
textOffsetX = 0;
|
||||
rec.x = -1;
|
||||
// Support UTF-8 encoded values from [0xc2 0x80] -> [0xc2 0xbf](¿)
|
||||
letter = (unsigned char)text[i + 1];
|
||||
index = GetCharIndex(spriteFont, (int)letter);
|
||||
i++;
|
||||
}
|
||||
else rec = spriteFont.charRecs[(int)text[i] - FONT_FIRST_CHAR];
|
||||
}
|
||||
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];
|
||||
index = GetCharIndex(spriteFont, (int)letter + 64);
|
||||
i++;
|
||||
}
|
||||
else index = GetCharIndex(spriteFont, (int)text[i]);
|
||||
|
||||
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,
|
||||
rec.width*scaleFactor, rec.height*scaleFactor} , (Vector2){ 0, 0 }, 0.0f, tint);
|
||||
DrawTexturePro(spriteFont.texture, spriteFont.charRecs[index],
|
||||
(Rectangle){ position.x + textOffsetX + spriteFont.charOffsets[index].x*scaleFactor,
|
||||
position.y + textOffsetY + spriteFont.charOffsets[index].y*scaleFactor,
|
||||
spriteFont.charRecs[index].width*scaleFactor,
|
||||
spriteFont.charRecs[index].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 += (spriteFont.charRecs[index].width*scaleFactor + spacing);
|
||||
else textOffsetX += (spriteFont.charAdvanceX[index]*scaleFactor + spacing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -417,14 +444,14 @@ int MeasureText(const char *text, int fontSize)
|
|||
if (fontSize < defaultFontSize) fontSize = defaultFontSize;
|
||||
int spacing = fontSize/defaultFontSize;
|
||||
|
||||
vec = MeasureTextEx(GetDefaultFont(), text, fontSize, spacing);
|
||||
vec = MeasureTextEx(GetDefaultFont(), text, (float)fontSize, spacing);
|
||||
}
|
||||
|
||||
return (int)vec.x;
|
||||
}
|
||||
|
||||
// Measure string size for SpriteFont
|
||||
Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, int fontSize, int spacing)
|
||||
Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, float fontSize, int spacing)
|
||||
{
|
||||
int len = strlen(text);
|
||||
int tempLen = 0; // Used to count longer text line num chars
|
||||
|
@ -434,7 +461,7 @@ Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, int fontSize, int
|
|||
int tempTextWidth = 0; // Used to count longer text line width
|
||||
|
||||
int textHeight = spriteFont.size;
|
||||
float scaleFactor;
|
||||
float scaleFactor = fontSize/spriteFont.size;
|
||||
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
|
@ -442,8 +469,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
|
||||
{
|
||||
|
@ -458,9 +487,6 @@ Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, int fontSize, int
|
|||
|
||||
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
|
||||
|
||||
if (fontSize <= spriteFont.size) scaleFactor = 1.0f;
|
||||
else scaleFactor = (float)fontSize/spriteFont.size;
|
||||
|
||||
Vector2 vec;
|
||||
vec.x = (float)tempTextWidth*scaleFactor + (tempLen - 1)*spacing; // Adds chars spacing to measure
|
||||
vec.y = (float)textHeight*scaleFactor;
|
||||
|
@ -500,7 +526,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))
|
||||
|
@ -511,8 +558,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
|
||||
|
@ -573,15 +620,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
|
||||
|
@ -811,8 +867,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));
|
||||
|
@ -820,22 +881,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 };
|
||||
|
@ -845,11 +902,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();
|
||||
|
@ -861,14 +914,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 };
|
||||
|
@ -877,40 +933,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;
|
||||
|
@ -922,7 +985,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;
|
||||
|
|
143
src/textures.c
143
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.
|
||||
|
@ -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