Compare commits

...

27 Commits

Author SHA1 Message Date
Serhii Zasenko
f51204821a
Add vibration test button to core_input_gamepad (#5362) 2025-11-18 21:27:50 +01:00
Ray
a24e65d8e1
Update examples_testing_windows.md 2025-11-18 21:26:54 +01:00
Ray
f75682f5c9 Merge branch 'master' of https://github.com/raysan5/raylib 2025-11-18 21:26:33 +01:00
Ray
57e22d5fa0 Update rtext.c 2025-11-18 21:26:26 +01:00
Ray
1b6303b900
Update examples_testing_windows.md 2025-11-18 21:20:05 +01:00
Ray
83a167ca3f Update text_inline_styling.c 2025-11-18 21:19:55 +01:00
Ray
48496e2307 Update core_input_actions.c 2025-11-18 21:18:32 +01:00
Ray
e6ef99275a Update shapes_digital_clock.c 2025-11-18 21:14:48 +01:00
Ray
c7c6aaf156 Update examples_testing_windows.md 2025-11-18 21:12:25 +01:00
Ray
06958c91d0 Merge branch 'master' of https://github.com/raysan5/raylib 2025-11-18 20:59:55 +01:00
Ray
46ca641ec5 Update raygui to avoid warnings 2025-11-18 20:59:48 +01:00
Ray
f3393b8fd8 Update core_clipboard_text.c 2025-11-18 20:59:38 +01:00
Ray
8455f9d088 Update rexm.c 2025-11-18 20:59:33 +01:00
Ray
95d58ed988
Update examples_testing_windows.md 2025-11-18 20:52:05 +01:00
Ray
5da90172ac Update examples_testing_windows.md 2025-11-18 20:49:21 +01:00
Ray
6f4f4cc508 Update rexm.c 2025-11-18 20:44:23 +01:00
Ray
e062e3835e REVIEWED: examples: Several minor issues 2025-11-18 20:43:58 +01:00
Ray
dcc9e96148 Update rexm.c 2025-11-18 20:18:17 +01:00
Ray
6993bc7337 Update examples_testing_windows.md 2025-11-18 19:51:34 +01:00
Ray
a4a6812d68 REXM: REVIEWED: Testing report generation 2025-11-18 19:50:45 +01:00
Ray
9efe127f5d Update shapes_lines_drawing.c 2025-11-18 19:50:07 +01:00
Robin ❤️
4caba49658
[examples] Added: shapes_rlgl_color_wheel example (#5355)
* [examples] Added: `shapes_rlgl_triangle` example

* correct name

* formatting

* Revert "formatting"

This reverts commit f1d246a6482afb438d6371c469558729cbabf466.

* Revert "correct name"

This reverts commit 974985ed495d41323bd879e5ebcc21d80876db37.

* Revert "[examples] Added: `shapes_rlgl_triangle` example"

This reverts commit d053b9afa0a6f1d2c991f336db22397bb581742d.

* [examples] Added: `shapes_rlgl_color_wheel` example

* clarify color variable

* formatting

* formatting

* formatting

* formatting

* reduce redundancy

* moved color updating code to update
2025-11-18 16:31:43 +01:00
Ray
86e00bde65 Update rcore_desktop_sdl.c 2025-11-18 16:30:48 +01:00
Ray
95a8977e33 REXM: FIX: Web log redirect and download 2025-11-18 16:28:10 +01:00
Ray
f531ee2d8f Update rexm.c 2025-11-18 16:19:43 +01:00
MikiZX1
b18f547d8f
Update rcore_desktop_sdl.c, fix crash when strncpy tries to copy using NULL pointer (#5359)
When SDL_GameControllerNameForIndex returns null, the app crashes. This was addressed earlier in PR#4859 though the fix submitted on PR #4859 was only fixing the crashing and not addressing the root cause.
2025-11-18 16:19:07 +01:00
Serhii Zasenko
be9a24e68c
Fix controller not available right after win init (#5358)
- Fix IsGamepadAvailable() returns false for an available controller immediately after window initialization
2025-11-18 16:17:58 +01:00
20 changed files with 1130 additions and 583 deletions

View File

@ -41,7 +41,7 @@ int main(void)
"Copy and paste me!"
};
char *clipboardText = NULL;
const char *clipboardText = NULL;
char inputBuffer[256] = "Hello from raylib!"; // Random initial string
// UI required variables
@ -144,7 +144,7 @@ int main(void)
GuiSetState(STATE_DISABLED);
GuiLabel((Rectangle){ 50, 260, 700, 40 }, "Clipboard current text data:");
GuiSetStyle(TEXTBOX, TEXT_READONLY, 1);
GuiTextBox((Rectangle){ 50, 300, 700, 40 }, clipboardText, 256, false);
GuiTextBox((Rectangle){ 50, 300, 700, 40 }, (char *)clipboardText, 256, false);
GuiSetStyle(TEXTBOX, TEXT_READONLY, 0);
GuiLabel((Rectangle){ 50, 360, 700, 40 }, "Try copying text from other applications and pasting here!");
GuiSetState(STATE_NORMAL);

View File

@ -71,6 +71,7 @@ int main(void)
// Set default actions
char actionSet = 0;
SetActionsDefault();
bool releaseAction = false;
Vector2 position = (Vector2){ 400.0f, 200.0f };
Vector2 size = (Vector2){ 40.0f, 40.0f };
@ -83,7 +84,8 @@ int main(void)
{
// Update
//----------------------------------------------------------------------------------
gamepadIndex = 0; // set this to gamepad being checked
gamepadIndex = 0; // Set gamepad being checked
if (IsActionDown(ACTION_UP)) position.y -= 2;
if (IsActionDown(ACTION_DOWN)) position.y += 2;
if (IsActionDown(ACTION_LEFT)) position.x -= 2;
@ -93,6 +95,10 @@ int main(void)
position.x = (screenWidth-size.x)/2;
position.y = (screenHeight-size.y)/2;
}
// Register release action for one frame
releaseAction = false;
if (IsActionReleased(ACTION_FIRE)) releaseAction = true;
// Switch control scheme by pressing TAB
if (IsKeyPressed(KEY_TAB))
@ -109,7 +115,7 @@ int main(void)
ClearBackground(GRAY);
DrawRectangleV(position, size, RED);
DrawRectangleV(position, size, releaseAction? BLUE : RED);
DrawText((actionSet == 0)? "Current input set: WASD (default)" : "Current input set: Cursor", 10, 10, 20, WHITE);
DrawText("Use TAB key to toggles Actions keyset", 10, 50, 20, GREEN);

View File

@ -72,6 +72,8 @@ int main(void)
if (IsKeyPressed(KEY_LEFT) && gamepad > 0) gamepad--;
if (IsKeyPressed(KEY_RIGHT)) gamepad++;
Vector2 mousePosition = GetMousePosition();
bool mousePressed = IsMouseButtonPressed(MOUSE_BUTTON_LEFT);
if (IsGamepadAvailable(gamepad))
{
@ -262,6 +264,14 @@ int main(void)
DrawText(TextFormat("AXIS %i: %.02f", i, GetGamepadAxisMovement(gamepad, i)), 20, 70 + 20*i, 10, DARKGRAY);
}
Rectangle vibrateButton = (Rectangle){10, 70 + 20*GetGamepadAxisCount(gamepad) + 20, 75, 10};
if (mousePressed && CheckCollisionPointRec(mousePosition, vibrateButton)){
SetGamepadVibration(gamepad, 1.0, 1.0, 1.0);
}
DrawRectangleRec(vibrateButton, SKYBLUE);
DrawText("VIBRATE", vibrateButton.x + 14, vibrateButton.y + 1, 10, DARKGRAY);
if (GetGamepadButtonPressed() != GAMEPAD_BUTTON_UNKNOWN) DrawText(TextFormat("DETECTED BUTTON: %i", GetGamepadButtonPressed()), 10, 430, 10, RED);
else DrawText("DETECTED BUTTON: NONE", 10, 430, 10, GRAY);
}

View File

@ -3026,9 +3026,9 @@ int GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int
// NOTE: Requires static variables: frameCounter
int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode)
{
//#if !defined(RAYGUI_VALUEBOX_MAX_CHARS)
#if !defined(RAYGUI_VALUEBOX_MAX_CHARS)
#define RAYGUI_VALUEBOX_MAX_CHARS 32
//#endif
#endif
int result = 0;
GuiState state = guiState;
@ -3087,7 +3087,7 @@ int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, in
}
// Add new digit to text value
if ((keyCount < RAYGUI_VALUEBOX_MAX_CHARS) && (GuiGetTextWidth(textValue) < bounds.width))
if ((keyCount >= 0) && (keyCount < RAYGUI_VALUEBOX_MAX_CHARS) && (GuiGetTextWidth(textValue) < bounds.width))
{
int key = GetCharPressed();

View File

@ -67,7 +67,7 @@ int main(void)
models[i] = LoadModel(voxFileNames[i]);
double t1 = GetTime()*1000.0;
TraceLog(LOG_WARNING, TextFormat("[%s] File loaded in %.3f ms", voxFileNames[i], t1 - t0));
TraceLog(LOG_INFO, TextFormat("[%s] Model file loaded in %.3f ms", voxFileNames[i], t1 - t0));
// Compute model translation matrix to center model on draw position (0, 0 , 0)
BoundingBox bb = GetModelBoundingBox(models[i]);
@ -80,6 +80,8 @@ int main(void)
}
int currentModel = 0;
Vector3 modelpos = { 0 };
Vector3 camerarot = { 0 };
// Load voxel shader
Shader shader = LoadShader(TextFormat("resources/shaders/glsl%i/voxel_lighting.vs", GLSL_VERSION),
@ -98,11 +100,7 @@ int main(void)
// Assign out lighting shader to model
for (int i = 0; i < MAX_VOX_FILES; i++)
{
Model m = models[i];
for (int j = 0; j < m.materialCount; j++)
{
m.materials[j].shader = shader;
}
for (int j = 0; j < models[i].materialCount; j++) models[i].materials[j].shader = shader;
}
// Create lights
@ -112,12 +110,8 @@ int main(void)
lights[2] = CreateLight(LIGHT_POINT, (Vector3) { -20, 20, 20 }, Vector3Zero(), GRAY, shader);
lights[3] = CreateLight(LIGHT_POINT, (Vector3) { 20, -20, -20 }, Vector3Zero(), GRAY, shader);
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
Vector3 modelpos = { 0 };
Vector3 camerarot = { 0 };
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
@ -137,15 +131,11 @@ int main(void)
}
UpdateCameraPro(&camera,
(Vector3) {
(IsKeyDown(KEY_W) || IsKeyDown(KEY_UP))*0.1f - // Move forward-backward
(IsKeyDown(KEY_S) || IsKeyDown(KEY_DOWN))*0.1f,
(IsKeyDown(KEY_D) || IsKeyDown(KEY_RIGHT))*0.1f - // Move right-left
(IsKeyDown(KEY_A) || IsKeyDown(KEY_LEFT))*0.1f,
0.0f // Move up-down
},
camerarot,
GetMouseWheelMove()*-2.0f); // Move to target (zoom)
(Vector3){ (IsKeyDown(KEY_W) || IsKeyDown(KEY_UP))*0.1f - (IsKeyDown(KEY_S) || IsKeyDown(KEY_DOWN))*0.1f, // Move forward-backward
(IsKeyDown(KEY_D) || IsKeyDown(KEY_RIGHT))*0.1f - (IsKeyDown(KEY_A) || IsKeyDown(KEY_LEFT))*0.1f, // Move right-left
0.0f }, // Move up-down
camerarot, // Camera rotation
GetMouseWheelMove()*-2.0f); // Move to target (zoom)
// Cycle between models on mouse click
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) currentModel = (currentModel + 1) % MAX_VOX_FILES;
@ -156,36 +146,34 @@ int main(void)
// Update light values (actually, only enable/disable them)
for (int i = 0; i < MAX_LIGHTS; i++) UpdateLightValues(shader, lights[i]);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
ClearBackground(RAYWHITE);
// Draw 3D model
BeginMode3D(camera);
// Draw 3D model
BeginMode3D(camera);
DrawModel(models[currentModel], modelpos, 1.0f, WHITE);
DrawGrid(10, 1.0);
DrawModel(models[currentModel], modelpos, 1.0f, WHITE);
DrawGrid(10, 1.0);
// Draw spheres to show where the lights are
for (int i = 0; i < MAX_LIGHTS; i++)
{
if (lights[i].enabled) DrawSphereEx(lights[i].position, 0.2f, 8, 8, lights[i].color);
else DrawSphereWires(lights[i].position, 0.2f, 8, 8, ColorAlpha(lights[i].color, 0.3f));
}
EndMode3D();
// Draw spheres to show where the lights are
for (int i = 0; i < MAX_LIGHTS; i++)
{
if (lights[i].enabled) DrawSphereEx(lights[i].position, 0.2f, 8, 8, lights[i].color);
else DrawSphereWires(lights[i].position, 0.2f, 8, 8, ColorAlpha(lights[i].color, 0.3f));
}
EndMode3D();
// Display info
DrawRectangle(10, 400, 340, 60, Fade(SKYBLUE, 0.5f));
DrawRectangleLines(10, 400, 340, 60, Fade(DARKBLUE, 0.5f));
DrawText("MOUSE LEFT BUTTON to CYCLE VOX MODELS", 40, 410, 10, BLUE);
DrawText("MOUSE MIDDLE BUTTON to ZOOM OR ROTATE CAMERA", 40, 420, 10, BLUE);
DrawText("UP-DOWN-LEFT-RIGHT KEYS to MOVE CAMERA", 40, 430, 10, BLUE);
DrawText(TextFormat("File: %s", GetFileName(voxFileNames[currentModel])), 10, 10, 20, GRAY);
// Display info
DrawRectangle(10, 40, 340, 70, Fade(SKYBLUE, 0.5f));
DrawRectangleLines(10, 40, 340, 70, Fade(DARKBLUE, 0.5f));
DrawText("- MOUSE LEFT BUTTON: CYCLE VOX MODELS", 20, 50, 10, BLUE);
DrawText("- MOUSE MIDDLE BUTTON: ZOOM OR ROTATE CAMERA", 20, 70, 10, BLUE);
DrawText("- UP-DOWN-LEFT-RIGHT KEYS: MOVE CAMERA", 20, 90, 10, BLUE);
DrawText(TextFormat("Model file: %s", GetFileName(voxFileNames[currentModel])), 10, 10, 20, GRAY);
EndDrawing();
//----------------------------------------------------------------------------------
@ -201,5 +189,3 @@ int main(void)
return 0;
}

