14 Commits

Author SHA1 Message Date
Ray
d1b535c7b8 Merge branch 'master' of https://github.com/raysan5/raylib 2025-08-14 21:23:08 +02:00
Ray
ed06cdbbe4 Update examples_report.md 2025-08-14 21:22:57 +02:00
Ray
81615a91a6 Merge pull request #5111 from didas72/master
Adds more filters for conditional build of GetWindowHandle with GLFW
2025-08-14 21:13:27 +02:00
Ray
6252d92f79 Update rexm.c 2025-08-14 21:11:30 +02:00
Ray
a65bdd6cca REXM: Reviewed automatic validation and update -WIP- 2025-08-14 21:07:36 +02:00
Ray
afdc7972d6 REXM: Automatic validation and update of examples 2025-08-14 21:07:10 +02:00
3ef5ee878c Adjusted formatting to comply with contribution guidelines 2025-08-14 19:58:22 +01:00
Ray
28b804a6ba REXM: Validate examples list against existing examples in repo 2025-08-14 20:38:27 +02:00
Ray
7037f131dc REVIEWED: example: core_3d_fps_controller 2025-08-14 20:37:52 +02:00
Ray
a9970484f3 Remove trailing spaces 2025-08-14 20:37:18 +02:00
Ray
be974bb67e Update CONVENTIONS.md 2025-08-14 20:36:08 +02:00
eae1296b08 Fixed bad macro logic 2025-08-14 18:56:31 +01:00
59c979a59d Added suggestions by planetis-m 2025-08-14 18:46:45 +01:00
93f86fa074 fixes #5110
Adds more filters for conditional build of GetWindowHandle with glfw
2025-08-14 14:30:29 +01:00
15 changed files with 380 additions and 294 deletions

View File

@ -11,7 +11,7 @@ Local variables | lowerCase | `Vector2 playerPosition = { 0 };`
Global variables | lowerCase | `bool windowReady = false;` Global variables | lowerCase | `bool windowReady = false;`
Constants | lowerCase | `const int maxValue = 8;` Constants | lowerCase | `const int maxValue = 8;`
Pointers | MyType *pointer | `Texture2D *array = NULL;` Pointers | MyType *pointer | `Texture2D *array = NULL;`
float values | always x.xf | `float gravity = 10.0f` float values | always x.xf | `float gravity = 10.0f` (avoid `10.f`)
Operators | value1*value2 | `int product = value*6;` Operators | value1*value2 | `int product = value*6;`
Operators | value1/value2 | `int division = value/4;` Operators | value1/value2 | `int division = value/4;`
Operators | value1 + value2 | `int sum = value + 10;` Operators | value1 + value2 | `int sum = value + 10;`

View File

@ -704,8 +704,7 @@ core/core_3d_camera_split_screen: core/core_3d_camera_split_screen.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
core/core_3d_fps_controller: core/core_3d_fps_controller.c core/core_3d_fps_controller: core/core_3d_fps_controller.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
--preload-file core/resources/huh_jump.wav@resources/huh_jump.wav
core/core_3d_picking: core/core_3d_picking.c core/core_3d_picking: core/core_3d_picking.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)

View File

