mirror of
https://github.com/raysan5/raylib.git
synced 2025-12-25 10:22:33 -05:00
Compare commits
14 Commits
3c9d3d9bef
...
d1b535c7b8
| Author | SHA1 | Date | |
|---|---|---|---|
| d1b535c7b8 | |||
| ed06cdbbe4 | |||
| 81615a91a6 | |||
| 6252d92f79 | |||
| a65bdd6cca | |||
| afdc7972d6 | |||
| 3ef5ee878c | |||
| 28b804a6ba | |||
| 7037f131dc | |||
| a9970484f3 | |||
| be974bb67e | |||
| eae1296b08 | |||
| 59c979a59d | |||
| 93f86fa074 |
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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) |
|
||||
|
||||
@ -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.
@ -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
|
||||
#
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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}
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
}
|
||||
*/
|
||||
|
||||
16
src/rcore.c
16
src/rcore.c
@ -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;
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ❌ |
|
||||
|
||||
@ -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))
|
||||
|
||||
Reference in New Issue
Block a user