View File

@ -57,7 +57,7 @@ int main(void)
Mesh mesh = GenMeshPoints(numPoints);
Model model = LoadModelFromMesh(mesh);
//SetTargetFPS(60);
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
@ -92,15 +92,12 @@ int main(void)
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(BLACK);
BeginMode3D(camera);
// The new method only uploads the points once to the GPU
if (useDrawModelPoints)
{
DrawModelPoints(model, position, 1.0f, WHITE);
}
if (useDrawModelPoints) DrawModelPoints(model, position, 1.0f, WHITE);
else
{
// The old method must continually draw the "points" (lines)
@ -124,17 +121,16 @@ int main(void)
// Draw a unit sphere for reference
DrawSphereWires(position, 1.0f, 10, 10, YELLOW);
EndMode3D();
// Draw UI text
DrawText(TextFormat("Point Count: %d", numPoints), 20, screenHeight - 50, 40, WHITE);
DrawText("Up - increase points", 20, 70, 20, WHITE);
DrawText("Down - decrease points", 20, 100, 20, WHITE);
DrawText("Space - drawing function", 20, 130, 20, WHITE);
DrawText(TextFormat("Point Count: %d", numPoints), 10, screenHeight - 50, 40, WHITE);
DrawText("UP - Increase points", 10, 40, 20, WHITE);
DrawText("DOWN - Decrease points", 10, 70, 20, WHITE);
DrawText("SPACE - Drawing function", 10, 100, 20, WHITE);
if (useDrawModelPoints) DrawText("Using: DrawModelPoints()", 20, 160, 20, GREEN);
else DrawText("Using: DrawPoint3D()", 20, 160, 20, RED);
if (useDrawModelPoints) DrawText("Using: DrawModelPoints()", 10, 130, 20, GREEN);
else DrawText("Using: DrawPoint3D()", 10, 130, 20, RED);
DrawFPS(10, 10);

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,7 @@
#define GLSL_VERSION 100
#endif
#define MAP_SIZE 10
#define MAP_SIZE 16
//------------------------------------------------------------------------------------
// Program main entry point
@ -88,8 +88,6 @@ int main(void)
RenderTexture lightmap = LoadRenderTexture(MAP_SIZE, MAP_SIZE);
SetTextureFilter(lightmap.texture, TEXTURE_FILTER_TRILINEAR);
Material material = LoadMaterialDefault();
material.shader = shader;
material.maps[MATERIAL_MAP_ALBEDO].texture = texture;
@ -103,29 +101,33 @@ int main(void)
DrawTexturePro(
light,
(Rectangle){ 0, 0, (float)light.width, (float)light.height },
(Rectangle){ 0, 0, 20, 20 },
(Vector2){ 10.0, 10.0 },
(Rectangle){ 0, 0, 2.0f*MAP_SIZE, 2.0f*MAP_SIZE },
(Vector2){ (float)MAP_SIZE, (float)MAP_SIZE },
0.0,
RED
);
DrawTexturePro(
light,
(Rectangle){ 0, 0, (float)light.width, (float)light.height },
(Rectangle){ 8, 4, 20, 20 },
(Vector2){ 10.0, 10.0 },
(Rectangle){ (float)MAP_SIZE*0.8f, (float)MAP_SIZE/2.0f, 2.0f*MAP_SIZE, 2.0f*MAP_SIZE },
(Vector2){ (float)MAP_SIZE, (float)MAP_SIZE },
0.0,
BLUE
);
DrawTexturePro(
light,
(Rectangle){ 0, 0, (float)light.width, (float)light.height },
(Rectangle){ 8, 8, 10, 10 },
(Vector2){ 5.0, 5.0 },
(Rectangle){ (float)MAP_SIZE*0.8f, (float)MAP_SIZE*0.8f, (float)MAP_SIZE, (float)MAP_SIZE },
(Vector2){ (float)MAP_SIZE/2.0f, (float)MAP_SIZE/2.0f },
0.0,
GREEN
);
BeginBlendMode(BLEND_ALPHA);
EndTextureMode();
// NOTE: To enable trilinear filtering we need mipmaps available for texture
GenTextureMipmaps(&lightmap.texture);
SetTextureFilter(lightmap.texture, TEXTURE_FILTER_TRILINEAR);
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
@ -141,24 +143,20 @@ int main(void)
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
DrawMesh(mesh, material, MatrixIdentity());
EndMode3D();
DrawFPS(10, 10);
DrawTexturePro(
lightmap.texture,
(Rectangle){ 0, 0, -MAP_SIZE, -MAP_SIZE },
DrawTexturePro(lightmap.texture, (Rectangle){ 0, 0, -MAP_SIZE, -MAP_SIZE },
(Rectangle){ (float)GetRenderWidth() - MAP_SIZE*8 - 10, 10, (float)MAP_SIZE*8, (float)MAP_SIZE*8 },
(Vector2){ 0.0, 0.0 },
0.0,
WHITE);
(Vector2){ 0.0, 0.0 }, 0.0, WHITE);
DrawText("lightmap", GetRenderWidth() - 66, 16 + MAP_SIZE*8, 10, GRAY);
DrawText("10x10 pixels", GetRenderWidth() - 76, 30 + MAP_SIZE*8, 10, GRAY);
DrawText(TextFormat("LIGHTMAP: %ix%i pixels", MAP_SIZE, MAP_SIZE), GetRenderWidth() - 130, 20 + MAP_SIZE*8, 10, GREEN);
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------

View File

@ -77,7 +77,7 @@
*
* static unsigned int guiStyle[RAYGUI_MAX_CONTROLS*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED)];
*
* guiStyle size is by default: 16*(16 + 8) = 384*4 = 1536 bytes = 1.5 KB
* guiStyle size is by default: 16*(16 + 8) = 384 int = 384*4 bytes = 1536 bytes = 1.5 KB
*
* Note that the first set of BASE properties (by default guiStyle[0..15]) belong to the generic style
* used for all controls, when any of those base values is set, it is automatically populated to all
@ -141,7 +141,7 @@
* Draw text bounds rectangles for debug
*
* VERSIONS HISTORY:
* 5.0-dev (2025) Current dev version...
* 5.0 (xx-Nov-2025) ADDED: Support up to 32 controls (v500)
* ADDED: guiControlExclusiveMode and guiControlExclusiveRec for exclusive modes
* ADDED: GuiValueBoxFloat()
* ADDED: GuiDropdonwBox() properties: DROPDOWN_ARROW_HIDDEN, DROPDOWN_ROLL_UP
@ -271,7 +271,7 @@
* 0.8 (27-Aug-2015) Initial release. Implemented by Kevin Gato, Daniel Nicolás and Ramon Santamaria
*
* DEPENDENCIES:
* raylib 5.0 - Inputs reading (keyboard/mouse), shapes drawing, font loading and text drawing
* raylib 5.6-dev - Inputs reading (keyboard/mouse), shapes drawing, font loading and text drawing
*
* STANDALONE MODE:
* By default raygui depends on raylib mostly for the inputs and the drawing functionality but that dependency can be disabled
@ -1010,28 +1010,28 @@ typedef enum {
ICON_SLICING = 231,
ICON_MANUAL_CONTROL = 232,
ICON_COLLISION = 233,
ICON_234 = 234,
ICON_235 = 235,
ICON_236 = 236,
ICON_237 = 237,
ICON_238 = 238,
ICON_239 = 239,
ICON_240 = 240,
ICON_241 = 241,
ICON_242 = 242,
ICON_243 = 243,
ICON_244 = 244,
ICON_245 = 245,
ICON_246 = 246,
ICON_247 = 247,
ICON_248 = 248,
ICON_249 = 249,
ICON_CIRCLE_ADD = 234,
ICON_CIRCLE_ADD_FILL = 235,
ICON_CIRCLE_WARNING = 236,
ICON_CIRCLE_WARNING_FILL = 237,
ICON_BOX_MORE = 238,
ICON_BOX_MORE_FILL = 239,
ICON_BOX_MINUS = 240,
ICON_BOX_MINUS_FILL = 241,
ICON_UNION = 242,
ICON_INTERSECTION = 243,
ICON_DIFFERENCE = 244,
ICON_SPHERE = 245,
ICON_CYLINDER = 246,
ICON_CONE = 247,
ICON_ELLIPSOID = 248,
ICON_CAPSULE = 249,
ICON_250 = 250,
ICON_251 = 251,
ICON_252 = 252,
ICON_253 = 253,
ICON_254 = 254,
ICON_255 = 255,
ICON_255 = 255
} GuiIconName;
#endif
@ -1078,7 +1078,7 @@ typedef enum {
// Check if two rectangles are equal, used to validate a slider bounds as an id
#ifndef CHECK_BOUNDS_ID
#define CHECK_BOUNDS_ID(src, dst) ((src.x == dst.x) && (src.y == dst.y) && (src.width == dst.width) && (src.height == dst.height))
#define CHECK_BOUNDS_ID(src, dst) (((int)src.x == (int)dst.x) && ((int)src.y == (int)dst.y) && ((int)src.width == (int)dst.width) && ((int)src.height == (int)dst.height))
#endif
#if !defined(RAYGUI_NO_ICONS) && !defined(RAYGUI_CUSTOM_ICONS)
@ -1341,22 +1341,22 @@ static unsigned int guiIcons[RAYGUI_ICON_MAX_ICONS*RAYGUI_ICON_DATA_ELEMENTS] =
0x7fe00000, 0x402e4020, 0x43ce5e0a, 0x40504078, 0x438e4078, 0x402e5e0a, 0x7fe04020, 0x00000000, // ICON_SLICING
0x00000000, 0x40027ffe, 0x47c24002, 0x55425d42, 0x55725542, 0x50125552, 0x10105016, 0x00001ff0, // ICON_MANUAL_CONTROL
0x7ffe0000, 0x43c24002, 0x48124422, 0x500a500a, 0x500a500a, 0x44224812, 0x400243c2, 0x00007ffe, // ICON_COLLISION
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_234
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_235
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_236
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_237
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_238
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_239
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_240
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_241
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_242
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_243
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_244
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_245
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_246
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_247
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_248
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_249
0x03c00000, 0x10080c30, 0x21842184, 0x4ff24182, 0x41824ff2, 0x21842184, 0x0c301008, 0x000003c0, // ICON_CIRCLE_ADD
0x03c00000, 0x1ff80ff0, 0x3e7c3e7c, 0x700e7e7e, 0x7e7e700e, 0x3e7c3e7c, 0x0ff01ff8, 0x000003c0, // ICON_CIRCLE_ADD_FILL
0x03c00000, 0x10080c30, 0x21842184, 0x41824182, 0x40024182, 0x21842184, 0x0c301008, 0x000003c0, // ICON_CIRCLE_WARNING
0x03c00000, 0x1ff80ff0, 0x3e7c3e7c, 0x7e7e7e7e, 0x7ffe7e7e, 0x3e7c3e7c, 0x0ff01ff8, 0x000003c0, // ICON_CIRCLE_WARNING_FILL
0x00000000, 0x10041ffc, 0x10841004, 0x13e41084, 0x10841084, 0x10041004, 0x00001ffc, 0x00000000, // ICON_BOX_MORE
0x00000000, 0x1ffc1ffc, 0x1f7c1ffc, 0x1c1c1f7c, 0x1f7c1f7c, 0x1ffc1ffc, 0x00001ffc, 0x00000000, // ICON_BOX_MORE_FILL
0x00000000, 0x1ffc1ffc, 0x1ffc1ffc, 0x1c1c1ffc, 0x1ffc1ffc, 0x1ffc1ffc, 0x00001ffc, 0x00000000, // ICON_BOX_MINUS
0x00000000, 0x10041ffc, 0x10041004, 0x13e41004, 0x10041004, 0x10041004, 0x00001ffc, 0x00000000, // ICON_BOX_MINUS_FILL
0x07fe0000, 0x055606aa, 0x7ff606aa, 0x55766eba, 0x55766eaa, 0x55606ffe, 0x55606aa0, 0x00007fe0, // ICON_UNION
0x07fe0000, 0x04020402, 0x7fe20402, 0x456246a2, 0x456246a2, 0x402047fe, 0x40204020, 0x00007fe0, // ICON_INTERSECTION
0x07fe0000, 0x055606aa, 0x7ff606aa, 0x4436442a, 0x4436442a, 0x402047fe, 0x40204020, 0x00007fe0, // ICON_DIFFERENCE
0x03c00000, 0x10080c30, 0x20042004, 0x60064002, 0x47e2581a, 0x20042004, 0x0c301008, 0x000003c0, // ICON_SPHERE
0x03e00000, 0x08080410, 0x0c180808, 0x08080be8, 0x08080808, 0x08080808, 0x04100808, 0x000003e0, // ICON_CYLINDER
0x00800000, 0x01400140, 0x02200220, 0x04100410, 0x08080808, 0x1c1c13e4, 0x08081004, 0x000007f0, // ICON_CONE
0x00000000, 0x07e00000, 0x20841918, 0x40824082, 0x40824082, 0x19182084, 0x000007e0, 0x00000000, // ICON_ELLIPSOID
0x00000000, 0x00000000, 0x20041ff8, 0x40024002, 0x40024002, 0x1ff82004, 0x00000000, 0x00000000, // ICON_CAPSULE
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_250
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_251
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_252
@ -1743,7 +1743,7 @@ int GuiPanel(Rectangle bounds, const char *text)
// NOTE: Using GuiToggle() for the TABS
int GuiTabBar(Rectangle bounds, const char **text, int count, int *active)
{
#define RAYGUI_TABBAR_ITEM_WIDTH 160
#define RAYGUI_TABBAR_ITEM_WIDTH 148
int result = -1;
//GuiState state = guiState;
@ -1776,12 +1776,12 @@ int GuiTabBar(Rectangle bounds, const char **text, int count, int *active)
if (i == (*active))
{
toggle = true;
GuiToggle(tabBounds, GuiIconText(12, text[i]), &toggle);
GuiToggle(tabBounds, text[i], &toggle);
}
else
{
toggle = false;
GuiToggle(tabBounds, GuiIconText(12, text[i]), &toggle);
GuiToggle(tabBounds, text[i], &toggle);
if (toggle) *active = i;
}
@ -2590,7 +2590,7 @@ int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode)
int pasteLength = 0;
int pasteCodepoint;
int pasteCodepointSize;
// Count how many codepoints to copy, stopping at the first unwanted control character
while (true)
{
@ -2599,7 +2599,7 @@ int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode)
if (!(multiline && (pasteCodepoint == (int)'\n')) && !(pasteCodepoint >= 32)) break;
pasteLength += pasteCodepointSize;
}
if (pasteLength > 0)
{
// Move forward data from cursor position
@ -2662,7 +2662,7 @@ int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode)
while (offset < textLength)
{
if (!isspace(nextCodepoint & 0xff)) break;
offset += nextCodepointSize;
accCodepointSize += nextCodepointSize;
nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize);
@ -2673,11 +2673,11 @@ int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode)
textLength -= accCodepointSize;
}
else if ((textLength > textBoxCursorIndex) && (IsKeyPressed(KEY_DELETE) || (IsKeyDown(KEY_DELETE) && autoCursorShouldTrigger)))
{
// Delete single codepoint from text, after current cursor position
int nextCodepointSize = 0;
GetCodepointNext(text + textBoxCursorIndex, &nextCodepointSize);
@ -2704,7 +2704,7 @@ int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode)
offset -= prevCodepointSize;
accCodepointSize += prevCodepointSize;
}
// Check characters of the same type to delete (either ASCII punctuation or anything non-whitespace)
// Not using isalnum() since it only works on ASCII characters
bool puctuation = ispunct(prevCodepoint & 0xff);
@ -2723,11 +2723,11 @@ int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode)
textLength -= accCodepointSize;
textBoxCursorIndex -= accCodepointSize;
}
else if ((textBoxCursorIndex > 0) && (IsKeyPressed(KEY_BACKSPACE) || (IsKeyDown(KEY_BACKSPACE) && autoCursorShouldTrigger)))
{
// Delete single codepoint from text, before current cursor position
int prevCodepointSize = 0;
GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize);
@ -3033,7 +3033,7 @@ int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, in
int result = 0;
GuiState state = guiState;
char textValue[RAYGUI_VALUEBOX_MAX_CHARS + 1] = "\0";
char textValue[RAYGUI_VALUEBOX_MAX_CHARS + 1] = { 0 };
snprintf(textValue, RAYGUI_VALUEBOX_MAX_CHARS + 1, "%i", *value);
Rectangle textBounds = { 0 };
@ -3051,7 +3051,6 @@ int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, in
if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
{
Vector2 mousePoint = GetMousePosition();
bool valueHasChanged = false;
if (editMode)
@ -3070,7 +3069,7 @@ int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, in
keyCount--;
valueHasChanged = true;
}
else if (keyCount < RAYGUI_VALUEBOX_MAX_CHARS -1)
else if (keyCount < RAYGUI_VALUEBOX_MAX_CHARS)
{
if (keyCount == 0)
{
@ -3087,30 +3086,26 @@ int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, in
}
}
// Only allow keys in range [48..57]
if (keyCount < RAYGUI_VALUEBOX_MAX_CHARS)
// Add new digit to text value
if ((keyCount >= 0) && (keyCount < RAYGUI_VALUEBOX_MAX_CHARS) && (GuiGetTextWidth(textValue) < bounds.width))
{
if (GuiGetTextWidth(textValue) < bounds.width)
int key = GetCharPressed();
// Only allow keys in range [48..57]
if ((key >= 48) && (key <= 57))
{
int key = GetCharPressed();
if ((key >= 48) && (key <= 57))
{
textValue[keyCount] = (char)key;
keyCount++;
valueHasChanged = true;
}
textValue[keyCount] = (char)key;
keyCount++;
valueHasChanged = true;
}
}
// Delete text
if (keyCount > 0)
if ((keyCount > 0) && IsKeyPressed(KEY_BACKSPACE))
{
if (IsKeyPressed(KEY_BACKSPACE))
{
keyCount--;
textValue[keyCount] = '\0';
valueHasChanged = true;
}
keyCount--;
textValue[keyCount] = '\0';
valueHasChanged = true;
}
if (valueHasChanged) *value = TextToInteger(textValue);
@ -3224,9 +3219,9 @@ int GuiValueBoxFloat(Rectangle bounds, const char *text, char *textValue, float
textValue[1] = '\0';
keyCount++;
}
for (int i = keyCount; i > -1; i--) textValue[i + 1] = textValue[i];
textValue[0] = '-';
keyCount++;
valueHasChanged = true;

