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;`
Constants | lowerCase | `const int maxValue = 8;`
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 division = value/4;`
Operators | value1 + value2 | `int sum = value + 10;`
@ -72,19 +72,19 @@ void SomeFunction()
**If proposing new functions, please try to use a clear naming for function-name and functions-parameters, in case of doubt, open an issue for discussion.**
## Files and Directories Naming Conventions
- Directories will be named using `snake_case`: `resources/models`, `resources/fonts`
- Files will be named using `snake_case`: `main_title.png`, `cubicmap.png`, `sound.wav`
_NOTE: Avoid any space or special character in the files/dir naming!_
## Games/Examples Directories Organization Conventions
- Data files should be organized by context and usage in the game, think about the loading requirements for data and put all the resources that need to be loaded at the same time together.
- Use descriptive names for the files, it would be perfect if just reading the name of the file, it was possible to know what is that file and where fits in the game.
- Here is an example, note that some resources require to be loaded all at once while other require to be loaded only at initialization (gui, font).
```
resources/audio/fx/long_jump.wav
resources/audio/music/main_theme.ogg

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)
core/core_3d_fps_controller: core/core_3d_fps_controller.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file core/resources/huh_jump.wav@resources/huh_jump.wav
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
core/core_3d_picking: core/core_3d_picking.c
$(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 [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.
@ -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_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_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_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) |

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 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)
*
@ -16,65 +16,60 @@
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
#include "rcamera.h"
#if defined(PLATFORM_WEB)
#include <emscripten/emscripten.h>
#endif
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
// 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 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
#define NORMALIZE_INPUT 0
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
// Body structure
typedef struct {
Vector3 position;
Vector3 velocity;
Vector3 dir;
bool isGrounded;
Sound soundJump;
}Body;
} Body;
const int screenWidth = 800;
const int screenHeight = 450;
Vector2 sensitivity = { 0.001f, 0.001f };
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
static Vector2 sensitivity = { 0.001f, 0.001f };
Body player;
Camera camera;
Vector2 lookRotation = { 0 };
float headTimer;
float walkLerp;
float headLerp;
Vector2 lean;
static Body player = { 0 };
static Vector2 lookRotation = { 0 };
static float headTimer = 0.0f;
static float walkLerp = 0.0f;
static float headLerp = STAND_HEIGHT;
static Vector2 lean = { 0 };
void UpdateDrawFrame(void); // Update and Draw one frame
void DrawLevel();
void UpdateCameraAngle();
void UpdateBody(Body* body, float rot, char side, char forward, bool jumpPressed, bool crouchHold);
//----------------------------------------------------------------------------------
// Module functions declaration
//----------------------------------------------------------------------------------
static void DrawLevel(void);
static void UpdateCameraAngle(Camera *camera);
static void UpdateBody(Body *body, float rot, char side, char forward, bool jumpPressed, bool crouchHold);
//------------------------------------------------------------------------------------
// Program main entry point
@ -83,213 +78,186 @@ int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
InitWindow(screenWidth, screenHeight, "Raylib Quake-like controller");
InitAudioDevice();
const int screenWidth = 800;
const int screenHeight = 450;
player = (Body){ Vector3Zero(), Vector3Zero(), Vector3Zero(), false, LoadSound("resources/huh_jump.wav")};
camera = (Camera){ 0 };
camera.fovy = 60.f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d first-person camera controller");
lookRotation = Vector2Zero();
headTimer = 0.f;
walkLerp = 0.f;
headLerp = STAND_HEIGHT;
lean = Vector2Zero();
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);
// Initialize camera variables
// NOTE: UpdateCameraAngle() takes care of the rest
Camera camera = { 0 };
camera.fovy = 60.0f;
camera.projection = CAMERA_PERSPECTIVE;
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.f;
walkLerp = Lerp(walkLerp, 1.f, 10.f * delta);
camera.fovy = Lerp(camera.fovy, 55.f, 5.f * delta);
}
else {
walkLerp = Lerp(walkLerp, 0.f, 10.f * delta);
camera.fovy = Lerp(camera.fovy, 60.f, 5.f * delta);
UpdateCameraAngle(&camera); // Update camera parameters
DisableCursor(); // Limit cursor to relative movement inside the window
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// 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);
lean.y = Lerp(lean.y, forward * 0.015f, 10.f * delta);
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
UpdateCameraAngle();
// 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();
//----------------------------------------------------------------------------------
return 0;
}
void UpdateBody(Body* body, float rot, char side, char forward, bool jumpPressed, bool crouchHold)
//----------------------------------------------------------------------------------
// Module functions definition
//----------------------------------------------------------------------------------
void UpdateBody(Body* body, float rot, char side, char forward, bool jumpPressed, bool crouchHold)
{
Vector2 input = (Vector2){ (float)side, (float)-forward };
#if defined(NORMALIZE_INPUT)
// Slow down diagonal movement
if (side != 0 & forward != 0)
{
input = Vector2Normalize(input);
}
if ((side != 0) && (forward != 0)) input = Vector2Normalize(input);
#endif
float delta = GetFrameTime();
if (!body->isGrounded)
{
body->velocity.y -= GRAVITY * delta;
}
if (body->isGrounded && jumpPressed)
if (!body->isGrounded) body->velocity.y -= GRAVITY*delta;
if (body->isGrounded && jumpPressed)
{
body->velocity.y = JUMP_FORCE;
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 right_vec = (Vector3){ cos(-rot), 0.f, sin(-rot) };
Vector3 front = (Vector3){ sin(rot), 0.f, cos(rot) };
Vector3 right = (Vector3){ cos(-rot), 0.f, sin(-rot) };
Vector3 desired_dir = (Vector3){
input.x * right_vec.x + input.y * front_vec.x,
0.f,
input.x * right_vec.z + input.y * front_vec.z,
};
Vector3 desiredDir = (Vector3){ input.x*right.x + input.y*front.x, 0.0f, input.x*right.z + input.y*front.z, };
body->dir = Vector3Lerp(body->dir, desiredDir, CONTROL*delta);
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;
Vector3 hvel = (Vector3){
body->velocity.x * decel,
0.f,
body->velocity.z * decel
};
float hvelLength = Vector3Length(hvel); // Magnitude
if (hvelLength < (MAX_SPEED*0.01f)) hvel = (Vector3){ 0 };
float hvel_length = Vector3Length(hvel); // a.k.a. magnitude
if (hvel_length < MAX_SPEED * 0.01f) {
hvel = (Vector3){ 0 };
}
/* This is what creates strafing */
// This is what creates strafing
float speed = Vector3DotProduct(hvel, body->dir);
/*
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
More info here: https://youtu.be/v3zT3Z5apaM?t=165
*/
float max_speed = crouchHold ? CROUCH_SPEED : MAX_SPEED;
float accel = Clamp(max_speed - speed, 0.f, MAX_ACCEL * delta);
hvel.x += body->dir.x * accel;
hvel.z += body->dir.z * accel;
// 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
// 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);
hvel.x += body->dir.x*accel;
hvel.z += body->dir.z*accel;
body->velocity.x = hvel.x;
body->velocity.z = hvel.z;
body->position.x += body->velocity.x * delta;
body->position.y += body->velocity.y * delta;
body->position.z += body->velocity.z * delta;
body->position.x += body->velocity.x*delta;
body->position.y += body->velocity.y*delta;
body->position.z += body->velocity.z*delta;
/* Fancy collision system against "THE FLOOR" */
if (body->position.y <= 0.f)
// Fancy collision system against the floor
if (body->position.y <= 0.0f)
{
body->position.y = 0.f;
body->velocity.y = 0.f;
body->isGrounded = true; // <= enables jumping
body->position.y = 0.0f;
body->velocity.y = 0.0f;
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 targetOffset = (Vector3){ 0.f, 0.f, -1.f };
const Vector3 up = (Vector3){ 0.0f, 1.0f, 0.0f };
const Vector3 targetOffset = (Vector3){ 0.0f, 0.0f, -1.0f };
/* Left & Right */
// Left and right
Vector3 yaw = Vector3RotateByAxisAngle(targetOffset, up, lookRotation.x);
// Clamp view up
float maxAngleUp = Vector3Angle(up, yaw);
maxAngleUp -= 0.001f; // avoid numerical errors
maxAngleUp -= 0.001f; // Avoid numerical errors
if ( -(lookRotation.y) > maxAngleUp) { lookRotation.y = -maxAngleUp; }
// Clamp view down
float maxAngleDown = Vector3Angle(Vector3Negate(up), yaw);
maxAngleDown *= -1.0f; // downwards angle is negative
maxAngleDown += 0.001f; // avoid numerical errors
maxAngleDown *= -1.0f; // Downwards angle is negative
maxAngleDown += 0.001f; // Avoid numerical errors
if ( -(lookRotation.y) < maxAngleDown) { lookRotation.y = -maxAngleDown; }
/* Up & Down */
// Up and down
Vector3 right = Vector3Normalize(Vector3CrossProduct(yaw, up));
// Rotate view vector around right axis
@ -297,49 +265,48 @@ void UpdateCameraAngle()
// Head animation
// Rotate up direction around forward axis
float _sin = sin(headTimer * PI);
float _cos = cos(headTimer * PI);
float headSin = sin(headTimer*PI);
float headCos = cos(headTimer*PI);
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 bobUp = 0.15f;
Vector3 bobbing = Vector3Scale(right, _sin * bobSide);
bobbing.y = fabsf(_cos * bobUp);
camera.position = Vector3Add(camera.position, Vector3Scale(bobbing, walkLerp));
Vector3 bobbing = Vector3Scale(right, headSin*bobSide);
bobbing.y = fabsf(headCos*bobUp);
camera.target = Vector3Add(camera.position, pitch);
camera->position = Vector3Add(camera->position, Vector3Scale(bobbing, walkLerp));
camera->target = Vector3Add(camera->position, pitch);
}
void DrawLevel()
// Draw game level
static void DrawLevel(void)
{
const int floorExtent = 25;
const float tileSize = 5.f;
const float tileSize = 5.0f;
const Color tileColor1 = (Color){ 150, 200, 200, 255 };
// Floor tiles
for (int y = -floorExtent; y < floorExtent; y++)
for (int y = -floorExtent; y < floorExtent; y++)
{
for (int x = -floorExtent; x < floorExtent; x++)
for (int x = -floorExtent; x < floorExtent; x++)
{
if ((y & 1) && (x & 1))
if ((y & 1) && (x & 1))
{
DrawPlane((Vector3) { x * tileSize, 0.f, y * tileSize},
(Vector2) {tileSize, tileSize}, tileColor1);
DrawPlane((Vector3){ x*tileSize, 0.0f, y*tileSize}, (Vector2){ tileSize, tileSize }, tileColor1);
}
else if(!(y & 1) && !(x & 1))
else if (!(y & 1) && !(x & 1))
{
DrawPlane((Vector3) { x * tileSize, 0.f, y * tileSize},
(Vector2) {tileSize, tileSize}, LIGHTGRAY);
DrawPlane((Vector3){ x*tileSize, 0.0f, y*tileSize}, (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 };
Vector3 towerPos = (Vector3){ 16.f, 16.f, 16.f };
Vector3 towerPos = (Vector3){ 16.0f, 16.0f, 16.0f };
DrawCubeV(towerPos, towerSize, towerColor);
DrawCubeWiresV(towerPos, towerSize, DARKBLUE);
@ -356,5 +323,5 @@ void DrawLevel()
DrawCubeWiresV(towerPos, towerSize, DARKBLUE);
// 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

@ -3,7 +3,7 @@
# examples must be provided as: <example_category>;<example_name>;<example_stars>;<raylib_created_version>;<raylib_last_update_version>;"<example_author_name>";<author_github_user>
#
# This list is used as the main reference by [rexm] tool for examples collection validation and management
# New examples must be added to this list and any possible rename must be made on this list first
# New examples must be added to this list and any possible rename must be made on this list first
#
# WARNING: List is not ordered by example name but by the display order on web
#

View File

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

View File

@ -335,6 +335,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_input_virtual_controls
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_3d_fps_controller", "examples\core_3d_fps_controller.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shaders_normalmap", "examples\shaders_normalmap.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
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|x86.ActiveCfg = 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
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -4276,6 +4302,7 @@ Global
{9CD8BCAD-F212-4BCC-BA98-899743CE3279} = {CC132A4D-D081-4C26-BFB9-AB11984054F8}
{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} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29}

View File

@ -74,14 +74,27 @@
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__)
#include <sys/time.h> // Required for: timespec, nanosleep(), select() - POSIX
//#define GLFW_EXPOSE_NATIVE_WAYLAND
#define GLFW_EXPOSE_NATIVE_X11
#define Font X11Font // Hack to fix 'Font' name collision
#if defined(_GLFW_X11) || defined(_GLFW_WAYLAND)
// Set appropriate expose macros based on available backends
#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'
// 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
#include "GLFW/glfw3native.h" // Required for: glfwGetX11Window()
#undef Font // Revert hack and allow normal raylib Font usage
#endif
#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
#if defined(__APPLE__)
#include <unistd.h> // Required for: usleep()
@ -710,7 +723,7 @@ void SetWindowFocused(void)
glfwFocusWindow(platform.handle);
}
#if defined(__linux__)
#if defined(__linux__) && defined(_GLFW_X11)
// 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
// 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);
#endif
#if defined(__linux__)
// 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;
#if defined(_GLFW_WAYLAND)
#if defined(_GLFW_X11)
int platformID = glfwGetPlatform();
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
#if defined(__APPLE__)
// NOTE: Returned handle is: (objc_object *)
@ -1365,7 +1395,7 @@ int InitPlatform(void)
// Window flags requested before initialization to be applied after initialization
unsigned int requestedWindowFlags = CORE.Window.flags;
// Check window creation flags
if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) CORE.Window.fullscreen = true;
@ -1663,7 +1693,7 @@ int InitPlatform(void)
int monitorHeight = 0;
glfwGetMonitorWorkarea(monitor, &monitorX, &monitorY, &monitorWidth, &monitorHeight);
// Here CORE.Window.render.width/height should be used instead of
// Here CORE.Window.render.width/height should be used instead of
// CORE.Window.screen.width/height to center the window correctly when the high dpi flag is enabled
int posX = monitorX + (monitorWidth - (int)CORE.Window.render.width)/2;
int posY = monitorY + (monitorHeight - (int)CORE.Window.render.height)/2;
@ -1675,7 +1705,7 @@ int InitPlatform(void)
CORE.Window.position.x = posX;
CORE.Window.position.y = posY;
}
// Apply window flags requested previous to initialization
SetWindowState(requestedWindowFlags);

View File

@ -1103,7 +1103,7 @@ Vector2 GetWindowScaleDPI(void)
TRACELOG(LOG_WARNING, "GetWindowScaleDPI() not implemented on target platform");
#else
scale.x = SDL_GetWindowDisplayScale(platform.window);
scale.y = scale.x;
scale.y = scale.x;
#endif
return scale;

View File

@ -1355,7 +1355,7 @@ int InitPlatform(void)
emscripten_set_blur_callback(GetCanvasId(), platform.handle, 1, EmscriptenFocusCallback);
emscripten_set_focus_callback(GetCanvasId(), platform.handle, 1, EmscriptenFocusCallback);
emscripten_set_visibilitychange_callback(NULL, 1, EmscriptenVisibilityChangeCallback);
// WARNING: Below resize code was breaking fullscreen mode for sample games and examples, it needs review
// Check fullscreen change events(note this is done on the window since most browsers don't support this on #canvas)
// emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, 1, EmscriptenResizeCallback);
@ -1623,7 +1623,7 @@ static void MouseEnterCallback(GLFWwindow *window, int enter)
static EM_BOOL EmscriptenKeyboardCallback(int eventType, const EmscriptenKeyboardEvent *keyboardEvent, void *userData)
{
// WARNING: Keyboard inputs already processed through GLFW callback
return 1; // The event was consumed by the callback handler
}
*/

View File

@ -1963,25 +1963,25 @@ bool IsFileExtension(const char *fileName, const char *ext)
if ((fileExt[i] >= 'A') && (fileExt[i] <= 'Z')) fileExtLower[i] = fileExt[i] + 32;
else fileExtLower[i] = fileExt[i];
}
int extCount = 1;
int extLen = (int)strlen(ext);
char *extList = (char *)RL_CALLOC(extLen + 1, 1);
char *extListPtrs[MAX_FILE_EXTENSIONS] = { 0 };
strcpy(extList, ext);
extListPtrs[0] = extList;
for (int i = 0; i < extLen; i++)
for (int i = 0; i < extLen; i++)
{
// Convert to lower-case if extension is upper-case
if ((extList[i] >= 'A') && (extList[i] <= 'Z')) extList[i] += 32;
// Get pointer to next extension and add null-terminator
if ((extList[i] == ';') && (extCount < (MAX_FILE_EXTENSIONS - 1)))
{
extList[i] = '\0';
extList[i] = '\0';
extListPtrs[extCount] = extList + i + 1;
extCount++;
extCount++;
}
}
@ -1991,7 +1991,7 @@ bool IsFileExtension(const char *fileName, const char *ext)
// does not start with the '.'
fileExtLowerPtr = fileExtLower;
if (extListPtrs[i][0] != '.') fileExtLowerPtr++;
if (strcmp(fileExtLowerPtr, extListPtrs[i]) == 0)
{
result = true;
@ -2053,7 +2053,7 @@ int GetFileLength(const char *fileName)
// WARNING: We just get the ptr but not the extension as a separate string
const char *GetFileExtension(const char *fileName)
{
const char *dot = strrchr(fileName, '.');
const char *dot = strrchr(fileName, '.');
if (!dot || (dot == fileName)) return NULL;

View File

@ -2573,7 +2573,7 @@ void rlLoadExtensions(void *loader)
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
RLGL.loader = (rlglLoadProc)loader;
// NOTE: Anisotropy levels capability is an extension
#ifndef GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT
#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF

View File

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

View File

@ -749,6 +749,53 @@ int main(int argc, char *argv[])
// 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!
int exCollectionCount = 0;
rlExampleInfo *exCollection = LoadExamplesData(exCollectionFilePath, "ALL", false, &exCollectionCount);
@ -875,11 +922,18 @@ int main(int argc, char *argv[])
else
{
// 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_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_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_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_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_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/raylib.sln
@ -893,7 +947,7 @@ int main(int argc, char *argv[])
FileTextReplace(TextFormat("%s/../projects/VS2022/examples/%s.vcxproj", exBasePath, exInfo->name),
"..\\..\\examples\\core", TextFormat("..\\..\\examples\\%s", exInfo->category));
exInfo->status |= VALID_MISSING_VCXPROJ;
exInfo->status &= ~VALID_MISSING_VCXPROJ;
}
// 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),
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
@ -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.js
// 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));
@ -924,7 +979,7 @@ int main(int argc, char *argv[])
FileCopy(TextFormat("%s/%s/%s.js", exBasePath, 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();
for (int i = 0; i < exCollectionCount; i++)
{
exCollection[i].status |= VALID_NOT_IN_MAKEFILE;
exCollection[i].status |= VALID_NOT_IN_MAKEFILE_WEB;
exCollection[i].status |= VALID_NOT_IN_README;
exCollection[i].status |= VALID_NOT_IN_JS;
exCollection[i].status &= ~VALID_NOT_IN_MAKEFILE;
exCollection[i].status &= ~VALID_NOT_IN_MAKEFILE_WEB;
exCollection[i].status &= ~VALID_NOT_IN_README;
exCollection[i].status &= ~VALID_NOT_IN_JS;
}
//------------------------------------------------------------------------------------------------
}
@ -1566,12 +1621,13 @@ static void UnloadTextLines(char **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 *exInfo = (rlExampleInfo *)RL_CALLOC(1, sizeof(rlExampleInfo));
if (IsFileExtension(exFileName, ".c"))
if (FileExists(exFileName) && IsFileExtension(exFileName, ".c"))
{
strcpy(exInfo->name, GetFileNameWithoutExt(exFileName));
strncpy(exInfo->category, exInfo->name, TextFindIndex(exInfo->name, "_"));
@ -1747,16 +1803,21 @@ static char **ScanExampleResources(const char *filePath, int *resPathCount)
strncpy(buffer, start, len);
buffer[len] = '\0';
// TODO: Make sure buffer is a path (and not a Tracelog() text)
// Check for known extensions
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]))
{
// Avoid duplicates
bool found = false;
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))