@ -16,9 +16,9 @@ You may find it easier to use than other toolchains, especially when it comes to
- `zig build [module]` to compile all examples for a module (e.g. `zig build core`) - `zig build [module]` to compile all examples for a module (e.g. `zig build core`)
- `zig build [example]` to compile _and run_ a particular example (e.g. `zig build core_basic_window`) - `zig build [example]` to compile _and run_ a particular example (e.g. `zig build core_basic_window`)
## EXAMPLES COLLECTION [TOTAL: 160] ## EXAMPLES COLLECTION [TOTAL: 161]
### category: core [36] ### category: core [37]
Examples using raylib[core](../src/rcore.c) platform functionality like window creation, inputs, drawing modes and system functionality. Examples using raylib[core](../src/rcore.c) platform functionality like window creation, inputs, drawing modes and system functionality.
@ -40,6 +40,7 @@ Examples using raylib[core](../src/rcore.c) platform functionality like window c
| [core_3d_camera_free](core/core_3d_camera_free.c) | <img src="core/core_3d_camera_free.png" alt="core_3d_camera_free" width="80"> | ⭐☆☆☆ | 1.3 | 1.3 | [Ramon Santamaria](https://github.com/raysan5) | | [core_3d_camera_free](core/core_3d_camera_free.c) | <img src="core/core_3d_camera_free.png" alt="core_3d_camera_free" width="80"> | ⭐☆☆☆ | 1.3 | 1.3 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_3d_camera_first_person](core/core_3d_camera_first_person.c) | <img src="core/core_3d_camera_first_person.png" alt="core_3d_camera_first_person" width="80"> | ⭐⭐☆☆ | 1.3 | 1.3 | [Ramon Santamaria](https://github.com/raysan5) | | [core_3d_camera_first_person](core/core_3d_camera_first_person.c) | <img src="core/core_3d_camera_first_person.png" alt="core_3d_camera_first_person" width="80"> | ⭐⭐☆☆ | 1.3 | 1.3 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_3d_camera_split_screen](core/core_3d_camera_split_screen.c) | <img src="core/core_3d_camera_split_screen.png" alt="core_3d_camera_split_screen" width="80"> | ⭐⭐⭐☆ | 3.7 | 4.0 | [Jeffery Myers](https://github.com/JeffM2501) | | [core_3d_camera_split_screen](core/core_3d_camera_split_screen.c) | <img src="core/core_3d_camera_split_screen.png" alt="core_3d_camera_split_screen" width="80"> | ⭐⭐⭐☆ | 3.7 | 4.0 | [Jeffery Myers](https://github.com/JeffM2501) |
| [core_3d_fps_controller](core/core_3d_fps_controller.c) | <img src="core/core_3d_fps_controller.png" alt="core_3d_fps_controller" width="80"> | ⭐⭐⭐☆ | 5.5 | 5.5 | [Agnis Aldins](https://github.com/nezvers) |
| [core_3d_picking](core/core_3d_picking.c) | <img src="core/core_3d_picking.png" alt="core_3d_picking" width="80"> | ⭐⭐☆☆ | 1.3 | 4.0 | [Ramon Santamaria](https://github.com/raysan5) | | [core_3d_picking](core/core_3d_picking.c) | <img src="core/core_3d_picking.png" alt="core_3d_picking" width="80"> | ⭐⭐☆☆ | 1.3 | 4.0 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_world_screen](core/core_world_screen.c) | <img src="core/core_world_screen.png" alt="core_world_screen" width="80"> | ⭐⭐☆☆ | 1.3 | 1.4 | [Ramon Santamaria](https://github.com/raysan5) | | [core_world_screen](core/core_world_screen.c) | <img src="core/core_world_screen.png" alt="core_world_screen" width="80"> | ⭐⭐☆☆ | 1.3 | 1.4 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_custom_logging](core/core_custom_logging.c) | <img src="core/core_custom_logging.png" alt="core_custom_logging" width="80"> | ⭐⭐⭐☆ | 2.5 | 2.5 | [Pablo Marcos Oltra](https://github.com/pamarcos) | | [core_custom_logging](core/core_custom_logging.c) | <img src="core/core_custom_logging.png" alt="core_custom_logging" width="80"> | ⭐⭐⭐☆ | 2.5 | 2.5 | [Pablo Marcos Oltra](https://github.com/pamarcos) |

View File

@ -1,10 +1,10 @@
/******************************************************************************************* /*******************************************************************************************
* *
* raylib [core] example - Input Gestures for Web * raylib [core] example - 3d first-person camera controller
* *
* Example complexity rating: [★★★☆] 3/4 * Example complexity rating: [★★★☆] 3/4
* *
* Example originally created with raylib 5.5 * Example originally created with raylib 5.5, last time updated with raylib 5.5
* *
* Example contributed by Agnis Aldins (@nezvers) and reviewed by Ramon Santamaria (@raysan5) * Example contributed by Agnis Aldins (@nezvers) and reviewed by Ramon Santamaria (@raysan5)
* *
@ -16,65 +16,60 @@
********************************************************************************************/ ********************************************************************************************/
#include "raylib.h" #include "raylib.h"
#include "raymath.h" #include "raymath.h"
#include "rcamera.h" #include "rcamera.h"
#if defined(PLATFORM_WEB) //----------------------------------------------------------------------------------
#include <emscripten/emscripten.h> // Defines and Macros
#endif //----------------------------------------------------------------------------------
// Movement constants
#define GRAVITY 32.0f
#define MAX_SPEED 20.0f
#define CROUCH_SPEED 5.0f
#define JUMP_FORCE 12.0f
#define MAX_ACCEL 150.0f
// Grounded drag
#define FRICTION 0.86f
// Increasing air drag, increases strafing speed
#define AIR_DRAG 0.98f
// Responsiveness for turning movement direction to looked direction
#define CONTROL 15.0f
#define CROUCH_HEIGHT 0.0f
#define STAND_HEIGHT 1.0f
#define BOTTOM_HEIGHT 0.5f
#if defined(PLATFORM_DESKTOP) #define NORMALIZE_INPUT 0
#define GLSL_VERSION 330
#else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100
#endif
/* Movement constants */
#define GRAVITY 32.f
#define MAX_SPEED 20.f
#define CROUCH_SPEED 5.f
#define JUMP_FORCE 12.f
#define MAX_ACCEL 150.f
/* Grounded drag */
#define FRICTION 0.86f
/* Increasing air drag, increases strafing speed */
#define AIR_DRAG 0.98f
/* Responsiveness for turning movement direction to looked direction */
#define CONTROL 15.f
#define CROUCH_HEIGHT 0.f
#define STAND_HEIGHT 1.f
#define BOTTOM_HEIGHT 0.5f
#define NORMALIZE_INPUT 0
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
// Body structure
typedef struct { typedef struct {
Vector3 position; Vector3 position;
Vector3 velocity; Vector3 velocity;
Vector3 dir; Vector3 dir;
bool isGrounded; bool isGrounded;
Sound soundJump; } Body;
}Body;
const int screenWidth = 800; //----------------------------------------------------------------------------------
const int screenHeight = 450; // Global Variables Definition
Vector2 sensitivity = { 0.001f, 0.001f }; //----------------------------------------------------------------------------------
static Vector2 sensitivity = { 0.001f, 0.001f };
Body player; static Body player = { 0 };
Camera camera; static Vector2 lookRotation = { 0 };
Vector2 lookRotation = { 0 }; static float headTimer = 0.0f;
float headTimer; static float walkLerp = 0.0f;
float walkLerp; static float headLerp = STAND_HEIGHT;
float headLerp; static Vector2 lean = { 0 };
Vector2 lean;
void UpdateDrawFrame(void); // Update and Draw one frame //----------------------------------------------------------------------------------
// Module functions declaration
void DrawLevel(); //----------------------------------------------------------------------------------
static void DrawLevel(void);
void UpdateCameraAngle(); static void UpdateCameraAngle(Camera *camera);
static void UpdateBody(Body *body, float rot, char side, char forward, bool jumpPressed, bool crouchHold);
void UpdateBody(Body* body, float rot, char side, char forward, bool jumpPressed, bool crouchHold);
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Program main entry point // Program main entry point
@ -83,213 +78,186 @@ int main(void)
{ {
// Initialization // Initialization
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
InitWindow(screenWidth, screenHeight, "Raylib Quake-like controller"); const int screenWidth = 800;
InitAudioDevice(); const int screenHeight = 450;
player = (Body){ Vector3Zero(), Vector3Zero(), Vector3Zero(), false, LoadSound("resources/huh_jump.wav")}; InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d first-person camera controller");
camera = (Camera){ 0 };
camera.fovy = 60.f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
lookRotation = Vector2Zero(); // Initialize camera variables
headTimer = 0.f; // NOTE: UpdateCameraAngle() takes care of the rest
walkLerp = 0.f; Camera camera = { 0 };
headLerp = STAND_HEIGHT; camera.fovy = 60.0f;
lean = Vector2Zero(); camera.projection = CAMERA_PERSPECTIVE;
camera.position = (Vector3){
player.position.x,
player.position.y + (BOTTOM_HEIGHT + headLerp),
player.position.z,
};
UpdateCameraAngle();
DisableCursor(); // Limit cursor to relative movement inside the window
#if defined(PLATFORM_WEB)
emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
#else
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
UpdateDrawFrame();
}
#endif
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadSound(player.soundJump);
CloseAudioDevice();
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
void UpdateDrawFrame(void)
{
// Update
//----------------------------------------------------------------------------------
Vector2 mouse_delta = GetMouseDelta();
lookRotation.x -= mouse_delta.x * sensitivity.x;
lookRotation.y += mouse_delta.y * sensitivity.y;
char sideway = (IsKeyDown(KEY_D) - IsKeyDown(KEY_A));
char forward = (IsKeyDown(KEY_W) - IsKeyDown(KEY_S));
bool crouching = IsKeyDown(KEY_LEFT_CONTROL);
UpdateBody(&player, lookRotation.x, sideway, forward, IsKeyPressed(KEY_SPACE), crouching);
float delta = GetFrameTime();
headLerp = Lerp(headLerp, (crouching ? CROUCH_HEIGHT : STAND_HEIGHT), 20.f * delta);
camera.position = (Vector3){ camera.position = (Vector3){
player.position.x, player.position.x,
player.position.y + (BOTTOM_HEIGHT + headLerp), player.position.y + (BOTTOM_HEIGHT + headLerp),
player.position.z, player.position.z,
}; };
if (player.isGrounded && (forward != 0 || sideway != 0)) { UpdateCameraAngle(&camera); // Update camera parameters
headTimer += delta * 3.f;
walkLerp = Lerp(walkLerp, 1.f, 10.f * delta); DisableCursor(); // Limit cursor to relative movement inside the window
camera.fovy = Lerp(camera.fovy, 55.f, 5.f * delta);
} SetTargetFPS(60); // Set our game to run at 60 frames-per-second
else { //--------------------------------------------------------------------------------------
walkLerp = Lerp(walkLerp, 0.f, 10.f * delta);
camera.fovy = Lerp(camera.fovy, 60.f, 5.f * delta); // Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
Vector2 mouse_delta = GetMouseDelta();
lookRotation.x -= mouse_delta.x*sensitivity.x;
lookRotation.y += mouse_delta.y*sensitivity.y;
char sideway = (IsKeyDown(KEY_D) - IsKeyDown(KEY_A));
char forward = (IsKeyDown(KEY_W) - IsKeyDown(KEY_S));
bool crouching = IsKeyDown(KEY_LEFT_CONTROL);
UpdateBody(&player, lookRotation.x, sideway, forward, IsKeyPressed(KEY_SPACE), crouching);
float delta = GetFrameTime();
headLerp = Lerp(headLerp, (crouching ? CROUCH_HEIGHT : STAND_HEIGHT), 20.0f*delta);
camera.position = (Vector3){
player.position.x,
player.position.y + (BOTTOM_HEIGHT + headLerp),
player.position.z,
};
if (player.isGrounded && ((forward != 0) || (sideway != 0)))
{
headTimer += delta*3.0f;
walkLerp = Lerp(walkLerp, 1.0f, 10.0f*delta);
camera.fovy = Lerp(camera.fovy, 55.0f, 5.0f*delta);
}
else
{
walkLerp = Lerp(walkLerp, 0.0f, 10.0f*delta);
camera.fovy = Lerp(camera.fovy, 60.0f, 5.0f*delta);
}
lean.x = Lerp(lean.x, sideway*0.02f, 10.0f*delta);
lean.y = Lerp(lean.y, forward*0.015f, 10.0f*delta);
UpdateCameraAngle(&camera);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
DrawLevel();
EndMode3D();
// Draw info box
DrawRectangle(5, 5, 330, 75, Fade(SKYBLUE, 0.5f));
DrawRectangleLines(5, 5, 330, 75, BLUE);
DrawText("Camera controls:", 15, 15, 10, BLACK);
DrawText("- Move keys: W, A, S, D, Space, Left-Ctrl", 15, 30, 10, BLACK);
DrawText("- Look around: arrow keys or mouse", 15, 45, 10, BLACK);
DrawText(TextFormat("- Velocity Len: (%06.3f)", Vector2Length((Vector2){ player.velocity.x, player.velocity.z })), 15, 60, 10, BLACK);
EndDrawing();
//----------------------------------------------------------------------------------
} }
lean.x = Lerp(lean.x, sideway * 0.02f, 10.f * delta); // De-Initialization
lean.y = Lerp(lean.y, forward * 0.015f, 10.f * delta); //--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
UpdateCameraAngle(); return 0;
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
DrawLevel();
EndMode3D();
// Draw info box
DrawRectangle(5, 5, 330, 100, Fade(SKYBLUE, 0.5f));
DrawRectangleLines(5, 5, 330, 100, BLUE);
DrawText("Camera controls:", 15, 15, 10, BLACK);
DrawText("- Move keys: W, A, S, D, Space, Left-Ctrl", 15, 30, 10, BLACK);
DrawText("- Look around: arrow keys or mouse", 15, 45, 10, BLACK);
DrawText(TextFormat("- Velocity Len: (%06.3f)", Vector2Length((Vector2) { player.velocity.x, player.velocity.z })), 15, 60, 10, BLACK);
EndDrawing();
//----------------------------------------------------------------------------------
} }
//----------------------------------------------------------------------------------
// Module functions definition
//----------------------------------------------------------------------------------
void UpdateBody(Body* body, float rot, char side, char forward, bool jumpPressed, bool crouchHold) void UpdateBody(Body* body, float rot, char side, char forward, bool jumpPressed, bool crouchHold)
{ {
Vector2 input = (Vector2){ (float)side, (float)-forward }; Vector2 input = (Vector2){ (float)side, (float)-forward };
#if defined(NORMALIZE_INPUT) #if defined(NORMALIZE_INPUT)
// Slow down diagonal movement // Slow down diagonal movement
if (side != 0 & forward != 0) if ((side != 0) && (forward != 0)) input = Vector2Normalize(input);
{
input = Vector2Normalize(input);
}
#endif #endif
float delta = GetFrameTime(); float delta = GetFrameTime();
if (!body->isGrounded) if (!body->isGrounded) body->velocity.y -= GRAVITY*delta;
{
body->velocity.y -= GRAVITY * delta;
}
if (body->isGrounded && jumpPressed) if (body->isGrounded && jumpPressed)
{ {
body->velocity.y = JUMP_FORCE; body->velocity.y = JUMP_FORCE;
body->isGrounded = false; body->isGrounded = false;
SetSoundPitch(body->soundJump, 1.f + (GetRandomValue(-100, 100) * 0.001));
PlaySound(body->soundJump); // Sound can be played at this moment
//SetSoundPitch(fxJump, 1.0f + (GetRandomValue(-100, 100)*0.001));
//PlaySound(fxJump);
} }
Vector3 front_vec = (Vector3){ sin(rot), 0.f, cos(rot) }; Vector3 front = (Vector3){ sin(rot), 0.f, cos(rot) };
Vector3 right_vec = (Vector3){ cos(-rot), 0.f, sin(-rot) }; Vector3 right = (Vector3){ cos(-rot), 0.f, sin(-rot) };
Vector3 desired_dir = (Vector3){ Vector3 desiredDir = (Vector3){ input.x*right.x + input.y*front.x, 0.0f, input.x*right.z + input.y*front.z, };
input.x * right_vec.x + input.y * front_vec.x, body->dir = Vector3Lerp(body->dir, desiredDir, CONTROL*delta);
0.f,
input.x * right_vec.z + input.y * front_vec.z,
};
body->dir = Vector3Lerp(body->dir, desired_dir, CONTROL * delta); float decel = (body->isGrounded ? FRICTION : AIR_DRAG);
Vector3 hvel = (Vector3){ body->velocity.x*decel, 0.0f, body->velocity.z*decel };
float decel = body->isGrounded ? FRICTION : AIR_DRAG; float hvelLength = Vector3Length(hvel); // Magnitude
Vector3 hvel = (Vector3){ if (hvelLength < (MAX_SPEED*0.01f)) hvel = (Vector3){ 0 };
body->velocity.x * decel,
0.f,
body->velocity.z * decel
};
float hvel_length = Vector3Length(hvel); // a.k.a. magnitude // This is what creates strafing
if (hvel_length < MAX_SPEED * 0.01f) {
hvel = (Vector3){ 0 };
}
/* This is what creates strafing */
float speed = Vector3DotProduct(hvel, body->dir); float speed = Vector3DotProduct(hvel, body->dir);
/* // Whenever the amount of acceleration to add is clamped by the maximum acceleration constant,
Whenever the amount of acceleration to add is clamped by the maximum acceleration constant, // a Player can make the speed faster by bringing the direction closer to horizontal velocity angle
a Player can make the speed faster by bringing the direction closer to horizontal velocity angle // More info here: https://youtu.be/v3zT3Z5apaM?t=165
More info here: https://youtu.be/v3zT3Z5apaM?t=165 float maxSpeed = (crouchHold? CROUCH_SPEED : MAX_SPEED);
*/ float accel = Clamp(maxSpeed - speed, 0.f, MAX_ACCEL*delta);
float max_speed = crouchHold ? CROUCH_SPEED : MAX_SPEED; hvel.x += body->dir.x*accel;
float accel = Clamp(max_speed - speed, 0.f, MAX_ACCEL * delta); hvel.z += body->dir.z*accel;
hvel.x += body->dir.x * accel;
hvel.z += body->dir.z * accel;
body->velocity.x = hvel.x; body->velocity.x = hvel.x;
body->velocity.z = hvel.z; body->velocity.z = hvel.z;
body->position.x += body->velocity.x * delta; body->position.x += body->velocity.x*delta;
body->position.y += body->velocity.y * delta; body->position.y += body->velocity.y*delta;
body->position.z += body->velocity.z * delta; body->position.z += body->velocity.z*delta;
/* Fancy collision system against "THE FLOOR" */ // Fancy collision system against the floor
if (body->position.y <= 0.f) if (body->position.y <= 0.0f)
{ {
body->position.y = 0.f; body->position.y = 0.0f;
body->velocity.y = 0.f; body->velocity.y = 0.0f;
body->isGrounded = true; // <= enables jumping body->isGrounded = true; // Enable jumping
} }
} }
void UpdateCameraAngle() // Update camera
static void UpdateCameraAngle(Camera *camera)
{ {
const Vector3 up = (Vector3){ 0.f, 1.f, 0.f }; const Vector3 up = (Vector3){ 0.0f, 1.0f, 0.0f };
const Vector3 targetOffset = (Vector3){ 0.f, 0.f, -1.f }; const Vector3 targetOffset = (Vector3){ 0.0f, 0.0f, -1.0f };
/* Left & Right */ // Left and right
Vector3 yaw = Vector3RotateByAxisAngle(targetOffset, up, lookRotation.x); Vector3 yaw = Vector3RotateByAxisAngle(targetOffset, up, lookRotation.x);
// Clamp view up // Clamp view up
float maxAngleUp = Vector3Angle(up, yaw); float maxAngleUp = Vector3Angle(up, yaw);
maxAngleUp -= 0.001f; // avoid numerical errors maxAngleUp -= 0.001f; // Avoid numerical errors
if ( -(lookRotation.y) > maxAngleUp) { lookRotation.y = -maxAngleUp; } if ( -(lookRotation.y) > maxAngleUp) { lookRotation.y = -maxAngleUp; }
// Clamp view down // Clamp view down
float maxAngleDown = Vector3Angle(Vector3Negate(up), yaw); float maxAngleDown = Vector3Angle(Vector3Negate(up), yaw);
maxAngleDown *= -1.0f; // downwards angle is negative maxAngleDown *= -1.0f; // Downwards angle is negative
maxAngleDown += 0.001f; // avoid numerical errors maxAngleDown += 0.001f; // Avoid numerical errors
if ( -(lookRotation.y) < maxAngleDown) { lookRotation.y = -maxAngleDown; } if ( -(lookRotation.y) < maxAngleDown) { lookRotation.y = -maxAngleDown; }
/* Up & Down */ // Up and down
Vector3 right = Vector3Normalize(Vector3CrossProduct(yaw, up)); Vector3 right = Vector3Normalize(Vector3CrossProduct(yaw, up));
// Rotate view vector around right axis // Rotate view vector around right axis
@ -297,27 +265,28 @@ void UpdateCameraAngle()
// Head animation // Head animation
// Rotate up direction around forward axis // Rotate up direction around forward axis
float _sin = sin(headTimer * PI); float headSin = sin(headTimer*PI);
float _cos = cos(headTimer * PI); float headCos = cos(headTimer*PI);
const float stepRotation = 0.01f; const float stepRotation = 0.01f;
camera.up = Vector3RotateByAxisAngle(up, pitch, _sin * stepRotation + lean.x); camera->up = Vector3RotateByAxisAngle(up, pitch, headSin*stepRotation + lean.x);
/* BOB */ // Camera BOB
const float bobSide = 0.1f; const float bobSide = 0.1f;
const float bobUp = 0.15f; const float bobUp = 0.15f;
Vector3 bobbing = Vector3Scale(right, _sin * bobSide); Vector3 bobbing = Vector3Scale(right, headSin*bobSide);
bobbing.y = fabsf(_cos * bobUp); bobbing.y = fabsf(headCos*bobUp);
camera.position = Vector3Add(camera.position, Vector3Scale(bobbing, walkLerp));
camera.target = Vector3Add(camera.position, pitch); camera->position = Vector3Add(camera->position, Vector3Scale(bobbing, walkLerp));
camera->target = Vector3Add(camera->position, pitch);
} }
// Draw game level
void DrawLevel() static void DrawLevel(void)
{ {
const int floorExtent = 25; const int floorExtent = 25;
const float tileSize = 5.f; const float tileSize = 5.0f;
const Color tileColor1 = (Color){ 150, 200, 200, 255 }; const Color tileColor1 = (Color){ 150, 200, 200, 255 };
// Floor tiles // Floor tiles
for (int y = -floorExtent; y < floorExtent; y++) for (int y = -floorExtent; y < floorExtent; y++)
{ {
@ -325,21 +294,19 @@ void DrawLevel()
{ {
if ((y & 1) && (x & 1)) if ((y & 1) && (x & 1))
{ {
DrawPlane((Vector3) { x * tileSize, 0.f, y * tileSize}, DrawPlane((Vector3){ x*tileSize, 0.0f, y*tileSize}, (Vector2){ tileSize, tileSize }, tileColor1);
(Vector2) {tileSize, tileSize}, tileColor1);
} }
else if(!(y & 1) && !(x & 1)) else if (!(y & 1) && !(x & 1))
{ {
DrawPlane((Vector3) { x * tileSize, 0.f, y * tileSize}, DrawPlane((Vector3){ x*tileSize, 0.0f, y*tileSize}, (Vector2){ tileSize, tileSize }, LIGHTGRAY);
(Vector2) {tileSize, tileSize}, LIGHTGRAY);
} }
} }
} }
const Vector3 towerSize = (Vector3){ 16.f, 32.f, 16.f }; const Vector3 towerSize = (Vector3){ 16.0f, 32.0f, 16.0f };
const Color towerColor = (Color){ 150, 200, 200, 255 }; const Color towerColor = (Color){ 150, 200, 200, 255 };
Vector3 towerPos = (Vector3){ 16.f, 16.f, 16.f }; Vector3 towerPos = (Vector3){ 16.0f, 16.0f, 16.0f };
DrawCubeV(towerPos, towerSize, towerColor); DrawCubeV(towerPos, towerSize, towerColor);
DrawCubeWiresV(towerPos, towerSize, DARKBLUE); DrawCubeWiresV(towerPos, towerSize, DARKBLUE);
@ -356,5 +323,5 @@ void DrawLevel()
DrawCubeWiresV(towerPos, towerSize, DARKBLUE); DrawCubeWiresV(towerPos, towerSize, DARKBLUE);
// Red sun // Red sun
DrawSphere((Vector3) { 300.f, 300.f, 0.f }, 100.f, (Color) { 255, 0, 0, 255 }); DrawSphere((Vector3){ 300.0f, 300.0f, 0.0f }, 100.0f, (Color){ 255, 0, 0, 255 });
} }

Binary file not shown.

View File

@ -51,7 +51,7 @@
</ProjectConfiguration> </ProjectConfiguration>
</ItemGroup> </ItemGroup>
<PropertyGroup Label="Globals"> <PropertyGroup Label="Globals">
<ProjectGuid>{0981CA98-E4A5-4DF1-987F-A41D09131EFC}</ProjectGuid> <ProjectGuid>{6B1A933E-71B8-4C1F-9E79-02D98830E671}</ProjectGuid>
<Keyword>Win32Proj</Keyword> <Keyword>Win32Proj</Keyword>
<RootNamespace>shaders_normalmap</RootNamespace> <RootNamespace>shaders_normalmap</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>

View File

@ -335,6 +335,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_input_virtual_controls
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_3d_fps_controller", "examples\core_3d_fps_controller.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_3d_fps_controller", "examples\core_3d_fps_controller.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shaders_normalmap", "examples\shaders_normalmap.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug.DLL|ARM64 = Debug.DLL|ARM64 Debug.DLL|ARM64 = Debug.DLL|ARM64
@ -4107,6 +4109,30 @@ Global
{6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64 {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64
{6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32 {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32
{6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32 {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32
{6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64
{6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64
{6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64
{6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.Build.0 = Debug.DLL|x64
{6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
{6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32
{6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.ActiveCfg = Debug|ARM64
{6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.Build.0 = Debug|ARM64
{6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.ActiveCfg = Debug|x64
{6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.Build.0 = Debug|x64
{6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.ActiveCfg = Debug|Win32
{6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.Build.0 = Debug|Win32
{6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64
{6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64
{6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.ActiveCfg = Release.DLL|x64
{6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.Build.0 = Release.DLL|x64
{6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32
{6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.Build.0 = Release.DLL|Win32
{6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.ActiveCfg = Release|ARM64
{6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.Build.0 = Release|ARM64
{6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.ActiveCfg = Release|x64
{6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64
{6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32
{6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -4276,6 +4302,7 @@ Global
{9CD8BCAD-F212-4BCC-BA98-899743CE3279} = {CC132A4D-D081-4C26-BFB9-AB11984054F8} {9CD8BCAD-F212-4BCC-BA98-899743CE3279} = {CC132A4D-D081-4C26-BFB9-AB11984054F8}
{0981CA28-E4A5-4DF1-987F-A41D09131EFC} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} {0981CA28-E4A5-4DF1-987F-A41D09131EFC} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
{6B1A933E-71B8-4C1F-9E79-02D98830E671} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
{6B1A933E-71B8-4C1F-9E79-02D98830E671} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29} SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29}

View File

@ -74,14 +74,27 @@
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__)
#include <sys/time.h> // Required for: timespec, nanosleep(), select() - POSIX #include <sys/time.h> // Required for: timespec, nanosleep(), select() - POSIX
//#define GLFW_EXPOSE_NATIVE_WAYLAND #if defined(_GLFW_X11) || defined(_GLFW_WAYLAND)
#define GLFW_EXPOSE_NATIVE_X11 // Set appropriate expose macros based on available backends
#define Font X11Font // Hack to fix 'Font' name collision #if defined(_GLFW_X11)
#define GLFW_EXPOSE_NATIVE_X11
#define Font X11Font // Hack to fix 'Font' name collision
// The definition and references to the X11 Font type will be replaced by 'X11Font' // The definition and references to the X11 Font type will be replaced by 'X11Font'
// Works as long as the current file consistently references any X11 Font as X11Font // Works as long as the current file consistently references any X11 Font as X11Font
// Since it is never referenced (as of writting), this does not pose an issue // Since it is never referenced (as of writting), this does not pose an issue
#include "GLFW/glfw3native.h" // Required for: glfwGetX11Window() #endif
#undef Font // Revert hack and allow normal raylib Font usage
#if defined(_GLFW_WAYLAND)
#define GLFW_EXPOSE_NATIVE_WAYLAND
#endif
#include "GLFW/glfw3native.h" // Include native header only once, regardless of how many backends are defined
// Required for: glfwGetX11Window() and glfwGetWaylandWindow()
#if defined(_GLFW_X11) // Clean up X11-specific hacks
#undef Font // Revert hack and allow normal raylib Font usage
#endif
#endif
#endif #endif
#if defined(__APPLE__) #if defined(__APPLE__)
#include <unistd.h> // Required for: usleep() #include <unistd.h> // Required for: usleep()
@ -710,7 +723,7 @@ void SetWindowFocused(void)
glfwFocusWindow(platform.handle); glfwFocusWindow(platform.handle);
} }
#if defined(__linux__) #if defined(__linux__) && defined(_GLFW_X11)
// Local storage for the window handle returned by glfwGetX11Window // Local storage for the window handle returned by glfwGetX11Window
// This is needed as X11 handles are integers and may not fit inside a pointer depending on platform // This is needed as X11 handles are integers and may not fit inside a pointer depending on platform
// Storing the handle locally and returning a pointer in GetWindowHandle allows the code to work regardless of pointer width // Storing the handle locally and returning a pointer in GetWindowHandle allows the code to work regardless of pointer width
@ -724,10 +737,27 @@ void *GetWindowHandle(void)
return glfwGetWin32Window(platform.handle); return glfwGetWin32Window(platform.handle);
#endif #endif
#if defined(__linux__) #if defined(__linux__)
// Store the window handle localy and return a pointer to the variable instead #if defined(_GLFW_WAYLAND)
// Reasoning detailed in the declaration of X11WindowHandle #if defined(_GLFW_X11)
X11WindowHandle = glfwGetX11Window(platform.handle); int platformID = glfwGetPlatform();
return &X11WindowHandle; if (platformID == GLFW_PLATFORM_WAYLAND)
{
return glfwGetWaylandWindow(platform.handle);
}
else
{
X11WindowHandle = glfwGetX11Window(platform.handle);
return &X11WindowHandle;
}
#else
return glfwGetWaylandWindow(platform.handle);
#endif
#elif defined(_GLFW_X11)
// Store the window handle localy and return a pointer to the variable instead
// Reasoning detailed in the declaration of X11WindowHandle
X11WindowHandle = glfwGetX11Window(platform.handle);
return &X11WindowHandle;
#endif
#endif #endif
#if defined(__APPLE__) #if defined(__APPLE__)
// NOTE: Returned handle is: (objc_object *) // NOTE: Returned handle is: (objc_object *)

View File

@ -35,6 +35,7 @@ Example elements validated:
| core_3d_camera_free | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | core_3d_camera_free | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| core_3d_camera_first_person | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | core_3d_camera_first_person | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| core_3d_camera_split_screen | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | core_3d_camera_split_screen | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| core_3d_fps_controller | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| core_3d_picking | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | core_3d_picking | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| core_world_screen | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | core_world_screen | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| core_custom_logging | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | core_custom_logging | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
@ -54,7 +55,7 @@ Example elements validated:
| core_basic_window_web | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ❌ | | core_basic_window_web | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ❌ |
| core_input_gestures_web | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | | core_input_gestures_web | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ |
| core_automation_events | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | core_automation_events | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| core_high_dpi | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | | core_high_dpi | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | |
| shapes_basic_shapes | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_basic_shapes | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shapes_bouncing_ball | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_bouncing_ball | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shapes_colors_palette | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_colors_palette | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
@ -73,8 +74,8 @@ Example elements validated:
| shapes_top_down_lights | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_top_down_lights | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shapes_rectangle_advanced | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_rectangle_advanced | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shapes_splines_drawing | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_splines_drawing | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shapes_digital_clock | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | | shapes_digital_clock | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | |
| shapes_double_pendulum | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | | shapes_double_pendulum | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | |
| textures_logo_raylib | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | textures_logo_raylib | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| textures_srcrec_dstrec | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | textures_srcrec_dstrec | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| textures_image_drawing | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | textures_image_drawing | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
@ -91,7 +92,7 @@ Example elements validated:
| textures_sprite_button | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | textures_sprite_button | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| textures_sprite_explosion | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | textures_sprite_explosion | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| textures_bunnymark | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | textures_bunnymark | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| textures_mouse_painting | ✔ | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | | textures_mouse_painting | ✔ | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | |
| textures_blend_modes | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | textures_blend_modes | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| textures_draw_tiled | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | textures_draw_tiled | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| textures_polygon | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | textures_polygon | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
@ -153,7 +154,7 @@ Example elements validated:
| shaders_hot_reloading | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shaders_hot_reloading | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shaders_mesh_instancing | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shaders_mesh_instancing | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shaders_multi_sample2d | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shaders_multi_sample2d | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shaders_normalmap | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | ✔ | ✔ | | | shaders_normalmap | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | ✔ | ✔ | |
| shaders_spotlight | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shaders_spotlight | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shaders_deferred_render | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shaders_deferred_render | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shaders_hybrid_render | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shaders_hybrid_render | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
@ -163,8 +164,8 @@ Example elements validated:
| shaders_write_depth | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shaders_write_depth | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shaders_basic_pbr | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shaders_basic_pbr | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shaders_lightmap | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shaders_lightmap | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shaders_rounded_rectangle | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | | shaders_rounded_rectangle | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | |
| shaders_view_depth | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | | shaders_view_depth | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | |
| audio_module_playing | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | audio_module_playing | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| audio_music_stream | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | audio_music_stream | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| audio_raw_stream | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | audio_raw_stream | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
@ -172,10 +173,10 @@ Example elements validated:
| audio_mixed_processor | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | audio_mixed_processor | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| audio_stream_effects | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | audio_stream_effects | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| audio_sound_multi | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | audio_sound_multi | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| audio_sound_positioning | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | | audio_sound_positioning | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | |
| rlgl_standalone | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | | ✔ | ✔ | ✔ | | ❌ | | rlgl_standalone | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | | ✔ | ✔ | ✔ | | ❌ |
| rlgl_compute_shader | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | | ✔ | ✔ | ✔ | | ❌ | | rlgl_compute_shader | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | | ✔ | ✔ | ✔ | | ❌ |
| easings_testbed | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | | ✔ | ✔ | ✔ | | ❌ | | easings_testbed | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | | ✔ | ✔ | ✔ | | ❌ |
| raylib_opengl_interop | ✔ | ❌ | ❌ | ✔ | ✔ | ❌ | ✔ | | ✔ | ❌ | ✔ | | ❌ | | raylib_opengl_interop | ✔ | ❌ | ❌ | ✔ | ✔ | ❌ | ✔ | | ✔ | ❌ | ✔ | | ❌ |
| embedded_files_loading | ✔ | ❌ | ❌ | ✔ | ✔ | ❌ | ✔ | | ✔ | ✔ | ✔ | | ❌ | | embedded_files_loading | ✔ | ❌ | ❌ | ✔ | ✔ | ❌ | ✔ | | ✔ | ✔ | ✔ | | ❌ |
| raymath_vector_angle | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | | ✔ | ❌ | ✔ | | ❌ | | raymath_vector_angle | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | | ✔ | ❌ | ✔ | | ❌ |

View File

@ -749,6 +749,53 @@ int main(int argc, char *argv[])
// TODO: Log more details about the validation process // TODO: Log more details about the validation process
// Scan available example .c files and add to collection missing ones
// NOTE: Source of truth is what we have in the examples directories (on validation/update)
FilePathList list = LoadDirectoryFilesEx(exBasePath, ".c", true);
const char *exList = LoadFileText(exCollectionFilePath);
char *exListUpdated = (char *)RL_CALLOC(REXM_MAX_BUFFER_SIZE, 1);
bool listUpdated = false;
int exListLen = strlen(exList);
strcpy(exListUpdated, exList);
for (int i = 0; i < list.count; i++)
{
if ((strcmp("examples_template", GetFileNameWithoutExt(list.paths[i])) != 0) && // HACK: Skip "examples_template"
(TextFindIndex(exList, GetFileNameWithoutExt(list.paths[i])) == -1))
{
// Add example to the examples collection list
// WARNING: Added to the end of the list, order must be set by users and
// defines placement on raylib webpage
rlExampleInfo *exInfo = LoadExampleInfo(list.paths[i]);
// Get example difficulty stars
char starsText[16] = { 0 };
for (int i = 0; i < 4; i++)
{
// NOTE: Every UTF-8 star are 3 bytes
if (i < exInfo->stars) strcpy(starsText + 3*i, "⭐️");
else strcpy(starsText + 3*i, "");
}
exListLen += sprintf(exListUpdated + exListLen,
TextFormat("%s;%s;%s;%.1f;%.1f;\"%s\";@%s\n",
exInfo->category, exInfo->name, starsText, exInfo->verCreated,
exInfo->verUpdated, exInfo->author, exInfo->authorGitHub));
listUpdated = true;
UnloadExampleInfo(exInfo);
}
}
if (listUpdated) SaveFileText(exCollectionFilePath, exListUpdated);
UnloadFileText(exList);
RL_FREE(exListUpdated);
UnloadDirectoryFiles(list);
// Check all examples in collection [examples_list.txt] -> Source of truth! // Check all examples in collection [examples_list.txt] -> Source of truth!
int exCollectionCount = 0; int exCollectionCount = 0;
rlExampleInfo *exCollection = LoadExamplesData(exCollectionFilePath, "ALL", false, &exCollectionCount); rlExampleInfo *exCollection = LoadExamplesData(exCollectionFilePath, "ALL", false, &exCollectionCount);
@ -875,11 +922,18 @@ int main(int argc, char *argv[])
else else
{ {
// NOTE: Some issues can not be automatically fixed, only logged // NOTE: Some issues can not be automatically fixed, only logged
//if (exInfo->status & VALID_MISSING_PNG) LOG("WARNING: [%s] Missing screenshot file\n", exInfo->name); if (exInfo->status & VALID_MISSING_PNG) LOG("WARNING: [%s] Missing screenshot file\n", exInfo->name);
//if (exInfo->status & VALID_INVALID_PNG) LOG("WARNING: [%s] Invalid screenshot file (using template)\n", exInfo->name); if (exInfo->status & VALID_INVALID_PNG) LOG("WARNING: [%s] Invalid screenshot file (using template)\n", exInfo->name);
//if (exInfo->status & VALID_MISSING_RESOURCES) LOG("WARNING: [%s] Missing resources detected\n", exInfo->name); if (exInfo->status & VALID_MISSING_RESOURCES) LOG("WARNING: [%s] Missing resources detected\n", exInfo->name);
//if (exInfo->status & VALID_INCONSISTENT_INFO) LOG("WARNING: [%s] Inconsistent example header info\n", exInfo->name); if (exInfo->status & VALID_INCONSISTENT_INFO) LOG("WARNING: [%s] Inconsistent example header info\n", exInfo->name);
//if (exInfo->status & VALID_INVALID_CATEGORY) LOG("WARNING: [%s] Invalid example category\n", exInfo->name); if (exInfo->status & VALID_INVALID_CATEGORY) LOG("WARNING: [%s] Invalid example category\n", exInfo->name);
// NOTE: Some examples should be excluded from VS2022 solution because
// they have specific platform/linkage requirements:
if ((strcmp(exInfo->name, "core_basic_window_web") == 0) ||
(strcmp(exInfo->name, "core_input_gestures_web") == 0) ||
(strcmp(exInfo->name, "raylib_opengl_interop") == 0) ||
(strcmp(exInfo->name, "raymath_vector_angle") == 0)) continue;
// Review: Add: raylib/projects/VS2022/examples/<category>_example_name.vcxproj // Review: Add: raylib/projects/VS2022/examples/<category>_example_name.vcxproj
// Review: Add: raylib/projects/VS2022/raylib.sln // Review: Add: raylib/projects/VS2022/raylib.sln
@ -893,7 +947,7 @@ int main(int argc, char *argv[])
FileTextReplace(TextFormat("%s/../projects/VS2022/examples/%s.vcxproj", exBasePath, exInfo->name), FileTextReplace(TextFormat("%s/../projects/VS2022/examples/%s.vcxproj", exBasePath, exInfo->name),
"..\\..\\examples\\core", TextFormat("..\\..\\examples\\%s", exInfo->category)); "..\\..\\examples\\core", TextFormat("..\\..\\examples\\%s", exInfo->category));
exInfo->status |= VALID_MISSING_VCXPROJ; exInfo->status &= ~VALID_MISSING_VCXPROJ;
} }
// Add project (.vcxproj) to raylib solution (.sln) // Add project (.vcxproj) to raylib solution (.sln)
@ -902,7 +956,7 @@ int main(int argc, char *argv[])
AddVSProjectToSolution(TextFormat("%s/../projects/VS2022/examples/%s.vcxproj", exBasePath, exInfo->name), AddVSProjectToSolution(TextFormat("%s/../projects/VS2022/examples/%s.vcxproj", exBasePath, exInfo->name),
exVSProjectSolutionFile, exInfo->category); exVSProjectSolutionFile, exInfo->category);
exInfo->status |= VALID_NOT_IN_VCXSOL; exInfo->status &= ~VALID_NOT_IN_VCXSOL;
} }
// Review: Add/Remove: raylib.com/examples/<category>/<category>_example_name.html // Review: Add/Remove: raylib.com/examples/<category>/<category>_example_name.html
@ -910,7 +964,8 @@ int main(int argc, char *argv[])
// Review: Add/Remove: raylib.com/examples/<category>/<category>_example_name.wasm // Review: Add/Remove: raylib.com/examples/<category>/<category>_example_name.wasm
// Review: Add/Remove: raylib.com/examples/<category>/<category>_example_name.js // Review: Add/Remove: raylib.com/examples/<category>/<category>_example_name.js
// Solves: VALID_MISSING_WEB_OUTPUT // Solves: VALID_MISSING_WEB_OUTPUT
if (exInfo->status & VALID_MISSING_WEB_OUTPUT) if ((strcmp(exInfo->category, "others") != 0) && // Skipping "others" category
exInfo->status & VALID_MISSING_WEB_OUTPUT)
{ {
system(TextFormat("%s/build_example_web.bat %s/%s", exBasePath, exInfo->category, exInfo->name)); system(TextFormat("%s/build_example_web.bat %s/%s", exBasePath, exInfo->category, exInfo->name));
@ -924,7 +979,7 @@ int main(int argc, char *argv[])
FileCopy(TextFormat("%s/%s/%s.js", exBasePath, exInfo->category, exInfo->name), FileCopy(TextFormat("%s/%s/%s.js", exBasePath, exInfo->category, exInfo->name),
TextFormat("%s/%s/%s.js", exWebPath, exInfo->category, exInfo->name)); TextFormat("%s/%s/%s.js", exWebPath, exInfo->category, exInfo->name));
exInfo->status |= VALID_MISSING_WEB_OUTPUT; exInfo->status &= ~VALID_MISSING_WEB_OUTPUT;
} }
} }
} }
@ -934,10 +989,10 @@ int main(int argc, char *argv[])
UpdateRequiredFiles(); UpdateRequiredFiles();
for (int i = 0; i < exCollectionCount; i++) for (int i = 0; i < exCollectionCount; i++)
{ {
exCollection[i].status |= VALID_NOT_IN_MAKEFILE; exCollection[i].status &= ~VALID_NOT_IN_MAKEFILE;
exCollection[i].status |= VALID_NOT_IN_MAKEFILE_WEB; exCollection[i].status &= ~VALID_NOT_IN_MAKEFILE_WEB;
exCollection[i].status |= VALID_NOT_IN_README; exCollection[i].status &= ~VALID_NOT_IN_README;
exCollection[i].status |= VALID_NOT_IN_JS; exCollection[i].status &= ~VALID_NOT_IN_JS;
} }
//------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------
} }
@ -1566,12 +1621,13 @@ static void UnloadTextLines(char **lines)
RL_FREE(lines); RL_FREE(lines);
} }
// Get example info from file header // Get example info from example file header
// NOTE: Expecting the example to follow raylib_example_template.c
rlExampleInfo *LoadExampleInfo(const char *exFileName) rlExampleInfo *LoadExampleInfo(const char *exFileName)
{ {
rlExampleInfo *exInfo = (rlExampleInfo *)RL_CALLOC(1, sizeof(rlExampleInfo)); rlExampleInfo *exInfo = (rlExampleInfo *)RL_CALLOC(1, sizeof(rlExampleInfo));
if (IsFileExtension(exFileName, ".c")) if (FileExists(exFileName) && IsFileExtension(exFileName, ".c"))
{ {
strcpy(exInfo->name, GetFileNameWithoutExt(exFileName)); strcpy(exInfo->name, GetFileNameWithoutExt(exFileName));
strncpy(exInfo->category, exInfo->name, TextFindIndex(exInfo->name, "_")); strncpy(exInfo->category, exInfo->name, TextFindIndex(exInfo->name, "_"));
@ -1747,16 +1803,21 @@ static char **ScanExampleResources(const char *filePath, int *resPathCount)
strncpy(buffer, start, len); strncpy(buffer, start, len);
buffer[len] = '\0'; buffer[len] = '\0';
// TODO: Make sure buffer is a path (and not a Tracelog() text)
// Check for known extensions // Check for known extensions
for (int i = 0; i < extCount; i++) for (int i = 0; i < extCount; i++)
{ {
// TODO: WARNING: IsFileExtension() expects a NULL terminated fileName,
// but in this case buffer can contain any kind of string,
// including not paths strings, for example TraceLog() string
if (IsFileExtension(buffer, exts[i])) if (IsFileExtension(buffer, exts[i]))
{ {
// Avoid duplicates // Avoid duplicates
bool found = false; bool found = false;
for (int j = 0; j < resCounter; j++) for (int j = 0; j < resCounter; j++)
{ {
if (TextIsEqual(paths[j], buffer)) { found = true; break; } if (strcmp(paths[j], buffer) == 0) { found = true; break; }
} }
if (!found && (resCounter < REXM_MAX_RESOURCE_PATHS)) if (!found && (resCounter < REXM_MAX_RESOURCE_PATHS))