View File

@ -284,11 +284,13 @@ static void DrawDisplaySegment(Vector2 center, int length, int thick, bool verti
if (!vertical)
{
// Horizontal segment points
// 3___________________________5
// / \
// /1 x 6\
// \ /
// \2___________________________4/
/*
3___________________________5
/ \
/1 x 6\
\ /
\2___________________________4/
*/
Vector2 segmentPointsH[6] = {
(Vector2){ center.x - length/2.0f - thick/2.0f, center.y }, // Point 1
(Vector2){ center.x - length/2.0f, center.y + thick/2.0f }, // Point 2

View File

@ -51,6 +51,8 @@ int main(void)
BeginTextureMode(canvas);
ClearBackground(backgroundColor);
EndTextureMode();
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
@ -59,10 +61,7 @@ int main(void)
// Update
//----------------------------------------------------------------------------------
// Disable the hint text once the user clicks
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && startText)
{
startText = false;
}
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && startText) startText = false;
// Clear the canvas when the user middle-clicks
if (IsMouseButtonPressed(MOUSE_BUTTON_MIDDLE))
@ -79,7 +78,7 @@ int main(void)
if (leftButtonDown || rightButtonDown)
{
// The color for the line
Color drawColor;
Color drawColor = WHITE;
if (leftButtonDown)
{
@ -88,10 +87,7 @@ int main(void)
// While the hue is >=360, subtract it to bring it down into the range 0-360
// This is more visually accurate than resetting to zero
while (lineHue >= 360.0f)
{
lineHue -= 360.0f;
}
while (lineHue >= 360.0f) lineHue -= 360.0f;
// Create the final color
drawColor = ColorFromHSV(lineHue, 1.0f, 1.0f);
@ -104,10 +100,12 @@ int main(void)
// Draw the line onto the canvas
BeginTextureMode(canvas);
// Circles act as "caps", smoothing corners
DrawCircleV(mousePositionPrevious, lineThickness/2.0f, drawColor);
DrawCircleV(GetMousePosition(), lineThickness/2.0f, drawColor);
DrawLineEx(mousePositionPrevious, GetMousePosition(), lineThickness, drawColor);
EndTextureMode();
}

View File

@ -0,0 +1,280 @@
/*******************************************************************************************
*
* raylib [shapes] example - rlgl color wheel
*
* Example complexity rating: [] 3/4
*
* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
*
* Example contributed by Robin (@RobinsAviary) and reviewed by Ramon Santamaria (@raysan5)
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2025-2025 Robin (@RobinsAviary)
*
********************************************************************************************/
#include "raylib.h"
#include "rlgl.h"
#include "raymath.h"
#include <stdlib.h>
#include <stdio.h>
#define RAYGUI_IMPLEMENTATION
#include "raygui.h"
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
// The minimum/maximum points the circle can have
const unsigned int pointsMin = 3;
const unsigned int pointsMax = 256;
// The current number of points and the radius of the circle
unsigned int triangleCount = 64;
float pointScale = 150.0f;
// Slider value, literally maps to value in HSV
float value = 1.0f;
// The center of the screen
Vector2 center = { (float)screenWidth/2.0f, (float)screenHeight/2.0f };
// The location of the color wheel
Vector2 circlePosition = center;
// The currently selected color
Color color = { 255, 255, 255, 255 };
// Indicates if the slider is being clicked
bool sliderClicked = false;
// Indicates if the current color going to be updated, as well as the handle position
bool settingColor = false;
// How the color wheel will be rendered
unsigned int renderType = RL_TRIANGLES;
// Enable anti-aliasing
SetConfigFlags(FLAG_MSAA_4X_HINT);
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - rlgl color wheel");
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
triangleCount += (unsigned int)GetMouseWheelMove();
triangleCount = (unsigned int)Clamp((float)triangleCount, (float)pointsMin, (float)pointsMax);
Rectangle sliderRectangle = { 42.0f, 16.0f + 64.0f + 45.0f, 64.0f, 16.0f };
Vector2 mousePosition = GetMousePosition();
// Checks if the user is hovering over the value slider
bool sliderHover = (mousePosition.x >= sliderRectangle.x && mousePosition.y >= sliderRectangle.y && mousePosition.x < sliderRectangle.x + sliderRectangle.width && mousePosition.y < sliderRectangle.y + sliderRectangle.height);
// Copy color as hex
if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyDown(KEY_C))
{
if (IsKeyPressed(KEY_C))
{
SetClipboardText(TextFormat("#%02X%02X%02X", color.r, color.g, color.b));
}
}
// Scale up the color wheel, adjusting the handle visually
if (IsKeyDown(KEY_UP))
{
pointScale *= 1.025f;
if (pointScale > (float)screenHeight/2.0f)
{
pointScale = (float)screenHeight/2.0f;
}
else
{
circlePosition = Vector2Add(Vector2Multiply(Vector2Subtract(circlePosition, center), (Vector2){ 1.025f, 1.025f }), center);
}
}
// Scale down the wheel, adjusting the handle visually
if (IsKeyDown(KEY_DOWN))
{
pointScale *= 0.975f;
if (pointScale < 32.0f)
{
pointScale = 32.0f;
}
else
{
circlePosition = Vector2Add(Vector2Multiply(Vector2Subtract(circlePosition, center), (Vector2){ 0.975f, 0.975f }), center);
}
float distance = Vector2Distance(center, circlePosition)/pointScale;
float angle = ((Vector2Angle((Vector2){ 0.0f, -pointScale }, Vector2Subtract(center, circlePosition))/PI + 1.0f) / 2.0f);
if (distance > 1.0f)
{
circlePosition = Vector2Add((Vector2){ sinf(angle*(PI * 2.0f)) * pointScale, -cosf(angle*(PI*2.0f))*pointScale }, center);
}
}
// Checks if the user clicked on the color wheel
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && Vector2Distance(GetMousePosition(), center) <= pointScale + 10.0f)
{
settingColor = true;
}
// Update flag when mouse button is released
if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) settingColor = false;
// Check if the user clicked/released the slider for the color's value
if (sliderHover && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) sliderClicked = true;
if (sliderClicked && IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) sliderClicked = false;
// Update render mode accordingly
if (IsKeyPressed(KEY_SPACE)) renderType = RL_LINES;
if (IsKeyReleased(KEY_SPACE)) renderType = RL_TRIANGLES;
// If the slider or the wheel was clicked, update the current color
if (settingColor || sliderClicked)
{
if (settingColor) {
circlePosition = GetMousePosition();
}
float distance = Vector2Distance(center, circlePosition) / pointScale;
float angle = ((Vector2Angle((Vector2){ 0.0f, -pointScale }, Vector2Subtract(center, circlePosition))/PI + 1.0f)/2.0f);
if (settingColor && distance > 1.0f) {
circlePosition = Vector2Add((Vector2){ sinf(angle*(PI*2.0f))*pointScale, -cosf(angle*(PI* 2.0f))*pointScale }, center);
}
float angle360 = angle*360.0f;
float valueActual = Clamp(distance, 0.0f, 1.0f);
color = ColorLerp((Color){ (int)(value*255.0f), (int)(value*255.0f), (int)(value*255.0f), 255 }, ColorFromHSV(angle360, Clamp(distance, 0.0f, 1.0f), 1.0f), valueActual);
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
// Begin rendering color wheel
rlBegin(renderType);
for (unsigned int i = 0; i < triangleCount; i++)
{
float angleOffset = ((PI*2.0f)/(float)triangleCount);
float angle = angleOffset*(float)i;
float angleOffsetCalculated = ((float)i + 1)*angleOffset;
Vector2 scale = (Vector2){ pointScale, pointScale };
Vector2 offset = Vector2Multiply((Vector2){ sinf(angle), -cosf(angle) }, scale);
Vector2 offset2 = Vector2Multiply((Vector2){ sinf(angleOffsetCalculated), -cosf(angleOffsetCalculated) }, scale);
Vector2 position = Vector2Add(center, offset);
Vector2 position2 = Vector2Add(center, offset2);
float angleNonRadian = (angle/(2.0f*PI))*360.0f;
float angleNonRadianOffset = (angleOffset/(2.0f*PI))*360.0f;
Color currentColor = ColorFromHSV(angleNonRadian, 1.0f, 1.0f);
Color offsetColor = ColorFromHSV(angleNonRadian + angleNonRadianOffset, 1.0f, 1.0f);
// Input vertices differently depending on mode
if (renderType == RL_TRIANGLES)
{
// RL_TRIANGLES expects three vertices per triangle
rlColor4ub(currentColor.r, currentColor.g, currentColor.b, currentColor.a);
rlVertex2f(position.x, position.y);
rlColor4f(value, value, value, 1.0f);
rlVertex2f(center.x, center.y);
rlColor4ub(offsetColor.r, offsetColor.g, offsetColor.b, offsetColor.a);
rlVertex2f(position2.x, position2.y);
}
else if (renderType == RL_LINES)
{
// RL_LINES expects two vertices per line
rlColor4ub(currentColor.r, currentColor.g, currentColor.b, currentColor.a);
rlVertex2f(position.x, position.y);
rlColor4ub(WHITE.r, WHITE.g, WHITE.b, WHITE.a);
rlVertex2f(center.x, center.y);
rlVertex2f(center.x, center.y);
rlColor4ub(offsetColor.r, offsetColor.g, offsetColor.b, offsetColor.a);
rlVertex2f(position2.x, position2.y);
rlVertex2f(position2.x, position2.y);
rlColor4ub(currentColor.r, currentColor.g, currentColor.b, currentColor.a);
rlVertex2f(position.x, position.y);
}
}
rlEnd();
// Make the handle slightly more visible overtop darker colors
Color handleColor = BLACK;
if (Vector2Distance(center, circlePosition)/pointScale <= 0.5f && value <= 0.5f)
{
handleColor = DARKGRAY;
}
// Draw the color handle
DrawCircleLinesV(circlePosition, 4.0f, handleColor);
// Draw the color in a preview, with a darkened outline.
DrawRectangleV((Vector2){ 8.0f, 8.0f }, (Vector2){ 64.0f, 64.0f }, color);
DrawRectangleLinesEx((Rectangle){ 8.0f, 8.0f, 64.0f, 64.0f }, 2.0f, ColorLerp(color, BLACK, 0.5f));
// Draw current color as hex and decimal
DrawText(TextFormat("#%02X%02X%02X\n(%d, %d, %d)", color.r, color.g, color.b, color.r, color.g, color.b), 8, 8 + 64 + 8, 20, DARKGRAY);
// Update the visuals for the copying text
Color copyColor = DARKGRAY;
unsigned int offset = 0;
if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyDown(KEY_C))
{
copyColor = DARKGREEN;
offset = 4;
}
// Draw the copying text
DrawText("press ctrl+c to copy!", 8, 425 - offset, 20, copyColor);
// Display the number of rendered triangles
DrawText(TextFormat("triangle count: %d", triangleCount), 8, 395, 20, DARKGRAY);
// Slider to change color's value
GuiSliderBar(sliderRectangle, "value: ", "", &value, 0.0f, 1.0f);
// Draw FPS next to outlined color preview
DrawFPS(64 + 16, 8);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

View File

@ -210,7 +210,7 @@ static Vector2 MeasureTextStyled(Font font, const char *text, float fontSize, fl
if ((font.texture.id == 0) || (text == NULL) || (text[0] == '\0')) return textSize; // Security check
int textLen = TextLength(text); // Get size in bytes of text
float textLineSpacing = fontSize*1.5f;
//float textLineSpacing = fontSize*1.5f; // Not used...
float textWidth = 0.0f;
float textHeight = fontSize;

View File

@ -40,7 +40,7 @@ int main(void)
// NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required)
Texture texPattern = LoadTexture("resources/patterns.png");
SetTextureFilter(texPattern, TEXTURE_FILTER_TRILINEAR); // Makes the texture smoother when upscaled
SetTextureFilter(texPattern, TEXTURE_FILTER_BILINEAR); // Makes the texture smoother when upscaled
// Coordinates for all patterns inside the texture
const Rectangle recPattern[] = {
@ -110,19 +110,17 @@ int main(void)
}
}
// Handle keys
// Change scale
// Handle keys: change scale
if (IsKeyPressed(KEY_UP)) scale += 0.25f;
if (IsKeyPressed(KEY_DOWN)) scale -= 0.25f;
if (scale > 10.0f) scale = 10.0f;
else if ( scale <= 0.0f) scale = 0.25f;
// Change rotation
// Handle keys: change rotation
if (IsKeyPressed(KEY_LEFT)) rotation -= 25.0f;
if (IsKeyPressed(KEY_RIGHT)) rotation += 25.0f;
// Reset
// Handle keys: reset
if (IsKeyPressed(KEY_SPACE)) { rotation = 0.0f; scale = 1.0f; }
//----------------------------------------------------------------------------------
@ -165,7 +163,7 @@ int main(void)
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadTexture(texPattern); // Unload texture
UnloadTexture(texPattern); // Unload texture
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------

View File

@ -1749,7 +1749,12 @@ int InitPlatform(void)
{
// WARNING: If glfwGetJoystickName() is longer than MAX_GAMEPAD_NAME_LENGTH,
// we can get a not-NULL terminated string, so, we only copy up to (MAX_GAMEPAD_NAME_LENGTH - 1)
if (glfwJoystickPresent(i)) strncpy(CORE.Input.Gamepad.name[i], glfwGetJoystickName(i), MAX_GAMEPAD_NAME_LENGTH - 1);
if (glfwJoystickPresent(i))
{
CORE.Input.Gamepad.ready[i] = true;
CORE.Input.Gamepad.axisCount[i] = GLFW_GAMEPAD_AXIS_LAST + 1;
strncpy(CORE.Input.Gamepad.name[i], glfwGetJoystickName(i), MAX_GAMEPAD_NAME_LENGTH - 1);
}
}
//----------------------------------------------------------------------------

View File

@ -1723,12 +1723,11 @@ void PollInputEvents(void)
CORE.Input.Gamepad.axisState[nextAvailableSlot][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f;
CORE.Input.Gamepad.axisState[nextAvailableSlot][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f;
memset(CORE.Input.Gamepad.name[nextAvailableSlot], 0, MAX_GAMEPAD_NAME_LENGTH);
strncpy(CORE.Input.Gamepad.name[nextAvailableSlot], SDL_GameControllerNameForIndex(nextAvailableSlot), MAX_GAMEPAD_NAME_LENGTH - 1);
}
else
{
TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError());
const char *controllerName = SDL_GameControllerNameForIndex(nextAvailableSlot);
if (controllerName != NULL) strncpy(CORE.Input.Gamepad.name[nextAvailableSlot], controllerName, MAX_GAMEPAD_NAME_LENGTH - 1);
else strncpy(CORE.Input.Gamepad.name[nextAvailableSlot], "noname", 6);
}
else TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError());
}
} break;
case SDL_JOYDEVICEREMOVED:

View File

@ -724,7 +724,8 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
stbtt_GetCodepointHMetrics(&fontInfo, cp, &glyphs[k].advanceX, NULL);
glyphs[k].advanceX = (int)((float)glyphs[k].advanceX*scaleFactor);
if (cpHeight > fontSize) TRACELOG(LOG_WARNING, "FONT: [0x%04x] Glyph height is bigger than requested font size: %i > %i", cp, cpHeight, (int)fontSize);
// WARNING: If requested SDF font, sdf-glyph height is definitely bigger than fontSize due to FONT_SDF_CHAR_PADDING
if ((type != FONT_SDF) && (cpHeight > fontSize)) TRACELOG(LOG_WARNING, "FONT: [0x%04x] Glyph height is bigger than requested font size: %i > %i", cp, cpHeight, (int)fontSize);
// Load glyph image
glyphs[k].image.width = cpWidth;

View File

@ -4,7 +4,8 @@
```
Example automated testing elements validated:
- [WARN] : WARNING messages count
- [CWARN] : Compilation WARNING messages
- [LWARN] : Log WARNING messages count
- [INIT] : Initialization
- [CLOSE] : Closing
- [ASSETS] : Assets loading
@ -13,8 +14,9 @@ Example automated testing elements validated:
- [FONT] : Font default initialization
- [TIMER] : Timer initialization
```
| **EXAMPLE NAME** | [WARN] | [INIT] | [CLOSE] | [ASSETS] | [RLGL] | [PLAT] | [FONT] | [TIMER] |
|:---------------------------------|:------:|:------:|:-------:|:--------:|:------:|:------:|:------:|:-------:|
| core_custom_logging | 0 | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ |
| core_custom_frame_control | 0 | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔ |
| **EXAMPLE NAME** | [CWARN] | [LWARN] | [INIT] | [CLOSE] | [ASSETS] | [RLGL] | [PLAT] | [FONT] | [TIMER] |
|:---------------------------------|:-------:|:-------:|:------:|:-------:|:--------:|:------:|:------:|:------:|:-------:|
| text_font_loading | 0 | 10 | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| text_codepoints_loading | 0 | 1 | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| models_animation_playing | 0 | 1 | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ |

View File

@ -415,12 +415,17 @@ int main(int argc, char *argv[])
else
{
// Support building/testing not only individual examples but multiple: ALL/<category>
rlExampleInfo *exBuildListInfo = LoadExampleData(argv[2], false, &exBuildListCount);
int exBuildListInfoCount = 0;
rlExampleInfo *exBuildListInfo = LoadExampleData(argv[2], false, &exBuildListInfoCount);
for (int i = 0; i < exBuildListCount; i++)
for (int i = 0; i < exBuildListInfoCount; i++)
{
exBuildList[i] = (char *)RL_CALLOC(256, sizeof(char));
strcpy(exBuildList[i], exBuildListInfo[i].name);
if (!TextIsEqual(exBuildListInfo[i].category, "others"))
{
exBuildList[exBuildListCount] = (char *)RL_CALLOC(256, sizeof(char));
strcpy(exBuildList[exBuildListCount], exBuildListInfo[i].name);
exBuildListCount++;
}
}
UnloadExampleData(exBuildListInfo);
@ -1266,8 +1271,8 @@ int main(int argc, char *argv[])
_putenv("PATH=%PATH%;C:\\raylib\\w64devkit\\bin");
system(TextFormat("mingw32-make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exInfo->category, exInfo->name));
#else
LOG("INFO: [%s] Building example for PLATFORM_WEB (Host: POSIX)\n", exInfo->filter);
system(TextFormat("make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exInfo->category, exInfo->filter));
LOG("INFO: [%s] Building example for PLATFORM_WEB (Host: POSIX)\n", exInfo->name);
system(TextFormat("make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exInfo->category, exInfo->name));
#endif
// Update generated .html metadata
@ -1479,6 +1484,11 @@ int main(int argc, char *argv[])
memset(exCategory, 0, 32);
strncpy(exCategory, exName, TextFindIndex(exName, "_"));
// Skip some examples from building
if ((strcmp(exName, "core_custom_logging") == 0) ||
(strcmp(exName, "core_window_should_close") == 0) ||
(strcmp(exName, "core_custom_frame_control") == 0)) continue;
LOG("INFO: [%i/%i] Testing example: [%s]\n", i + 1, exBuildListCount, exName);
// Steps to follow
@ -1500,16 +1510,17 @@ int main(int argc, char *argv[])
TextFormat("%s/%s/%s.original.c", exBasePath, exCategory, exName));
char *srcText = LoadFileText(TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName));
#define BUILD_TESTING_WEB
//#define BUILD_TESTING_WEB
#if defined(BUILD_TESTING_WEB)
static const char *mainReplaceText =
"#include <stdio.h>\n"
"#include <string.h>\n"
"#include <stdlib.h>\n"
"#include <emscripten/emscripten.h>\n\n"
"static char logText[1024] = {0};\n"
"static char logText[4096] = {0};\n"
"static int logTextOffset = 0;\n\n"
"void CustomTraceLog(int msgType, const char *text, va_list args)\n{\n"
" if (logTextOffset < 3800)\n {\n"
" switch (msgType)\n {\n"
" case LOG_INFO: logTextOffset += sprintf(logText + logTextOffset, \"INFO: \"); break;\n"
" case LOG_ERROR: logTextOffset += sprintf(logText + logTextOffset, \"ERROR: \"); break;\n"
@ -1517,7 +1528,7 @@ int main(int argc, char *argv[])
" case LOG_DEBUG: logTextOffset += sprintf(logText + logTextOffset, \"DEBUG: \"); break;\n"
" default: break;\n }\n"
" logTextOffset += vsprintf(logText + logTextOffset, text, args);\n"
" logTextOffset += sprintf(logText + logTextOffset, \"\\n\");\n}\n\n"
" logTextOffset += sprintf(logText + logTextOffset, \"\\n\");\n}\n}\n\n"
"int main(int argc, char *argv[])\n{\n"
" SetTraceLogCallback(CustomTraceLog);\n"
" int requestedTestFrames = 0;\n"
@ -1525,20 +1536,20 @@ int main(int argc, char *argv[])
" if ((argc > 1) && (argc == 3) && (strcmp(argv[1], \"--frames\") != 0)) requestedTestFrames = atoi(argv[2]);\n";
static const char *returnReplaceText =
" char outputLogFile[256] = { 0 };\n"
" TextCopy(outputLogFile, GetFileNameWithoutExt(argv[0]));\n"
" SaveFileText(outputLogFile, logText);\n"
" emscripten_run_script(TextFormat(\"saveFileFromMEMFSToDisk('%s','%s')\", outputLogFile, GetFileName(outputLogFile)));\n\n"
" SaveFileText(\"outputLogFileName\", logText);\n"
" emscripten_run_script(\"saveFileFromMEMFSToDisk('outputLogFileName','outputLogFileName')\");\n\n"
" return 0";
char *returnReplaceTextUpdated = TextReplace(returnReplaceText, "outputLogFileName", TextFormat("%s.log", exName));
char *srcTextUpdated[4] = { 0 };
srcTextUpdated[0] = TextReplace(srcText, "int main(void)\n{", mainReplaceText);
srcTextUpdated[1] = TextReplace(srcTextUpdated[0], "WindowShouldClose()", "WindowShouldClose() && (testFramesCount < requestedTestFrames)");
srcTextUpdated[2] = TextReplace(srcTextUpdated[1], "EndDrawing();", "EndDrawing(); testFramesCount++;");
srcTextUpdated[3] = TextReplace(srcTextUpdated[2], " return 0", returnReplaceText);
srcTextUpdated[3] = TextReplace(srcTextUpdated[2], " return 0", returnReplaceTextUpdated);
MemFree(returnReplaceTextUpdated);
UnloadFileText(srcText);
//SaveFileText(TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName), srcTextUpdated[3]);
SaveFileText(TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName), srcTextUpdated[3]);
for (int i = 0; i < 4; i++) { MemFree(srcTextUpdated[i]); srcTextUpdated[i] = NULL; }
// Build example for PLATFORM_WEB
@ -1548,7 +1559,7 @@ int main(int argc, char *argv[])
// Build: raylib.com/examples/<category>/<category>_example_name.js
#if defined(_WIN32)
LOG("INFO: [%s] Building example for PLATFORM_WEB (Host: Win32)\n", exName);
system(TextFormat("mingw32-make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exCategory, exName));
system(TextFormat("mingw32-make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B > %s/%s/logs/%s.build.log 2>&1", exBasePath, exCategory, exName));
#else
LOG("INFO: [%s] Building example for PLATFORM_WEB (Host: POSIX)\n", exName);
system(TextFormat("make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exCategory, exName));
@ -1560,9 +1571,11 @@ int main(int argc, char *argv[])
// STEP 3: Run example on browser
ChangeDirectory(TextFormat("%s/%s", exBasePath, exCategory));
system("start python -m http.server 8080");
system("start python -m http.server 8080"); // TODO: Init localhost just once!
system(TextFormat("start explorer \"http:\\localhost:8080/%s.html", exName));
// NOTE: Example .log is automatically downloaded into system Downloads directory on browser-example exectution
#else // BUILD_TESTING_DESKTOP
static const char *mainReplaceText =
@ -1620,6 +1633,7 @@ int main(int argc, char *argv[])
for (int k = 0, index = 0; k < exTestBuildLogLinesCount; k++)
{
// Checking compilation warnings generated
if (TextFindIndex(exTestBuildLogLines[k], "warning:") >= 0) testing[i].buildwarns++;
}
@ -1663,7 +1677,8 @@ int main(int argc, char *argv[])
//-----------------------------------------------------------------------------------------------------
/*
Columns:
- [WARN] : WARNING messages count
- [CWARN] : Compilation WARNING messages
- [LWARN] : Log WARNING messages count
- [INIT] : Initialization
- [CLOSE] : Closing
- [ASSETS] : Assets loading
@ -1672,9 +1687,9 @@ int main(int argc, char *argv[])
- [FONT] : Font default initialization
- [TIMER] : Timer initialization
| **EXAMPLE NAME** | [WARN] | [INIT] | [CLOSE] | [ASSETS] | [RLGL] | [PLAT] | [FONT] | [TIMER] |
|:---------------------------------|:------:|:------:|:-------:|:--------:|:------:|:------:|:------:|:-------:|
| core_basic window | 0 | | | | | | | |
| **EXAMPLE NAME** | [CWARN] | [LWARN] | [INIT] | [CLOSE] | [ASSETS] | [RLGL] | [PLAT] | [FONT] | [TIMER] |
|:---------------------------------|:-------:|:-------:|:------:|:-------:|:--------:|:------:|:------:|:------:|:-------:|
| core_basic window | 0 | 0 | | | | | | | |
*/
LOG("INFO: [examples_testing.md] Generating examples testing report...\n");
@ -1685,7 +1700,8 @@ int main(int argc, char *argv[])
repIndex += sprintf(report + repIndex, "## Tested Platform: Windows\n\n");
repIndex += sprintf(report + repIndex, "```\nExample automated testing elements validated:\n");
repIndex += sprintf(report + repIndex, " - [WARN] : WARNING messages count\n");
repIndex += sprintf(report + repIndex, " - [CWARN] : Compilation WARNING messages\n");
repIndex += sprintf(report + repIndex, " - [LWARN] : Log WARNING messages count\n");
repIndex += sprintf(report + repIndex, " - [INIT] : Initialization\n");
repIndex += sprintf(report + repIndex, " - [CLOSE] : Closing\n");
repIndex += sprintf(report + repIndex, " - [ASSETS] : Assets loading\n");
@ -1694,8 +1710,8 @@ int main(int argc, char *argv[])
repIndex += sprintf(report + repIndex, " - [FONT] : Font default initialization\n");
repIndex += sprintf(report + repIndex, " - [TIMER] : Timer initialization\n```\n");
repIndex += sprintf(report + repIndex, "| **EXAMPLE NAME** | [WARN] | [INIT] | [CLOSE] | [ASSETS] | [RLGL] | [PLAT] | [FONT] | [TIMER] |\n");
repIndex += sprintf(report + repIndex, "|:---------------------------------|:------:|:------:|:-------:|:--------:|:------:|:------:|:------:|:-------:|\n");
repIndex += sprintf(report + repIndex, "| **EXAMPLE NAME** | [CWARN] | [LWARN] | [INIT] | [CLOSE] | [ASSETS] | [RLGL] | [PLAT] | [FONT] | [TIMER] |\n");
repIndex += sprintf(report + repIndex, "|:---------------------------------|:-------:|:-------:|:------:|:-------:|:--------:|:------:|:------:|:------:|:-------:|\n");
/*
TESTING_FAIL_INIT = 1 << 0, // Initialization (InitWindow()) -> "INFO: DISPLAY: Device initialized successfully"
@ -1708,23 +1724,41 @@ int main(int argc, char *argv[])
*/
for (int i = 0; i < exBuildListCount; i++)
{
if (testing[i].status > 0)
if ((testing[i].buildwarns > 0) || (testing[i].warnings > 0) || (testing[i].status > 0))
{
repIndex += sprintf(report + repIndex, "| %-32s | %i | %s | %s | %s | %s | %s | %s | %s |\n",
exBuildList[i], testing[i].warnings,
(testing[i].status & TESTING_FAIL_INIT)? "" : "",
(testing[i].status & TESTING_FAIL_CLOSE)? "" : "",
(testing[i].status & TESTING_FAIL_ASSETS)? "" : "",
(testing[i].status & TESTING_FAIL_RLGL)? "" : "",
(testing[i].status & TESTING_FAIL_PLATFORM)? "" : "",
(testing[i].status & TESTING_FAIL_FONT)? "" : "",
(testing[i].status & TESTING_FAIL_TIMER)? "" : "");
repIndex += sprintf(report + repIndex, "| %-32s | %i | %i | %s | %s | %s | %s | %s | %s | %s |\n",
exBuildList[i],
testing[i].buildwarns,
testing[i].warnings,
(testing[i].status & TESTING_FAIL_INIT)? "" : "",
(testing[i].status & TESTING_FAIL_CLOSE)? "" : "",
(testing[i].status & TESTING_FAIL_ASSETS)? "" : "",
(testing[i].status & TESTING_FAIL_RLGL)? "" : "",
(testing[i].status & TESTING_FAIL_PLATFORM)? "" : "",
(testing[i].status & TESTING_FAIL_FONT)? "" : "",
(testing[i].status & TESTING_FAIL_TIMER)? "" : "");
}
}
repIndex += sprintf(report + repIndex, "\n");
SaveFileText(TextFormat("%s/../tools/rexm/reports/%s", exBasePath, "examples_testing_windows.md"), report);
#if defined(PLATFORM_DRM)
const char *osName = "drm";
#elif defined(PLATFORM_WEB)
const char *osName = "web";
#elif defined(PLATFORM_DESKTOP)
#if defined(_WIN32)
const char *osName = "windows";
#elif defined(__linux__)
const char *osName = "linux";
#elif defined(__FreeBSD__)
const char *osName = "freebsd";
#elif defined(__APPLE__)
const char *osName = "macos";
#endif // Desktop OSs
#endif
SaveFileText(TextFormat("%s/../tools/rexm/reports/examples_testing_%s.md", exBasePath, osName), report);
RL_FREE(report);
//-----------------------------------------------------------------------------------------------------