diff --git a/2023-07-20-13-08-52.png b/2023-07-20-13-08-52.png new file mode 100644 index 0000000..ee21efd Binary files /dev/null and b/2023-07-20-13-08-52.png differ diff --git a/examples/core/core_3d_picking.c b/examples/core/core_3d_picking.c deleted file mode 100644 index c7bf946..0000000 --- a/examples/core/core_3d_picking.c +++ /dev/null @@ -1,118 +0,0 @@ -/******************************************************************************************* -* -* raylib [core] example - Picking in 3d mode -* -* Example originally created with raylib 1.3, last time updated with raylib 4.0 -* -* 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) 2015-2023 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main(void) -{ - // Initialization - //-------------------------------------------------------------------------------------- - const int screenWidth = 800; - const int screenHeight = 450; - - InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d picking"); - - // Define the camera to look into our 3d world - Camera camera = { 0 }; - camera.position = (Vector3){ 10.0f, 10.0f, 10.0f }; // Camera position - camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point - camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) - camera.fovy = 45.0f; // Camera field-of-view Y - camera.projection = CAMERA_PERSPECTIVE; // Camera projection type - - Vector3 cubePosition = { 0.0f, 1.0f, 0.0f }; - Vector3 cubeSize = { 2.0f, 2.0f, 2.0f }; - - Ray ray = { 0 }; // Picking line ray - RayCollision collision = { 0 }; // Ray collision hit info - - 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 - //---------------------------------------------------------------------------------- - if (IsCursorHidden()) UpdateCamera(&camera, CAMERA_FIRST_PERSON); - - // Toggle camera controls - if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT)) - { - if (IsCursorHidden()) EnableCursor(); - else DisableCursor(); - } - - if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) - { - if (!collision.hit) - { - ray = GetMouseRay(GetMousePosition(), camera); - - // Check collision between ray and box - collision = GetRayCollisionBox(ray, - (BoundingBox){(Vector3){ cubePosition.x - cubeSize.x/2, cubePosition.y - cubeSize.y/2, cubePosition.z - cubeSize.z/2 }, - (Vector3){ cubePosition.x + cubeSize.x/2, cubePosition.y + cubeSize.y/2, cubePosition.z + cubeSize.z/2 }}); - } - else collision.hit = false; - } - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - BeginMode3D(camera); - - if (collision.hit) - { - DrawCube(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, RED); - DrawCubeWires(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, MAROON); - - DrawCubeWires(cubePosition, cubeSize.x + 0.2f, cubeSize.y + 0.2f, cubeSize.z + 0.2f, GREEN); - } - else - { - DrawCube(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, GRAY); - DrawCubeWires(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, DARKGRAY); - } - - DrawRay(ray, MAROON); - DrawGrid(10, 1.0f); - - EndMode3D(); - - DrawText("Try clicking on the box with your mouse!", 240, 10, 20, DARKGRAY); - - if (collision.hit) DrawText("BOX SELECTED", (screenWidth - MeasureText("BOX SELECTED", 30)) / 2, (int)(screenHeight * 0.1f), 30, GREEN); - - DrawText("Right click mouse to toggle camera controls", 10, 430, 10, GRAY); - - DrawFPS(10, 10); - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} diff --git a/examples/core/core_custom_logging.c b/examples/core/core_custom_logging.c deleted file mode 100644 index b4da2d5..0000000 --- a/examples/core/core_custom_logging.c +++ /dev/null @@ -1,88 +0,0 @@ -/******************************************************************************************* -* -* raylib [core] example - Custom logging -* -* Example originally created with raylib 2.5, last time updated with raylib 2.5 -* -* Example contributed by Pablo Marcos Oltra (@pamarcos) 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) 2018-2023 Pablo Marcos Oltra (@pamarcos) and Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -#include // Required for: fopen(), fclose(), fputc(), fwrite(), printf(), fprintf(), funopen() -#include // Required for: time_t, tm, time(), localtime(), strftime() - -// Custom logging function -void CustomLog(int msgType, const char *text, va_list args) -{ - char timeStr[64] = { 0 }; - time_t now = time(NULL); - struct tm *tm_info = localtime(&now); - - strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", tm_info); - printf("[%s] ", timeStr); - - switch (msgType) - { - case LOG_INFO: printf("[INFO] : "); break; - case LOG_ERROR: printf("[ERROR]: "); break; - case LOG_WARNING: printf("[WARN] : "); break; - case LOG_DEBUG: printf("[DEBUG]: "); break; - default: break; - } - - vprintf(text, args); - printf("\n"); -} - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main(void) -{ - // Initialization - //-------------------------------------------------------------------------------------- - const int screenWidth = 800; - const int screenHeight = 450; - - // Set custom logger - SetTraceLogCallback(CustomLog); - - InitWindow(screenWidth, screenHeight, "raylib [core] example - custom logging"); - - 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 - //---------------------------------------------------------------------------------- - // TODO: Update your variables here - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - DrawText("Check out the console output to see the custom logger in action!", 60, 200, 20, LIGHTGRAY); - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} diff --git a/examples/core/core_input_gestures.c b/examples/core/core_input_gestures.c deleted file mode 100644 index 312e78f..0000000 --- a/examples/core/core_input_gestures.c +++ /dev/null @@ -1,119 +0,0 @@ -/******************************************************************************************* -* -* raylib [core] example - Input Gestures Detection -* -* Example originally created with raylib 1.4, last time updated with raylib 4.2 -* -* 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) 2016-2023 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -#define MAX_GESTURE_STRINGS 20 - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main(void) -{ - // Initialization - //-------------------------------------------------------------------------------------- - const int screenWidth = 800; - const int screenHeight = 450; - - InitWindow(screenWidth, screenHeight, "raylib [core] example - input gestures"); - - Vector2 touchPosition = { 0, 0 }; - Rectangle touchArea = { 220, 10, screenWidth - 230.0f, screenHeight - 20.0f }; - - int gesturesCount = 0; - char gestureStrings[MAX_GESTURE_STRINGS][32]; - - int currentGesture = GESTURE_NONE; - int lastGesture = GESTURE_NONE; - - //SetGesturesEnabled(0b0000000000001001); // Enable only some gestures to be detected - - 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 - //---------------------------------------------------------------------------------- - lastGesture = currentGesture; - currentGesture = GetGestureDetected(); - touchPosition = GetTouchPosition(0); - - if (CheckCollisionPointRec(touchPosition, touchArea) && (currentGesture != GESTURE_NONE)) - { - if (currentGesture != lastGesture) - { - // Store gesture string - switch (currentGesture) - { - case GESTURE_TAP: TextCopy(gestureStrings[gesturesCount], "GESTURE TAP"); break; - case GESTURE_DOUBLETAP: TextCopy(gestureStrings[gesturesCount], "GESTURE DOUBLETAP"); break; - case GESTURE_HOLD: TextCopy(gestureStrings[gesturesCount], "GESTURE HOLD"); break; - case GESTURE_DRAG: TextCopy(gestureStrings[gesturesCount], "GESTURE DRAG"); break; - case GESTURE_SWIPE_RIGHT: TextCopy(gestureStrings[gesturesCount], "GESTURE SWIPE RIGHT"); break; - case GESTURE_SWIPE_LEFT: TextCopy(gestureStrings[gesturesCount], "GESTURE SWIPE LEFT"); break; - case GESTURE_SWIPE_UP: TextCopy(gestureStrings[gesturesCount], "GESTURE SWIPE UP"); break; - case GESTURE_SWIPE_DOWN: TextCopy(gestureStrings[gesturesCount], "GESTURE SWIPE DOWN"); break; - case GESTURE_PINCH_IN: TextCopy(gestureStrings[gesturesCount], "GESTURE PINCH IN"); break; - case GESTURE_PINCH_OUT: TextCopy(gestureStrings[gesturesCount], "GESTURE PINCH OUT"); break; - default: break; - } - - gesturesCount++; - - // Reset gestures strings - if (gesturesCount >= MAX_GESTURE_STRINGS) - { - for (int i = 0; i < MAX_GESTURE_STRINGS; i++) TextCopy(gestureStrings[i], "\0"); - - gesturesCount = 0; - } - } - } - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - DrawRectangleRec(touchArea, GRAY); - DrawRectangle(225, 15, screenWidth - 240, screenHeight - 30, RAYWHITE); - - DrawText("GESTURES TEST AREA", screenWidth - 270, screenHeight - 40, 20, Fade(GRAY, 0.5f)); - - for (int i = 0; i < gesturesCount; i++) - { - if (i%2 == 0) DrawRectangle(10, 30 + 20*i, 200, 20, Fade(LIGHTGRAY, 0.5f)); - else DrawRectangle(10, 30 + 20*i, 200, 20, Fade(LIGHTGRAY, 0.3f)); - - if (i < gesturesCount - 1) DrawText(gestureStrings[i], 35, 36 + 20*i, 10, DARKGRAY); - else DrawText(gestureStrings[i], 35, 36 + 20*i, 10, MAROON); - } - - DrawRectangleLines(10, 29, 200, screenHeight - 50, GRAY); - DrawText("DETECTED GESTURES", 50, 15, 10, GRAY); - - if (currentGesture != GESTURE_NONE) DrawCircleV(touchPosition, 30, MAROON); - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- -} \ No newline at end of file diff --git a/examples/core/core_input_multitouch.c b/examples/core/core_input_multitouch.c deleted file mode 100644 index 37817e5..0000000 --- a/examples/core/core_input_multitouch.c +++ /dev/null @@ -1,79 +0,0 @@ -/******************************************************************************************* -* -* raylib [core] example - Input multitouch -* -* Example originally created with raylib 2.1, last time updated with raylib 2.5 -* -* Example contributed by Berni (@Berni8k) 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) 2019-2023 Berni (@Berni8k) and Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -#define MAX_TOUCH_POINTS 10 - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main(void) -{ - // Initialization - //-------------------------------------------------------------------------------------- - const int screenWidth = 800; - const int screenHeight = 450; - - InitWindow(screenWidth, screenHeight, "raylib [core] example - input multitouch"); - - Vector2 touchPositions[MAX_TOUCH_POINTS] = { 0 }; - - 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 - //---------------------------------------------------------------------------------- - // Get the touch point count ( how many fingers are touching the screen ) - int tCount = GetTouchPointCount(); - // Clamp touch points available ( set the maximum touch points allowed ) - if(tCount > MAX_TOUCH_POINTS) tCount = MAX_TOUCH_POINTS; - // Get touch points positions - for (int i = 0; i < tCount; ++i) touchPositions[i] = GetTouchPosition(i); - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - for (int i = 0; i < tCount; ++i) - { - // Make sure point is not (0, 0) as this means there is no touch for it - if ((touchPositions[i].x > 0) && (touchPositions[i].y > 0)) - { - // Draw circle and touch index number - DrawCircleV(touchPositions[i], 34, ORANGE); - DrawText(TextFormat("%d", i), (int)touchPositions[i].x - 10, (int)touchPositions[i].y - 70, 40, BLACK); - } - } - - DrawText("touch the screen at multiple locations to get multiple balls", 10, 10, 20, DARKGRAY); - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} diff --git a/examples/core/core_random_values.c b/examples/core/core_random_values.c deleted file mode 100644 index c2225bc..0000000 --- a/examples/core/core_random_values.c +++ /dev/null @@ -1,72 +0,0 @@ -/******************************************************************************************* -* -* raylib [core] example - Generate random values -* -* Example originally created with raylib 1.1, last time updated with raylib 1.1 -* -* 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) 2014-2023 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main(void) -{ - // Initialization - //-------------------------------------------------------------------------------------- - const int screenWidth = 800; - const int screenHeight = 450; - - InitWindow(screenWidth, screenHeight, "raylib [core] example - generate random values"); - - // SetRandomSeed(0xaabbccff); // Set a custom random seed if desired, by default: "time(NULL)" - - int randValue = GetRandomValue(-8, 5); // Get a random integer number between -8 and 5 (both included) - - int framesCounter = 0; // Variable used to count frames - - 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 - //---------------------------------------------------------------------------------- - framesCounter++; - - // Every two seconds (120 frames) a new random value is generated - if (((framesCounter/120)%2) == 1) - { - randValue = GetRandomValue(-8, 5); - framesCounter = 0; - } - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - DrawText("Every 2 seconds a new random value is generated:", 130, 100, 20, MAROON); - - DrawText(TextFormat("%i", randValue), 360, 180, 80, LIGHTGRAY); - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} \ No newline at end of file diff --git a/examples/core/core_scissor_test.c b/examples/core/core_scissor_test.c deleted file mode 100644 index c2b853c..0000000 --- a/examples/core/core_scissor_test.c +++ /dev/null @@ -1,76 +0,0 @@ -/******************************************************************************************* -* -* raylib [core] example - Scissor test -* -* Example originally created with raylib 2.5, last time updated with raylib 3.0 -* -* Example contributed by Chris Dill (@MysteriousSpace) 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) 2019-2023 Chris Dill (@MysteriousSpace) -* -********************************************************************************************/ - -#include "raylib.h" - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main(void) -{ - // Initialization - //-------------------------------------------------------------------------------------- - const int screenWidth = 800; - const int screenHeight = 450; - - InitWindow(screenWidth, screenHeight, "raylib [core] example - scissor test"); - - Rectangle scissorArea = { 0, 0, 300, 300 }; - bool scissorMode = true; - - 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 - //---------------------------------------------------------------------------------- - if (IsKeyPressed(KEY_S)) scissorMode = !scissorMode; - - // Centre the scissor area around the mouse position - scissorArea.x = GetMouseX() - scissorArea.width/2; - scissorArea.y = GetMouseY() - scissorArea.height/2; - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - if (scissorMode) BeginScissorMode((int)scissorArea.x, (int)scissorArea.y, (int)scissorArea.width, (int)scissorArea.height); - - // Draw full screen rectangle and some text - // NOTE: Only part defined by scissor area will be rendered - DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), RED); - DrawText("Move the mouse around to reveal this text!", 190, 200, 20, LIGHTGRAY); - - if (scissorMode) EndScissorMode(); - - DrawRectangleLinesEx(scissorArea, 1, BLACK); - DrawText("Press S to toggle scissor test", 10, 10, 20, BLACK); - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} diff --git a/examples/core/core_smooth_pixelperfect.c b/examples/core/core_smooth_pixelperfect.c deleted file mode 100644 index 776706c..0000000 --- a/examples/core/core_smooth_pixelperfect.c +++ /dev/null @@ -1,122 +0,0 @@ -/******************************************************************************************* -* -* raylib [core] example - smooth pixel-perfect camera -* -* Example originally created with raylib 3.7, last time updated with raylib 4.0 -* -* Example contributed by Giancamillo Alessandroni (@NotManyIdeasDev) 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) 2021-2023 Giancamillo Alessandroni (@NotManyIdeasDev) and Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -#include // Required for: sinf(), cosf() - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main(void) -{ - // Initialization - //-------------------------------------------------------------------------------------- - const int screenWidth = 800; - const int screenHeight = 450; - - const int virtualScreenWidth = 160; - const int virtualScreenHeight = 90; - - const float virtualRatio = (float)screenWidth/(float)virtualScreenWidth; - - InitWindow(screenWidth, screenHeight, "raylib [core] example - smooth pixel-perfect camera"); - - Camera2D worldSpaceCamera = { 0 }; // Game world camera - worldSpaceCamera.zoom = 1.0f; - - Camera2D screenSpaceCamera = { 0 }; // Smoothing camera - screenSpaceCamera.zoom = 1.0f; - - RenderTexture2D target = LoadRenderTexture(virtualScreenWidth, virtualScreenHeight); // This is where we'll draw all our objects. - - Rectangle rec01 = { 70.0f, 35.0f, 20.0f, 20.0f }; - Rectangle rec02 = { 90.0f, 55.0f, 30.0f, 10.0f }; - Rectangle rec03 = { 80.0f, 65.0f, 15.0f, 25.0f }; - - // The target's height is flipped (in the source Rectangle), due to OpenGL reasons - Rectangle sourceRec = { 0.0f, 0.0f, (float)target.texture.width, -(float)target.texture.height }; - Rectangle destRec = { -virtualRatio, -virtualRatio, screenWidth + (virtualRatio*2), screenHeight + (virtualRatio*2) }; - - Vector2 origin = { 0.0f, 0.0f }; - - float rotation = 0.0f; - - float cameraX = 0.0f; - float cameraY = 0.0f; - - SetTargetFPS(60); - //-------------------------------------------------------------------------------------- - - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update - //---------------------------------------------------------------------------------- - rotation += 60.0f*GetFrameTime(); // Rotate the rectangles, 60 degrees per second - - // Make the camera move to demonstrate the effect - cameraX = (sinf(GetTime())*50.0f) - 10.0f; - cameraY = cosf(GetTime())*30.0f; - - // Set the camera's target to the values computed above - screenSpaceCamera.target = (Vector2){ cameraX, cameraY }; - - // Round worldSpace coordinates, keep decimals into screenSpace coordinates - worldSpaceCamera.target.x = (int)screenSpaceCamera.target.x; - screenSpaceCamera.target.x -= worldSpaceCamera.target.x; - screenSpaceCamera.target.x *= virtualRatio; - - worldSpaceCamera.target.y = (int)screenSpaceCamera.target.y; - screenSpaceCamera.target.y -= worldSpaceCamera.target.y; - screenSpaceCamera.target.y *= virtualRatio; - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginTextureMode(target); - ClearBackground(RAYWHITE); - - BeginMode2D(worldSpaceCamera); - DrawRectanglePro(rec01, origin, rotation, BLACK); - DrawRectanglePro(rec02, origin, -rotation, RED); - DrawRectanglePro(rec03, origin, rotation + 45.0f, BLUE); - EndMode2D(); - EndTextureMode(); - - BeginDrawing(); - ClearBackground(RED); - - BeginMode2D(screenSpaceCamera); - DrawTexturePro(target.texture, sourceRec, destRec, origin, 0.0f, WHITE); - EndMode2D(); - - DrawText(TextFormat("Screen resolution: %ix%i", screenWidth, screenHeight), 10, 10, 20, DARKBLUE); - DrawText(TextFormat("World resolution: %ix%i", virtualScreenWidth, virtualScreenHeight), 10, 40, 20, DARKGREEN); - DrawFPS(GetScreenWidth() - 95, 10); - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - UnloadRenderTexture(target); // Unload render texture - - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} \ No newline at end of file diff --git a/examples/core/core_split_screen.c b/examples/core/core_split_screen.c deleted file mode 100644 index 50cfcf7..0000000 --- a/examples/core/core_split_screen.c +++ /dev/null @@ -1,151 +0,0 @@ -/******************************************************************************************* -* -* raylib [core] example - split screen -* -* Example originally created with raylib 3.7, last time updated with raylib 4.0 -* -* Example contributed by Jeffery Myers (@JeffM2501) 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) 2021-2023 Jeffery Myers (@JeffM2501) -* -********************************************************************************************/ - -#include "raylib.h" - -Camera cameraPlayer1 = { 0 }; -Camera cameraPlayer2 = { 0 }; - -// Scene drawing -void DrawScene(void) -{ - int count = 5; - float spacing = 4; - - // Grid of cube trees on a plane to make a "world" - DrawPlane((Vector3){ 0, 0, 0 }, (Vector2){ 50, 50 }, BEIGE); // Simple world plane - - for (float x = -count*spacing; x <= count*spacing; x += spacing) - { - for (float z = -count*spacing; z <= count*spacing; z += spacing) - { - DrawCube((Vector3) { x, 1.5f, z }, 1, 1, 1, LIME); - DrawCube((Vector3) { x, 0.5f, z }, 0.25f, 1, 0.25f, BROWN); - } - } - - // Draw a cube at each player's position - DrawCube(cameraPlayer1.position, 1, 1, 1, RED); - DrawCube(cameraPlayer2.position, 1, 1, 1, BLUE); -} - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main(void) -{ - // Initialization - //-------------------------------------------------------------------------------------- - const int screenWidth = 800; - const int screenHeight = 450; - - InitWindow(screenWidth, screenHeight, "raylib [core] example - split screen"); - - // Setup player 1 camera and screen - cameraPlayer1.fovy = 45.0f; - cameraPlayer1.up.y = 1.0f; - cameraPlayer1.target.y = 1.0f; - cameraPlayer1.position.z = -3.0f; - cameraPlayer1.position.y = 1.0f; - - RenderTexture screenPlayer1 = LoadRenderTexture(screenWidth/2, screenHeight); - - // Setup player two camera and screen - cameraPlayer2.fovy = 45.0f; - cameraPlayer2.up.y = 1.0f; - cameraPlayer2.target.y = 3.0f; - cameraPlayer2.position.x = -3.0f; - cameraPlayer2.position.y = 3.0f; - - RenderTexture screenPlayer2 = LoadRenderTexture(screenWidth / 2, screenHeight); - - // Build a flipped rectangle the size of the split view to use for drawing later - Rectangle splitScreenRect = { 0.0f, 0.0f, (float)screenPlayer1.texture.width, (float)-screenPlayer1.texture.height }; - - 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 - //---------------------------------------------------------------------------------- - // If anyone moves this frame, how far will they move based on the time since the last frame - // this moves thigns at 10 world units per second, regardless of the actual FPS - float offsetThisFrame = 10.0f*GetFrameTime(); - - // Move Player1 forward and backwards (no turning) - if (IsKeyDown(KEY_W)) - { - cameraPlayer1.position.z += offsetThisFrame; - cameraPlayer1.target.z += offsetThisFrame; - } - else if (IsKeyDown(KEY_S)) - { - cameraPlayer1.position.z -= offsetThisFrame; - cameraPlayer1.target.z -= offsetThisFrame; - } - - // Move Player2 forward and backwards (no turning) - if (IsKeyDown(KEY_UP)) - { - cameraPlayer2.position.x += offsetThisFrame; - cameraPlayer2.target.x += offsetThisFrame; - } - else if (IsKeyDown(KEY_DOWN)) - { - cameraPlayer2.position.x -= offsetThisFrame; - cameraPlayer2.target.x -= offsetThisFrame; - } - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - // Draw Player1 view to the render texture - BeginTextureMode(screenPlayer1); - ClearBackground(SKYBLUE); - BeginMode3D(cameraPlayer1); - DrawScene(); - EndMode3D(); - DrawText("PLAYER1 W/S to move", 10, 10, 20, RED); - EndTextureMode(); - - // Draw Player2 view to the render texture - BeginTextureMode(screenPlayer2); - ClearBackground(SKYBLUE); - BeginMode3D(cameraPlayer2); - DrawScene(); - EndMode3D(); - DrawText("PLAYER2 UP/DOWN to move", 10, 10, 20, BLUE); - EndTextureMode(); - - // Draw both views render textures to the screen side by side - BeginDrawing(); - ClearBackground(BLACK); - DrawTextureRec(screenPlayer1.texture, splitScreenRect, (Vector2){ 0, 0 }, WHITE); - DrawTextureRec(screenPlayer2.texture, splitScreenRect, (Vector2){ screenWidth/2.0f, 0 }, WHITE); - EndDrawing(); - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - UnloadRenderTexture(screenPlayer1); // Unload render texture - UnloadRenderTexture(screenPlayer2); // Unload render texture - - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} \ No newline at end of file diff --git a/examples/core/core_window_flags.c b/examples/core/core_window_flags.c deleted file mode 100644 index b1cbb1b..0000000 --- a/examples/core/core_window_flags.c +++ /dev/null @@ -1,196 +0,0 @@ -/******************************************************************************************* -* -* raylib [core] example - window flags -* -* Example originally created with raylib 3.5, last time updated with raylib 3.5 -* -* 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) 2020-2023 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main(void) -{ - // Initialization - //--------------------------------------------------------- - const int screenWidth = 800; - const int screenHeight = 450; - - // Possible window flags - /* - FLAG_VSYNC_HINT - FLAG_FULLSCREEN_MODE -> not working properly -> wrong scaling! - FLAG_WINDOW_RESIZABLE - FLAG_WINDOW_UNDECORATED - FLAG_WINDOW_TRANSPARENT - FLAG_WINDOW_HIDDEN - FLAG_WINDOW_MINIMIZED -> Not supported on window creation - FLAG_WINDOW_MAXIMIZED -> Not supported on window creation - FLAG_WINDOW_UNFOCUSED - FLAG_WINDOW_TOPMOST - FLAG_WINDOW_HIGHDPI -> errors after minimize-resize, fb size is recalculated - FLAG_WINDOW_ALWAYS_RUN - FLAG_MSAA_4X_HINT - */ - - // Set configuration flags for window creation - //SetConfigFlags(FLAG_VSYNC_HINT | FLAG_MSAA_4X_HINT | FLAG_WINDOW_HIGHDPI); - InitWindow(screenWidth, screenHeight, "raylib [core] example - window flags"); - - Vector2 ballPosition = { GetScreenWidth() / 2.0f, GetScreenHeight() / 2.0f }; - Vector2 ballSpeed = { 5.0f, 4.0f }; - float ballRadius = 20; - - int framesCounter = 0; - - //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 - //----------------------------------------------------- - if (IsKeyPressed(KEY_F)) ToggleFullscreen(); // modifies window size when scaling! - - if (IsKeyPressed(KEY_R)) - { - if (IsWindowState(FLAG_WINDOW_RESIZABLE)) ClearWindowState(FLAG_WINDOW_RESIZABLE); - else SetWindowState(FLAG_WINDOW_RESIZABLE); - } - - if (IsKeyPressed(KEY_D)) - { - if (IsWindowState(FLAG_WINDOW_UNDECORATED)) ClearWindowState(FLAG_WINDOW_UNDECORATED); - else SetWindowState(FLAG_WINDOW_UNDECORATED); - } - - if (IsKeyPressed(KEY_H)) - { - if (!IsWindowState(FLAG_WINDOW_HIDDEN)) SetWindowState(FLAG_WINDOW_HIDDEN); - - framesCounter = 0; - } - - if (IsWindowState(FLAG_WINDOW_HIDDEN)) - { - framesCounter++; - if (framesCounter >= 240) ClearWindowState(FLAG_WINDOW_HIDDEN); // Show window after 3 seconds - } - - if (IsKeyPressed(KEY_N)) - { - if (!IsWindowState(FLAG_WINDOW_MINIMIZED)) MinimizeWindow(); - - framesCounter = 0; - } - - if (IsWindowState(FLAG_WINDOW_MINIMIZED)) - { - framesCounter++; - if (framesCounter >= 240) RestoreWindow(); // Restore window after 3 seconds - } - - if (IsKeyPressed(KEY_M)) - { - // NOTE: Requires FLAG_WINDOW_RESIZABLE enabled! - if (IsWindowState(FLAG_WINDOW_MAXIMIZED)) RestoreWindow(); - else MaximizeWindow(); - } - - if (IsKeyPressed(KEY_U)) - { - if (IsWindowState(FLAG_WINDOW_UNFOCUSED)) ClearWindowState(FLAG_WINDOW_UNFOCUSED); - else SetWindowState(FLAG_WINDOW_UNFOCUSED); - } - - if (IsKeyPressed(KEY_T)) - { - if (IsWindowState(FLAG_WINDOW_TOPMOST)) ClearWindowState(FLAG_WINDOW_TOPMOST); - else SetWindowState(FLAG_WINDOW_TOPMOST); - } - - if (IsKeyPressed(KEY_A)) - { - if (IsWindowState(FLAG_WINDOW_ALWAYS_RUN)) ClearWindowState(FLAG_WINDOW_ALWAYS_RUN); - else SetWindowState(FLAG_WINDOW_ALWAYS_RUN); - } - - if (IsKeyPressed(KEY_V)) - { - if (IsWindowState(FLAG_VSYNC_HINT)) ClearWindowState(FLAG_VSYNC_HINT); - else SetWindowState(FLAG_VSYNC_HINT); - } - - // Bouncing ball logic - ballPosition.x += ballSpeed.x; - ballPosition.y += ballSpeed.y; - if ((ballPosition.x >= (GetScreenWidth() - ballRadius)) || (ballPosition.x <= ballRadius)) ballSpeed.x *= -1.0f; - if ((ballPosition.y >= (GetScreenHeight() - ballRadius)) || (ballPosition.y <= ballRadius)) ballSpeed.y *= -1.0f; - //----------------------------------------------------- - - // Draw - //----------------------------------------------------- - BeginDrawing(); - - if (IsWindowState(FLAG_WINDOW_TRANSPARENT)) ClearBackground(BLANK); - else ClearBackground(RAYWHITE); - - DrawCircleV(ballPosition, ballRadius, MAROON); - DrawRectangleLinesEx((Rectangle) { 0, 0, (float)GetScreenWidth(), (float)GetScreenHeight() }, 4, RAYWHITE); - - DrawCircleV(GetMousePosition(), 10, DARKBLUE); - - DrawFPS(10, 10); - - DrawText(TextFormat("Screen Size: [%i, %i]", GetScreenWidth(), GetScreenHeight()), 10, 40, 10, GREEN); - - // Draw window state info - DrawText("Following flags can be set after window creation:", 10, 60, 10, GRAY); - if (IsWindowState(FLAG_FULLSCREEN_MODE)) DrawText("[F] FLAG_FULLSCREEN_MODE: on", 10, 80, 10, LIME); - else DrawText("[F] FLAG_FULLSCREEN_MODE: off", 10, 80, 10, MAROON); - if (IsWindowState(FLAG_WINDOW_RESIZABLE)) DrawText("[R] FLAG_WINDOW_RESIZABLE: on", 10, 100, 10, LIME); - else DrawText("[R] FLAG_WINDOW_RESIZABLE: off", 10, 100, 10, MAROON); - if (IsWindowState(FLAG_WINDOW_UNDECORATED)) DrawText("[D] FLAG_WINDOW_UNDECORATED: on", 10, 120, 10, LIME); - else DrawText("[D] FLAG_WINDOW_UNDECORATED: off", 10, 120, 10, MAROON); - if (IsWindowState(FLAG_WINDOW_HIDDEN)) DrawText("[H] FLAG_WINDOW_HIDDEN: on", 10, 140, 10, LIME); - else DrawText("[H] FLAG_WINDOW_HIDDEN: off", 10, 140, 10, MAROON); - if (IsWindowState(FLAG_WINDOW_MINIMIZED)) DrawText("[N] FLAG_WINDOW_MINIMIZED: on", 10, 160, 10, LIME); - else DrawText("[N] FLAG_WINDOW_MINIMIZED: off", 10, 160, 10, MAROON); - if (IsWindowState(FLAG_WINDOW_MAXIMIZED)) DrawText("[M] FLAG_WINDOW_MAXIMIZED: on", 10, 180, 10, LIME); - else DrawText("[M] FLAG_WINDOW_MAXIMIZED: off", 10, 180, 10, MAROON); - if (IsWindowState(FLAG_WINDOW_UNFOCUSED)) DrawText("[G] FLAG_WINDOW_UNFOCUSED: on", 10, 200, 10, LIME); - else DrawText("[U] FLAG_WINDOW_UNFOCUSED: off", 10, 200, 10, MAROON); - if (IsWindowState(FLAG_WINDOW_TOPMOST)) DrawText("[T] FLAG_WINDOW_TOPMOST: on", 10, 220, 10, LIME); - else DrawText("[T] FLAG_WINDOW_TOPMOST: off", 10, 220, 10, MAROON); - if (IsWindowState(FLAG_WINDOW_ALWAYS_RUN)) DrawText("[A] FLAG_WINDOW_ALWAYS_RUN: on", 10, 240, 10, LIME); - else DrawText("[A] FLAG_WINDOW_ALWAYS_RUN: off", 10, 240, 10, MAROON); - if (IsWindowState(FLAG_VSYNC_HINT)) DrawText("[V] FLAG_VSYNC_HINT: on", 10, 260, 10, LIME); - else DrawText("[V] FLAG_VSYNC_HINT: off", 10, 260, 10, MAROON); - - DrawText("Following flags can only be set before window creation:", 10, 300, 10, GRAY); - if (IsWindowState(FLAG_WINDOW_HIGHDPI)) DrawText("FLAG_WINDOW_HIGHDPI: on", 10, 320, 10, LIME); - else DrawText("FLAG_WINDOW_HIGHDPI: off", 10, 320, 10, MAROON); - if (IsWindowState(FLAG_WINDOW_TRANSPARENT)) DrawText("FLAG_WINDOW_TRANSPARENT: on", 10, 340, 10, LIME); - else DrawText("FLAG_WINDOW_TRANSPARENT: off", 10, 340, 10, MAROON); - if (IsWindowState(FLAG_MSAA_4X_HINT)) DrawText("FLAG_MSAA_4X_HINT: on", 10, 360, 10, LIME); - else DrawText("FLAG_MSAA_4X_HINT: off", 10, 360, 10, MAROON); - - EndDrawing(); - //----------------------------------------------------- - } - - // De-Initialization - //--------------------------------------------------------- - CloseWindow(); // Close window and OpenGL context - //---------------------------------------------------------- - - return 0; -} diff --git a/examples/core/core_window_letterbox.c b/examples/core/core_window_letterbox.c deleted file mode 100644 index 751fb14..0000000 --- a/examples/core/core_window_letterbox.c +++ /dev/null @@ -1,107 +0,0 @@ -/******************************************************************************************* -* -* raylib [core] example - window scale letterbox (and virtual mouse) -* -* Example originally created with raylib 2.5, last time updated with raylib 4.0 -* -* Example contributed by Anata (@anatagawa) 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) 2019-2023 Anata (@anatagawa) and Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -#include "raymath.h" // Required for: Vector2Clamp() - -#define MAX(a, b) ((a)>(b)? (a) : (b)) -#define MIN(a, b) ((a)<(b)? (a) : (b)) - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main(void) -{ - const int windowWidth = 800; - const int windowHeight = 450; - - // Enable config flags for resizable window and vertical synchro - SetConfigFlags(FLAG_WINDOW_RESIZABLE | FLAG_VSYNC_HINT); - InitWindow(windowWidth, windowHeight, "raylib [core] example - window scale letterbox"); - SetWindowMinSize(320, 240); - - int gameScreenWidth = 640; - int gameScreenHeight = 480; - - // Render texture initialization, used to hold the rendering result so we can easily resize it - RenderTexture2D target = LoadRenderTexture(gameScreenWidth, gameScreenHeight); - SetTextureFilter(target.texture, TEXTURE_FILTER_BILINEAR); // Texture scale filter to use - - Color colors[10] = { 0 }; - for (int i = 0; i < 10; i++) colors[i] = (Color){ GetRandomValue(100, 250), GetRandomValue(50, 150), GetRandomValue(10, 100), 255 }; - - 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 - //---------------------------------------------------------------------------------- - // Compute required framebuffer scaling - float scale = MIN((float)GetScreenWidth()/gameScreenWidth, (float)GetScreenHeight()/gameScreenHeight); - - if (IsKeyPressed(KEY_SPACE)) - { - // Recalculate random colors for the bars - for (int i = 0; i < 10; i++) colors[i] = (Color){ GetRandomValue(100, 250), GetRandomValue(50, 150), GetRandomValue(10, 100), 255 }; - } - - // Update virtual mouse (clamped mouse value behind game screen) - Vector2 mouse = GetMousePosition(); - Vector2 virtualMouse = { 0 }; - virtualMouse.x = (mouse.x - (GetScreenWidth() - (gameScreenWidth*scale))*0.5f)/scale; - virtualMouse.y = (mouse.y - (GetScreenHeight() - (gameScreenHeight*scale))*0.5f)/scale; - virtualMouse = Vector2Clamp(virtualMouse, (Vector2){ 0, 0 }, (Vector2){ (float)gameScreenWidth, (float)gameScreenHeight }); - - // Apply the same transformation as the virtual mouse to the real mouse (i.e. to work with raygui) - //SetMouseOffset(-(GetScreenWidth() - (gameScreenWidth*scale))*0.5f, -(GetScreenHeight() - (gameScreenHeight*scale))*0.5f); - //SetMouseScale(1/scale, 1/scale); - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - // Draw everything in the render texture, note this will not be rendered on screen, yet - BeginTextureMode(target); - ClearBackground(RAYWHITE); // Clear render texture background color - - for (int i = 0; i < 10; i++) DrawRectangle(0, (gameScreenHeight/10)*i, gameScreenWidth, gameScreenHeight/10, colors[i]); - - DrawText("If executed inside a window,\nyou can resize the window,\nand see the screen scaling!", 10, 25, 20, WHITE); - DrawText(TextFormat("Default Mouse: [%i , %i]", (int)mouse.x, (int)mouse.y), 350, 25, 20, GREEN); - DrawText(TextFormat("Virtual Mouse: [%i , %i]", (int)virtualMouse.x, (int)virtualMouse.y), 350, 55, 20, YELLOW); - EndTextureMode(); - - BeginDrawing(); - ClearBackground(BLACK); // Clear screen background - - // Draw render texture to screen, properly scaled - DrawTexturePro(target.texture, (Rectangle){ 0.0f, 0.0f, (float)target.texture.width, (float)-target.texture.height }, - (Rectangle){ (GetScreenWidth() - ((float)gameScreenWidth*scale))*0.5f, (GetScreenHeight() - ((float)gameScreenHeight*scale))*0.5f, - (float)gameScreenWidth*scale, (float)gameScreenHeight*scale }, (Vector2){ 0, 0 }, 0.0f, WHITE); - EndDrawing(); - //-------------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - UnloadRenderTexture(target); // Unload render texture - - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} diff --git a/examples/core/core_window_should_close.c b/examples/core/core_window_should_close.c deleted file mode 100644 index f0392b0..0000000 --- a/examples/core/core_window_should_close.c +++ /dev/null @@ -1,77 +0,0 @@ -/******************************************************************************************* -* -* raylib [core] example - Window should close -* -* Example originally created with raylib 4.2, last time updated with raylib 4.2 -* -* 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) 2013-2023 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main() -{ - // Initialization - //-------------------------------------------------------------------------------------- - const int screenWidth = 800; - const int screenHeight = 450; - - InitWindow(screenWidth, screenHeight, "raylib [core] example - window should close"); - - SetExitKey(KEY_NULL); // Disable KEY_ESCAPE to close window, X-button still works - - bool exitWindowRequested = false; // Flag to request window to exit - bool exitWindow = false; // Flag to set window to exit - - SetTargetFPS(60); // Set our game to run at 60 frames-per-second - //-------------------------------------------------------------------------------------- - - // Main game loop - while (!exitWindow) - { - // Update - //---------------------------------------------------------------------------------- - // Detect if X-button or KEY_ESCAPE have been pressed to close window - if (WindowShouldClose() || IsKeyPressed(KEY_ESCAPE)) exitWindowRequested = true; - - if (exitWindowRequested) - { - // A request for close window has been issued, we can save data before closing - // or just show a message asking for confirmation - - if (IsKeyPressed(KEY_Y)) exitWindow = true; - else if (IsKeyPressed(KEY_N)) exitWindowRequested = false; - } - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - if (exitWindowRequested) - { - DrawRectangle(0, 100, screenWidth, 200, BLACK); - DrawText("Are you sure you want to exit program? [Y/N]", 40, 180, 30, WHITE); - } - else DrawText("Try to close the window to get confirmation message!", 120, 200, 20, LIGHTGRAY); - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} diff --git a/examples/core/core_world_screen.c b/examples/core/core_world_screen.c deleted file mode 100644 index 6c811a5..0000000 --- a/examples/core/core_world_screen.c +++ /dev/null @@ -1,85 +0,0 @@ -/******************************************************************************************* -* -* raylib [core] example - World to screen -* -* Example originally created with raylib 1.3, last time updated with raylib 1.4 -* -* 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) 2015-2023 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main(void) -{ - // Initialization - //-------------------------------------------------------------------------------------- - const int screenWidth = 800; - const int screenHeight = 450; - - InitWindow(screenWidth, screenHeight, "raylib [core] example - core world screen"); - - // Define the camera to look into our 3d world - Camera camera = { 0 }; - camera.position = (Vector3){ 10.0f, 10.0f, 10.0f }; // Camera position - camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point - camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) - camera.fovy = 45.0f; // Camera field-of-view Y - camera.projection = CAMERA_PERSPECTIVE; // Camera projection type - - Vector3 cubePosition = { 0.0f, 0.0f, 0.0f }; - Vector2 cubeScreenPosition = { 0.0f, 0.0f }; - - 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 - //---------------------------------------------------------------------------------- - UpdateCamera(&camera, CAMERA_THIRD_PERSON); - - // Calculate cube screen space position (with a little offset to be in top) - cubeScreenPosition = GetWorldToScreen((Vector3){cubePosition.x, cubePosition.y + 2.5f, cubePosition.z}, camera); - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - BeginMode3D(camera); - - DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED); - DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON); - - DrawGrid(10, 1.0f); - - EndMode3D(); - - DrawText("Enemy: 100 / 100", (int)cubeScreenPosition.x - MeasureText("Enemy: 100/100", 20)/2, (int)cubeScreenPosition.y, 20, BLACK); - - DrawText(TextFormat("Cube position in screen space coordinates: [%i, %i]", (int)cubeScreenPosition.x, (int)cubeScreenPosition.y), 10, 10, 20, LIME); - DrawText("Text 2d should be always on top of the cube", 10, 40, 20, GRAY); - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} \ No newline at end of file diff --git a/examples/shaders/shaders_basic_lighting2.js b/examples/shaders/js_shaders_gradient_lighting.js similarity index 100% rename from examples/shaders/shaders_basic_lighting2.js rename to examples/shaders/js_shaders_gradient_lighting.js diff --git a/examples/text/text_codepoints_loading.c b/examples/text/text_codepoints_loading.c deleted file mode 100644 index 1f3db0c..0000000 --- a/examples/text/text_codepoints_loading.c +++ /dev/null @@ -1,155 +0,0 @@ -/******************************************************************************************* -* -* raylib [text] example - Codepoints loading -* -* Example originally created with raylib 4.2, last time updated with raylib 2.5 -* -* 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) 2022-2023 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -#include // Required for: calloc(), realloc(), free() -#include // Required for: memcpy() - -// Text to be displayed, must be UTF-8 (save this code file as UTF-8) -// NOTE: It can contain all the required text for the game, -// this text will be scanned to get all the required codepoints -static char *text = "いろはにほへと ちりぬるを\nわかよたれそ つねならむ\nうゐのおくやま けふこえて\nあさきゆめみし ゑひもせす"; - -// Remove codepoint duplicates if requested -static int *CodepointRemoveDuplicates(int *codepoints, int codepointCount, int *codepointResultCount); - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main(void) -{ - // Initialization - //-------------------------------------------------------------------------------------- - const int screenWidth = 800; - const int screenHeight = 450; - - InitWindow(screenWidth, screenHeight, "raylib [text] example - codepoints loading"); - - // Get codepoints from text - int codepointCount = 0; - int *codepoints = LoadCodepoints(text, &codepointCount); - - // Removed duplicate codepoints to generate smaller font atlas - int codepointsNoDupsCount = 0; - int *codepointsNoDups = CodepointRemoveDuplicates(codepoints, codepointCount, &codepointsNoDupsCount); - UnloadCodepoints(codepoints); - - // Load font containing all the provided codepoint glyphs - // A texture font atlas is automatically generated - Font font = LoadFontEx("resources/DotGothic16-Regular.ttf", 36, codepointsNoDups, codepointsNoDupsCount); - - // Set bilinear scale filter for better font scaling - SetTextureFilter(font.texture, TEXTURE_FILTER_BILINEAR); - - // Free codepoints, atlas has already been generated - free(codepointsNoDups); - - bool showFontAtlas = false; - - int codepointSize = 0; - int codepoint = 0; - char *ptr = text; - - 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 - //---------------------------------------------------------------------------------- - if (IsKeyPressed(KEY_SPACE)) showFontAtlas = !showFontAtlas; - - // Testing code: getting next and previous codepoints on provided text - if (IsKeyPressed(KEY_RIGHT)) - { - // Get next codepoint in string and move pointer - codepoint = GetCodepointNext(ptr, &codepointSize); - ptr += codepointSize; - } - else if (IsKeyPressed(KEY_LEFT)) - { - // Get previous codepoint in string and move pointer - codepoint = GetCodepointPrevious(ptr, &codepointSize); - ptr -= codepointSize; - } - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - DrawRectangle(0, 0, GetScreenWidth(), 70, BLACK); - DrawText(TextFormat("Total codepoints contained in provided text: %i", codepointCount), 10, 10, 20, GREEN); - DrawText(TextFormat("Total codepoints required for font atlas (duplicates excluded): %i", codepointsNoDupsCount), 10, 40, 20, GREEN); - - if (showFontAtlas) - { - // Draw generated font texture atlas containing provided codepoints - DrawTexture(font.texture, 150, 100, BLACK); - DrawRectangleLines(150, 100, font.texture.width, font.texture.height, BLACK); - } - else - { - // Draw provided text with laoded font, containing all required codepoint glyphs - DrawTextEx(font, text, (Vector2) { 160, 110 }, 48, 5, BLACK); - } - - DrawText("Press SPACE to toggle font atlas view!", 10, GetScreenHeight() - 30, 20, GRAY); - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - UnloadFont(font); // Unload font - - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} - -// Remove codepoint duplicates if requested -// WARNING: This process could be a bit slow if there text to process is very long -static int *CodepointRemoveDuplicates(int *codepoints, int codepointCount, int *codepointsResultCount) -{ - int codepointsNoDupsCount = codepointCount; - int *codepointsNoDups = (int *)calloc(codepointCount, sizeof(int)); - memcpy(codepointsNoDups, codepoints, codepointCount*sizeof(int)); - - // Remove duplicates - for (int i = 0; i < codepointsNoDupsCount; i++) - { - for (int j = i + 1; j < codepointsNoDupsCount; j++) - { - if (codepointsNoDups[i] == codepointsNoDups[j]) - { - for (int k = j; k < codepointsNoDupsCount; k++) codepointsNoDups[k] = codepointsNoDups[k + 1]; - - codepointsNoDupsCount--; - j--; - } - } - } - - // NOTE: The size of codepointsNoDups is the same as original array but - // only required positions are filled (codepointsNoDupsCount) - - *codepointsResultCount = codepointsNoDupsCount; - return codepointsNoDups; -} \ No newline at end of file diff --git a/examples/text/text_draw_3d.c b/examples/text/text_draw_3d.c deleted file mode 100644 index 097e4fc..0000000 --- a/examples/text/text_draw_3d.c +++ /dev/null @@ -1,750 +0,0 @@ -/******************************************************************************************* -* -* raylib [text] example - Draw 3d -* -* NOTE: Draw a 2D text in 3D space, each letter is drawn in a quad (or 2 quads if backface is set) -* where the texture coodinates of each quad map to the texture coordinates of the glyphs -* inside the font texture. -* -* A more efficient approach, i believe, would be to render the text in a render texture and -* map that texture to a plane and render that, or maybe a shader but my method allows more -* flexibility...for example to change position of each letter individually to make somethink -* like a wavy text effect. -* -* Special thanks to: -* @Nighten for the DrawTextStyle() code https://github.com/NightenDushi/Raylib_DrawTextStyle -* Chris Camacho (codifies - http://bedroomcoders.co.uk/) for the alpha discard shader -* -* Example originally created with raylib 3.5, last time updated with raylib 4.0 -* -* Example contributed by Vlad Adrian (@demizdor) 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) 2021-2023 Vlad Adrian (@demizdor) -* -********************************************************************************************/ - -#include "raylib.h" -#include "rlgl.h" - -#include // Required for: NULL -#include // Required for: sinf() - -// To make it work with the older RLGL module just comment the line below -#define RAYLIB_NEW_RLGL - -//-------------------------------------------------------------------------------------- -// Globals -//-------------------------------------------------------------------------------------- -#define LETTER_BOUNDRY_SIZE 0.25f -#define TEXT_MAX_LAYERS 32 -#define LETTER_BOUNDRY_COLOR VIOLET - -bool SHOW_LETTER_BOUNDRY = false; -bool SHOW_TEXT_BOUNDRY = false; - -//-------------------------------------------------------------------------------------- -// Data Types definition -//-------------------------------------------------------------------------------------- - -// Configuration structure for waving the text -typedef struct WaveTextConfig { - Vector3 waveRange; - Vector3 waveSpeed; - Vector3 waveOffset; -} WaveTextConfig; - -//-------------------------------------------------------------------------------------- -// Module Functions Declaration -//-------------------------------------------------------------------------------------- -// Draw a codepoint in 3D space -static void DrawTextCodepoint3D(Font font, int codepoint, Vector3 position, float fontSize, bool backface, Color tint); -// Draw a 2D text in 3D space -static void DrawText3D(Font font, const char *text, Vector3 position, float fontSize, float fontSpacing, float lineSpacing, bool backface, Color tint); -// Measure a text in 3D. For some reason `MeasureTextEx()` just doesn't seem to work so i had to use this instead. -static Vector3 MeasureText3D(Font font, const char *text, float fontSize, float fontSpacing, float lineSpacing); - -// Draw a 2D text in 3D space and wave the parts that start with `~~` and end with `~~`. -// This is a modified version of the original code by @Nighten found here https://github.com/NightenDushi/Raylib_DrawTextStyle -static void DrawTextWave3D(Font font, const char *text, Vector3 position, float fontSize, float fontSpacing, float lineSpacing, bool backface, WaveTextConfig *config, float time, Color tint); -// Measure a text in 3D ignoring the `~~` chars. -static Vector3 MeasureTextWave3D(Font font, const char *text, float fontSize, float fontSpacing, float lineSpacing); -// Generates a nice color with a random hue -static Color GenerateRandomColor(float s, float v); - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main(void) -{ - // Initialization - //-------------------------------------------------------------------------------------- - const int screenWidth = 800; - const int screenHeight = 450; - - SetConfigFlags(FLAG_MSAA_4X_HINT|FLAG_VSYNC_HINT); - InitWindow(screenWidth, screenHeight, "raylib [text] example - draw 2D text in 3D"); - - bool spin = true; // Spin the camera? - bool multicolor = false; // Multicolor mode - - // Define the camera to look into our 3d world - Camera3D camera = { 0 }; - camera.position = (Vector3){ -10.0f, 15.0f, -10.0f }; // Camera position - camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point - camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) - camera.fovy = 45.0f; // Camera field-of-view Y - camera.projection = CAMERA_PERSPECTIVE; // Camera projection type - - int camera_mode = CAMERA_ORBITAL; - - Vector3 cubePosition = { 0.0f, 1.0f, 0.0f }; - Vector3 cubeSize = { 2.0f, 2.0f, 2.0f }; - - // Use the default font - Font font = GetFontDefault(); - float fontSize = 8.0f; - float fontSpacing = 0.5f; - float lineSpacing = -1.0f; - - // Set the text (using markdown!) - char text[64] = "Hello ~~World~~ in 3D!"; - Vector3 tbox = {0}; - int layers = 1; - int quads = 0; - float layerDistance = 0.01f; - - WaveTextConfig wcfg; - wcfg.waveSpeed.x = wcfg.waveSpeed.y = 3.0f; wcfg.waveSpeed.z = 0.5f; - wcfg.waveOffset.x = wcfg.waveOffset.y = wcfg.waveOffset.z = 0.35f; - wcfg.waveRange.x = wcfg.waveRange.y = wcfg.waveRange.z = 0.45f; - - float time = 0.0f; - - // Setup a light and dark color - Color light = MAROON; - Color dark = RED; - - // Load the alpha discard shader - Shader alphaDiscard = LoadShader(NULL, "resources/shaders/glsl330/alpha_discard.fs"); - - // Array filled with multiple random colors (when multicolor mode is set) - Color multi[TEXT_MAX_LAYERS] = {0}; - - 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 - //---------------------------------------------------------------------------------- - UpdateCamera(&camera, camera_mode); - - // Handle font files dropped - if (IsFileDropped()) - { - FilePathList droppedFiles = LoadDroppedFiles(); - - // NOTE: We only support first ttf file dropped - if (IsFileExtension(droppedFiles.paths[0], ".ttf")) - { - UnloadFont(font); - font = LoadFontEx(droppedFiles.paths[0], (int)fontSize, 0, 0); - } - else if (IsFileExtension(droppedFiles.paths[0], ".fnt")) - { - UnloadFont(font); - font = LoadFont(droppedFiles.paths[0]); - fontSize = (float)font.baseSize; - } - - UnloadDroppedFiles(droppedFiles); // Unload filepaths from memory - } - - // Handle Events - if (IsKeyPressed(KEY_F1)) SHOW_LETTER_BOUNDRY = !SHOW_LETTER_BOUNDRY; - if (IsKeyPressed(KEY_F2)) SHOW_TEXT_BOUNDRY = !SHOW_TEXT_BOUNDRY; - if (IsKeyPressed(KEY_F3)) - { - // Handle camera change - spin = !spin; - // we need to reset the camera when changing modes - camera = (Camera3D){ 0 }; - camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point - camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) - camera.fovy = 45.0f; // Camera field-of-view Y - camera.projection = CAMERA_PERSPECTIVE; // Camera mode type - - if (spin) - { - camera.position = (Vector3){ -10.0f, 15.0f, -10.0f }; // Camera position - camera_mode = CAMERA_ORBITAL; - } - else - { - camera.position = (Vector3){ 10.0f, 10.0f, -10.0f }; // Camera position - camera_mode = CAMERA_FREE; - } - } - - // Handle clicking the cube - if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) - { - Ray ray = GetMouseRay(GetMousePosition(), camera); - - // Check collision between ray and box - RayCollision collision = GetRayCollisionBox(ray, - (BoundingBox){(Vector3){ cubePosition.x - cubeSize.x/2, cubePosition.y - cubeSize.y/2, cubePosition.z - cubeSize.z/2 }, - (Vector3){ cubePosition.x + cubeSize.x/2, cubePosition.y + cubeSize.y/2, cubePosition.z + cubeSize.z/2 }}); - if (collision.hit) - { - // Generate new random colors - light = GenerateRandomColor(0.5f, 0.78f); - dark = GenerateRandomColor(0.4f, 0.58f); - } - } - - // Handle text layers changes - if (IsKeyPressed(KEY_HOME)) { if (layers > 1) --layers; } - else if (IsKeyPressed(KEY_END)) { if (layers < TEXT_MAX_LAYERS) ++layers; } - - // Handle text changes - if (IsKeyPressed(KEY_LEFT)) fontSize -= 0.5f; - else if (IsKeyPressed(KEY_RIGHT)) fontSize += 0.5f; - else if (IsKeyPressed(KEY_UP)) fontSpacing -= 0.1f; - else if (IsKeyPressed(KEY_DOWN)) fontSpacing += 0.1f; - else if (IsKeyPressed(KEY_PAGE_UP)) lineSpacing -= 0.1f; - else if (IsKeyPressed(KEY_PAGE_DOWN)) lineSpacing += 0.1f; - else if (IsKeyDown(KEY_INSERT)) layerDistance -= 0.001f; - else if (IsKeyDown(KEY_DELETE)) layerDistance += 0.001f; - else if (IsKeyPressed(KEY_TAB)) - { - multicolor = !multicolor; // Enable /disable multicolor mode - - if (multicolor) - { - // Fill color array with random colors - for (int i = 0; i < TEXT_MAX_LAYERS; ++i) - { - multi[i] = GenerateRandomColor(0.5f, 0.8f); - multi[i].a = GetRandomValue(0, 255); - } - } - } - - // Handle text input - int ch = GetCharPressed(); - if (IsKeyPressed(KEY_BACKSPACE)) - { - // Remove last char - int len = TextLength(text); - if (len > 0) text[len - 1] = '\0'; - } - else if (IsKeyPressed(KEY_ENTER)) - { - // handle newline - int len = TextLength(text); - if (len < sizeof(text) - 1) - { - text[len] = '\n'; - text[len+1] ='\0'; - } - } - else - { - // append only printable chars - int len = TextLength(text); - if (len < sizeof(text) - 1) - { - text[len] = ch; - text[len+1] ='\0'; - } - } - - // Measure 3D text so we can center it - tbox = MeasureTextWave3D(font, text, fontSize, fontSpacing, lineSpacing); - - quads = 0; // Reset quad counter - time += GetFrameTime(); // Update timer needed by `DrawTextWave3D()` - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - BeginMode3D(camera); - DrawCubeV(cubePosition, cubeSize, dark); - DrawCubeWires(cubePosition, 2.1f, 2.1f, 2.1f, light); - - DrawGrid(10, 2.0f); - - // Use a shader to handle the depth buffer issue with transparent textures - // NOTE: more info at https://bedroomcoders.co.uk/raylib-billboards-advanced-use/ - BeginShaderMode(alphaDiscard); - - // Draw the 3D text above the red cube - rlPushMatrix(); - rlRotatef(90.0f, 1.0f, 0.0f, 0.0f); - rlRotatef(90.0f, 0.0f, 0.0f, -1.0f); - - for (int i = 0; i < layers; ++i) - { - Color clr = light; - if (multicolor) clr = multi[i]; - DrawTextWave3D(font, text, (Vector3){ -tbox.x/2.0f, layerDistance*i, -4.5f }, fontSize, fontSpacing, lineSpacing, true, &wcfg, time, clr); - } - - // Draw the text boundry if set - if (SHOW_TEXT_BOUNDRY) DrawCubeWiresV((Vector3){ 0.0f, 0.0f, -4.5f + tbox.z/2 }, tbox, dark); - rlPopMatrix(); - - // Don't draw the letter boundries for the 3D text below - bool slb = SHOW_LETTER_BOUNDRY; - SHOW_LETTER_BOUNDRY = false; - - // Draw 3D options (use default font) - //------------------------------------------------------------------------- - rlPushMatrix(); - rlRotatef(180.0f, 0.0f, 1.0f, 0.0f); - char *opt = (char *)TextFormat("< SIZE: %2.1f >", fontSize); - quads += TextLength(opt); - Vector3 m = MeasureText3D(GetFontDefault(), opt, 8.0f, 1.0f, 0.0f); - Vector3 pos = { -m.x/2.0f, 0.01f, 2.0f}; - DrawText3D(GetFontDefault(), opt, pos, 8.0f, 1.0f, 0.0f, false, BLUE); - pos.z += 0.5f + m.z; - - opt = (char *)TextFormat("< SPACING: %2.1f >", fontSpacing); - quads += TextLength(opt); - m = MeasureText3D(GetFontDefault(), opt, 8.0f, 1.0f, 0.0f); - pos.x = -m.x/2.0f; - DrawText3D(GetFontDefault(), opt, pos, 8.0f, 1.0f, 0.0f, false, BLUE); - pos.z += 0.5f + m.z; - - opt = (char *)TextFormat("< LINE: %2.1f >", lineSpacing); - quads += TextLength(opt); - m = MeasureText3D(GetFontDefault(), opt, 8.0f, 1.0f, 0.0f); - pos.x = -m.x/2.0f; - DrawText3D(GetFontDefault(), opt, pos, 8.0f, 1.0f, 0.0f, false, BLUE); - pos.z += 1.0f + m.z; - - opt = (char *)TextFormat("< LBOX: %3s >", slb? "ON" : "OFF"); - quads += TextLength(opt); - m = MeasureText3D(GetFontDefault(), opt, 8.0f, 1.0f, 0.0f); - pos.x = -m.x/2.0f; - DrawText3D(GetFontDefault(), opt, pos, 8.0f, 1.0f, 0.0f, false, RED); - pos.z += 0.5f + m.z; - - opt = (char *)TextFormat("< TBOX: %3s >", SHOW_TEXT_BOUNDRY? "ON" : "OFF"); - quads += TextLength(opt); - m = MeasureText3D(GetFontDefault(), opt, 8.0f, 1.0f, 0.0f); - pos.x = -m.x/2.0f; - DrawText3D(GetFontDefault(), opt, pos, 8.0f, 1.0f, 0.0f, false, RED); - pos.z += 0.5f + m.z; - - opt = (char *)TextFormat("< LAYER DISTANCE: %.3f >", layerDistance); - quads += TextLength(opt); - m = MeasureText3D(GetFontDefault(), opt, 8.0f, 1.0f, 0.0f); - pos.x = -m.x/2.0f; - DrawText3D(GetFontDefault(), opt, pos, 8.0f, 1.0f, 0.0f, false, DARKPURPLE); - rlPopMatrix(); - //------------------------------------------------------------------------- - - // Draw 3D info text (use default font) - //------------------------------------------------------------------------- - opt = "All the text displayed here is in 3D"; - quads += 36; - m = MeasureText3D(GetFontDefault(), opt, 10.0f, 0.5f, 0.0f); - pos = (Vector3){-m.x/2.0f, 0.01f, 2.0f}; - DrawText3D(GetFontDefault(), opt, pos, 10.0f, 0.5f, 0.0f, false, DARKBLUE); - pos.z += 1.5f + m.z; - - opt = "press [Left]/[Right] to change the font size"; - quads += 44; - m = MeasureText3D(GetFontDefault(), opt, 6.0f, 0.5f, 0.0f); - pos.x = -m.x/2.0f; - DrawText3D(GetFontDefault(), opt, pos, 6.0f, 0.5f, 0.0f, false, DARKBLUE); - pos.z += 0.5f + m.z; - - opt = "press [Up]/[Down] to change the font spacing"; - quads += 44; - m = MeasureText3D(GetFontDefault(), opt, 6.0f, 0.5f, 0.0f); - pos.x = -m.x/2.0f; - DrawText3D(GetFontDefault(), opt, pos, 6.0f, 0.5f, 0.0f, false, DARKBLUE); - pos.z += 0.5f + m.z; - - opt = "press [PgUp]/[PgDown] to change the line spacing"; - quads += 48; - m = MeasureText3D(GetFontDefault(), opt, 6.0f, 0.5f, 0.0f); - pos.x = -m.x/2.0f; - DrawText3D(GetFontDefault(), opt, pos, 6.0f, 0.5f, 0.0f, false, DARKBLUE); - pos.z += 0.5f + m.z; - - opt = "press [F1] to toggle the letter boundry"; - quads += 39; - m = MeasureText3D(GetFontDefault(), opt, 6.0f, 0.5f, 0.0f); - pos.x = -m.x/2.0f; - DrawText3D(GetFontDefault(), opt, pos, 6.0f, 0.5f, 0.0f, false, DARKBLUE); - pos.z += 0.5f + m.z; - - opt = "press [F2] to toggle the text boundry"; - quads += 37; - m = MeasureText3D(GetFontDefault(), opt, 6.0f, 0.5f, 0.0f); - pos.x = -m.x/2.0f; - DrawText3D(GetFontDefault(), opt, pos, 6.0f, 0.5f, 0.0f, false, DARKBLUE); - //------------------------------------------------------------------------- - - SHOW_LETTER_BOUNDRY = slb; - EndShaderMode(); - - EndMode3D(); - - // Draw 2D info text & stats - //------------------------------------------------------------------------- - DrawText("Drag & drop a font file to change the font!\nType something, see what happens!\n\n" - "Press [F3] to toggle the camera", 10, 35, 10, BLACK); - - quads += TextLength(text)*2*layers; - char *tmp = (char *)TextFormat("%2i layer(s) | %s camera | %4i quads (%4i verts)", layers, spin? "ORBITAL" : "FREE", quads, quads*4); - int width = MeasureText(tmp, 10); - DrawText(tmp, screenWidth - 20 - width, 10, 10, DARKGREEN); - - tmp = "[Home]/[End] to add/remove 3D text layers"; - width = MeasureText(tmp, 10); - DrawText(tmp, screenWidth - 20 - width, 25, 10, DARKGRAY); - - tmp = "[Insert]/[Delete] to increase/decrease distance between layers"; - width = MeasureText(tmp, 10); - DrawText(tmp, screenWidth - 20 - width, 40, 10, DARKGRAY); - - tmp = "click the [CUBE] for a random color"; - width = MeasureText(tmp, 10); - DrawText(tmp, screenWidth - 20 - width, 55, 10, DARKGRAY); - - tmp = "[Tab] to toggle multicolor mode"; - width = MeasureText(tmp, 10); - DrawText(tmp, screenWidth - 20 - width, 70, 10, DARKGRAY); - //------------------------------------------------------------------------- - - DrawFPS(10, 10); - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - UnloadFont(font); - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} - -//-------------------------------------------------------------------------------------- -// Module Functions Definitions -//-------------------------------------------------------------------------------------- -// Draw codepoint at specified position in 3D space -static void DrawTextCodepoint3D(Font font, int codepoint, Vector3 position, float fontSize, bool backface, Color tint) -{ - // Character index position in sprite font - // NOTE: In case a codepoint is not available in the font, index returned points to '?' - int index = GetGlyphIndex(font, codepoint); - float scale = fontSize/(float)font.baseSize; - - // Character destination rectangle on screen - // NOTE: We consider charsPadding on drawing - position.x += (float)(font.glyphs[index].offsetX - font.glyphPadding)/(float)font.baseSize*scale; - position.z += (float)(font.glyphs[index].offsetY - font.glyphPadding)/(float)font.baseSize*scale; - - // Character source rectangle from font texture atlas - // NOTE: We consider chars padding when drawing, it could be required for outline/glow shader effects - Rectangle srcRec = { font.recs[index].x - (float)font.glyphPadding, font.recs[index].y - (float)font.glyphPadding, - font.recs[index].width + 2.0f*font.glyphPadding, font.recs[index].height + 2.0f*font.glyphPadding }; - - float width = (float)(font.recs[index].width + 2.0f*font.glyphPadding)/(float)font.baseSize*scale; - float height = (float)(font.recs[index].height + 2.0f*font.glyphPadding)/(float)font.baseSize*scale; - - if (font.texture.id > 0) - { - const float x = 0.0f; - const float y = 0.0f; - const float z = 0.0f; - - // normalized texture coordinates of the glyph inside the font texture (0.0f -> 1.0f) - const float tx = srcRec.x/font.texture.width; - const float ty = srcRec.y/font.texture.height; - const float tw = (srcRec.x+srcRec.width)/font.texture.width; - const float th = (srcRec.y+srcRec.height)/font.texture.height; - - if (SHOW_LETTER_BOUNDRY) DrawCubeWiresV((Vector3){ position.x + width/2, position.y, position.z + height/2}, (Vector3){ width, LETTER_BOUNDRY_SIZE, height }, LETTER_BOUNDRY_COLOR); - - rlCheckRenderBatchLimit(4 + 4*backface); - rlSetTexture(font.texture.id); - - rlPushMatrix(); - rlTranslatef(position.x, position.y, position.z); - - rlBegin(RL_QUADS); - rlColor4ub(tint.r, tint.g, tint.b, tint.a); - - // Front Face - rlNormal3f(0.0f, 1.0f, 0.0f); // Normal Pointing Up - rlTexCoord2f(tx, ty); rlVertex3f(x, y, z); // Top Left Of The Texture and Quad - rlTexCoord2f(tx, th); rlVertex3f(x, y, z + height); // Bottom Left Of The Texture and Quad - rlTexCoord2f(tw, th); rlVertex3f(x + width, y, z + height); // Bottom Right Of The Texture and Quad - rlTexCoord2f(tw, ty); rlVertex3f(x + width, y, z); // Top Right Of The Texture and Quad - - if (backface) - { - // Back Face - rlNormal3f(0.0f, -1.0f, 0.0f); // Normal Pointing Down - rlTexCoord2f(tx, ty); rlVertex3f(x, y, z); // Top Right Of The Texture and Quad - rlTexCoord2f(tw, ty); rlVertex3f(x + width, y, z); // Top Left Of The Texture and Quad - rlTexCoord2f(tw, th); rlVertex3f(x + width, y, z + height); // Bottom Left Of The Texture and Quad - rlTexCoord2f(tx, th); rlVertex3f(x, y, z + height); // Bottom Right Of The Texture and Quad - } - rlEnd(); - rlPopMatrix(); - - rlSetTexture(0); - } -} - -// Draw a 2D text in 3D space -static void DrawText3D(Font font, const char *text, Vector3 position, float fontSize, float fontSpacing, float lineSpacing, bool backface, Color tint) -{ - int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop - - float textOffsetY = 0.0f; // Offset between lines (on line break '\n') - float textOffsetX = 0.0f; // Offset X to next character to draw - - float scale = fontSize/(float)font.baseSize; - - for (int i = 0; i < length;) - { - // Get next codepoint from byte string and glyph index in font - int codepointByteCount = 0; - int codepoint = GetCodepoint(&text[i], &codepointByteCount); - int index = GetGlyphIndex(font, codepoint); - - // NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f) - // but we need to draw all of the bad bytes using the '?' symbol moving one byte - if (codepoint == 0x3f) codepointByteCount = 1; - - if (codepoint == '\n') - { - // NOTE: Fixed line spacing of 1.5 line-height - // TODO: Support custom line spacing defined by user - textOffsetY += scale + lineSpacing/(float)font.baseSize*scale; - textOffsetX = 0.0f; - } - else - { - if ((codepoint != ' ') && (codepoint != '\t')) - { - DrawTextCodepoint3D(font, codepoint, (Vector3){ position.x + textOffsetX, position.y, position.z + textOffsetY }, fontSize, backface, tint); - } - - if (font.glyphs[index].advanceX == 0) textOffsetX += (float)(font.recs[index].width + fontSpacing)/(float)font.baseSize*scale; - else textOffsetX += (float)(font.glyphs[index].advanceX + fontSpacing)/(float)font.baseSize*scale; - } - - i += codepointByteCount; // Move text bytes counter to next codepoint - } -} - -// Measure a text in 3D. For some reason `MeasureTextEx()` just doesn't seem to work so i had to use this instead. -static Vector3 MeasureText3D(Font font, const char* text, float fontSize, float fontSpacing, float lineSpacing) -{ - int len = TextLength(text); - int tempLen = 0; // Used to count longer text line num chars - int lenCounter = 0; - - float tempTextWidth = 0.0f; // Used to count longer text line width - - float scale = fontSize/(float)font.baseSize; - float textHeight = scale; - float textWidth = 0.0f; - - int letter = 0; // Current character - int index = 0; // Index position in sprite font - - for (int i = 0; i < len; i++) - { - lenCounter++; - - int next = 0; - letter = GetCodepoint(&text[i], &next); - index = GetGlyphIndex(font, letter); - - // NOTE: normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f) - // but we need to draw all of the bad bytes using the '?' symbol so to not skip any we set next = 1 - if (letter == 0x3f) next = 1; - i += next - 1; - - if (letter != '\n') - { - if (font.glyphs[index].advanceX != 0) textWidth += (font.glyphs[index].advanceX+fontSpacing)/(float)font.baseSize*scale; - else textWidth += (font.recs[index].width + font.glyphs[index].offsetX)/(float)font.baseSize*scale; - } - else - { - if (tempTextWidth < textWidth) tempTextWidth = textWidth; - lenCounter = 0; - textWidth = 0.0f; - textHeight += scale + lineSpacing/(float)font.baseSize*scale; - } - - if (tempLen < lenCounter) tempLen = lenCounter; - } - - if (tempTextWidth < textWidth) tempTextWidth = textWidth; - - Vector3 vec = { 0 }; - vec.x = tempTextWidth + (float)((tempLen - 1)*fontSpacing/(float)font.baseSize*scale); // Adds chars spacing to measure - vec.y = 0.25f; - vec.z = textHeight; - - return vec; -} - -// Draw a 2D text in 3D space and wave the parts that start with `~~` and end with `~~`. -// This is a modified version of the original code by @Nighten found here https://github.com/NightenDushi/Raylib_DrawTextStyle -static void DrawTextWave3D(Font font, const char *text, Vector3 position, float fontSize, float fontSpacing, float lineSpacing, bool backface, WaveTextConfig* config, float time, Color tint) -{ - int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop - - float textOffsetY = 0.0f; // Offset between lines (on line break '\n') - float textOffsetX = 0.0f; // Offset X to next character to draw - - float scale = fontSize/(float)font.baseSize; - - bool wave = false; - - for (int i = 0, k = 0; i < length; ++k) - { - // Get next codepoint from byte string and glyph index in font - int codepointByteCount = 0; - int codepoint = GetCodepoint(&text[i], &codepointByteCount); - int index = GetGlyphIndex(font, codepoint); - - // NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f) - // but we need to draw all of the bad bytes using the '?' symbol moving one byte - if (codepoint == 0x3f) codepointByteCount = 1; - - if (codepoint == '\n') - { - // NOTE: Fixed line spacing of 1.5 line-height - // TODO: Support custom line spacing defined by user - textOffsetY += scale + lineSpacing/(float)font.baseSize*scale; - textOffsetX = 0.0f; - k = 0; - } - else if (codepoint == '~') - { - if (GetCodepoint(&text[i+1], &codepointByteCount) == '~') - { - codepointByteCount += 1; - wave = !wave; - } - } - else - { - if ((codepoint != ' ') && (codepoint != '\t')) - { - Vector3 pos = position; - if (wave) // Apply the wave effect - { - pos.x += sinf(time*config->waveSpeed.x-k*config->waveOffset.x)*config->waveRange.x; - pos.y += sinf(time*config->waveSpeed.y-k*config->waveOffset.y)*config->waveRange.y; - pos.z += sinf(time*config->waveSpeed.z-k*config->waveOffset.z)*config->waveRange.z; - } - - DrawTextCodepoint3D(font, codepoint, (Vector3){ pos.x + textOffsetX, pos.y, pos.z + textOffsetY }, fontSize, backface, tint); - } - - if (font.glyphs[index].advanceX == 0) textOffsetX += (float)(font.recs[index].width + fontSpacing)/(float)font.baseSize*scale; - else textOffsetX += (float)(font.glyphs[index].advanceX + fontSpacing)/(float)font.baseSize*scale; - } - - i += codepointByteCount; // Move text bytes counter to next codepoint - } -} - -// Measure a text in 3D ignoring the `~~` chars. -static Vector3 MeasureTextWave3D(Font font, const char* text, float fontSize, float fontSpacing, float lineSpacing) -{ - int len = TextLength(text); - int tempLen = 0; // Used to count longer text line num chars - int lenCounter = 0; - - float tempTextWidth = 0.0f; // Used to count longer text line width - - float scale = fontSize/(float)font.baseSize; - float textHeight = scale; - float textWidth = 0.0f; - - int letter = 0; // Current character - int index = 0; // Index position in sprite font - - for (int i = 0; i < len; i++) - { - lenCounter++; - - int next = 0; - letter = GetCodepoint(&text[i], &next); - index = GetGlyphIndex(font, letter); - - // NOTE: normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f) - // but we need to draw all of the bad bytes using the '?' symbol so to not skip any we set next = 1 - if (letter == 0x3f) next = 1; - i += next - 1; - - if (letter != '\n') - { - if (letter == '~' && GetCodepoint(&text[i+1], &next) == '~') - { - i++; - } - else - { - if (font.glyphs[index].advanceX != 0) textWidth += (font.glyphs[index].advanceX+fontSpacing)/(float)font.baseSize*scale; - else textWidth += (font.recs[index].width + font.glyphs[index].offsetX)/(float)font.baseSize*scale; - } - } - else - { - if (tempTextWidth < textWidth) tempTextWidth = textWidth; - lenCounter = 0; - textWidth = 0.0f; - textHeight += scale + lineSpacing/(float)font.baseSize*scale; - } - - if (tempLen < lenCounter) tempLen = lenCounter; - } - - if (tempTextWidth < textWidth) tempTextWidth = textWidth; - - Vector3 vec = { 0 }; - vec.x = tempTextWidth + (float)((tempLen - 1)*fontSpacing/(float)font.baseSize*scale); // Adds chars spacing to measure - vec.y = 0.25f; - vec.z = textHeight; - - return vec; -} - -// Generates a nice color with a random hue -static Color GenerateRandomColor(float s, float v) -{ - const float Phi = 0.618033988749895f; // Golden ratio conjugate - float h = (float)GetRandomValue(0, 360); - h = fmodf((h + h*Phi), 360.0f); - return ColorFromHSV(h, s, v); -} diff --git a/examples/text/text_font_filters.c b/examples/text/text_font_filters.c deleted file mode 100644 index e675671..0000000 --- a/examples/text/text_font_filters.c +++ /dev/null @@ -1,137 +0,0 @@ -/******************************************************************************************* -* -* raylib [text] example - Font filters -* -* NOTE: After font loading, font texture atlas filter could be configured for a softer -* display of the font when scaling it to different sizes, that way, it's not required -* to generate multiple fonts at multiple sizes (as long as the scaling is not very different) -* -* Example originally created with raylib 1.3, last time updated with raylib 4.2 -* -* 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) 2015-2023 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main(void) -{ - // Initialization - //-------------------------------------------------------------------------------------- - const int screenWidth = 800; - const int screenHeight = 450; - - InitWindow(screenWidth, screenHeight, "raylib [text] example - font filters"); - - const char msg[50] = "Loaded Font"; - - // NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required) - - // TTF Font loading with custom generation parameters - Font font = LoadFontEx("resources/KAISG.ttf", 96, 0, 0); - - // Generate mipmap levels to use trilinear filtering - // NOTE: On 2D drawing it won't be noticeable, it looks like FILTER_BILINEAR - GenTextureMipmaps(&font.texture); - - float fontSize = (float)font.baseSize; - Vector2 fontPosition = { 40.0f, screenHeight/2.0f - 80.0f }; - Vector2 textSize = { 0.0f, 0.0f }; - - // Setup texture scaling filter - SetTextureFilter(font.texture, TEXTURE_FILTER_POINT); - int currentFontFilter = 0; // TEXTURE_FILTER_POINT - - 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 - //---------------------------------------------------------------------------------- - fontSize += GetMouseWheelMove()*4.0f; - - // Choose font texture filter method - if (IsKeyPressed(KEY_ONE)) - { - SetTextureFilter(font.texture, TEXTURE_FILTER_POINT); - currentFontFilter = 0; - } - else if (IsKeyPressed(KEY_TWO)) - { - SetTextureFilter(font.texture, TEXTURE_FILTER_BILINEAR); - currentFontFilter = 1; - } - else if (IsKeyPressed(KEY_THREE)) - { - // NOTE: Trilinear filter won't be noticed on 2D drawing - SetTextureFilter(font.texture, TEXTURE_FILTER_TRILINEAR); - currentFontFilter = 2; - } - - textSize = MeasureTextEx(font, msg, fontSize, 0); - - if (IsKeyDown(KEY_LEFT)) fontPosition.x -= 10; - else if (IsKeyDown(KEY_RIGHT)) fontPosition.x += 10; - - // Load a dropped TTF file dynamically (at current fontSize) - if (IsFileDropped()) - { - FilePathList droppedFiles = LoadDroppedFiles(); - - // NOTE: We only support first ttf file dropped - if (IsFileExtension(droppedFiles.paths[0], ".ttf")) - { - UnloadFont(font); - font = LoadFontEx(droppedFiles.paths[0], (int)fontSize, 0, 0); - } - - UnloadDroppedFiles(droppedFiles); // Unload filepaths from memory - } - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - DrawText("Use mouse wheel to change font size", 20, 20, 10, GRAY); - DrawText("Use KEY_RIGHT and KEY_LEFT to move text", 20, 40, 10, GRAY); - DrawText("Use 1, 2, 3 to change texture filter", 20, 60, 10, GRAY); - DrawText("Drop a new TTF font for dynamic loading", 20, 80, 10, DARKGRAY); - - DrawTextEx(font, msg, fontPosition, fontSize, 0, BLACK); - - // TODO: It seems texSize measurement is not accurate due to chars offsets... - //DrawRectangleLines(fontPosition.x, fontPosition.y, textSize.x, textSize.y, RED); - - DrawRectangle(0, screenHeight - 80, screenWidth, 80, LIGHTGRAY); - DrawText(TextFormat("Font size: %02.02f", fontSize), 20, screenHeight - 50, 10, DARKGRAY); - DrawText(TextFormat("Text size: [%02.02f, %02.02f]", textSize.x, textSize.y), 20, screenHeight - 30, 10, DARKGRAY); - DrawText("CURRENT TEXTURE FILTER:", 250, 400, 20, GRAY); - - if (currentFontFilter == 0) DrawText("POINT", 570, 400, 20, BLACK); - else if (currentFontFilter == 1) DrawText("BILINEAR", 570, 400, 20, BLACK); - else if (currentFontFilter == 2) DrawText("TRILINEAR", 570, 400, 20, BLACK); - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - UnloadFont(font); // Font unloading - - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} \ No newline at end of file diff --git a/examples/text/text_font_loading.c b/examples/text/text_font_loading.c deleted file mode 100644 index 2ded64f..0000000 --- a/examples/text/text_font_loading.c +++ /dev/null @@ -1,96 +0,0 @@ -/******************************************************************************************* -* -* raylib [text] example - Font loading -* -* NOTE: raylib can load fonts from multiple input file formats: -* -* - TTF/OTF > Sprite font atlas is generated on loading, user can configure -* some of the generation parameters (size, characters to include) -* - BMFonts > Angel code font fileformat, sprite font image must be provided -* together with the .fnt file, font generation cna not be configured -* - XNA Spritefont > Sprite font image, following XNA Spritefont conventions, -* Characters in image must follow some spacing and order rules -* -* Example originally created with raylib 1.4, last time updated with raylib 3.0 -* -* 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) 2016-2023 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main(void) -{ - // Initialization - //-------------------------------------------------------------------------------------- - const int screenWidth = 800; - const int screenHeight = 450; - - InitWindow(screenWidth, screenHeight, "raylib [text] example - font loading"); - - // Define characters to draw - // NOTE: raylib supports UTF-8 encoding, following list is actually codified as UTF8 internally - const char msg[256] = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHI\nJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmn\nopqrstuvwxyz{|}~¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓ\nÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷\nøùúûüýþÿ"; - - // NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required) - - // BMFont (AngelCode) : Font data and image atlas have been generated using external program - Font fontBm = LoadFont("resources/pixantiqua.fnt"); - - // TTF font : Font data and atlas are generated directly from TTF - // NOTE: We define a font base size of 32 pixels tall and up-to 250 characters - Font fontTtf = LoadFontEx("resources/pixantiqua.ttf", 32, 0, 250); - - bool useTtf = false; - - 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 - //---------------------------------------------------------------------------------- - if (IsKeyDown(KEY_SPACE)) useTtf = true; - else useTtf = false; - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - DrawText("Hold SPACE to use TTF generated font", 20, 20, 20, LIGHTGRAY); - - if (!useTtf) - { - DrawTextEx(fontBm, msg, (Vector2){ 20.0f, 100.0f }, (float)fontBm.baseSize, 2, MAROON); - DrawText("Using BMFont (Angelcode) imported", 20, GetScreenHeight() - 30, 20, GRAY); - } - else - { - DrawTextEx(fontTtf, msg, (Vector2){ 20.0f, 100.0f }, (float)fontTtf.baseSize, 2, LIME); - DrawText("Using TTF font generated", 20, GetScreenHeight() - 30, 20, GRAY); - } - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - UnloadFont(fontBm); // AngelCode Font unloading - UnloadFont(fontTtf); // TTF Font unloading - - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} \ No newline at end of file diff --git a/examples/text/text_font_loading.js b/examples/text/text_font_loading.js new file mode 100644 index 0000000..15ea08c --- /dev/null +++ b/examples/text/text_font_loading.js @@ -0,0 +1,86 @@ +/******************************************************************************************* +* +* raylib [text] example - Font loading +* +* NOTE: raylib can load fonts from multiple input file formats: +* +* - TTF/OTF > Sprite font atlas is generated on loading, user can configure +* some of the generation parameters (size, characters to include) +* - BMFonts > Angel code font fileformat, sprite font image must be provided +* together with the .fnt file, font generation cna not be configured +* - XNA Spritefont > Sprite font image, following XNA Spritefont conventions, +* Characters in image must follow some spacing and order rules +* +* Example originally created with raylib 1.4, last time updated with raylib 3.0 +* +* 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) 2016-2023 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ +// Initialization +//-------------------------------------------------------------------------------------- +const screenWidth = 800; +const screenHeight = 450; + +initWindow(screenWidth, screenHeight, "raylib [text] example - font loading"); + +// Define characters to draw +// NOTE: raylib supports UTF-8 encoding, following list is actually codified as UTF8 internally +const msg = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHI\nJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmn\nopqrstuvwxyz{|}~¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓ\nÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷\nøùúûüýþÿ"; + +// NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required) + +// BMFont (AngelCode) : Font data and image atlas have been generated using external program +const fontBm = loadFont("resources/pixantiqua.fnt"); + +// TTF font : Font data and atlas are generated directly from TTF +// NOTE: We define a font base size of 32 pixels tall and up-to 250 characters +const fontTtf = loadFontEx("resources/pixantiqua.ttf", 32, 0, 250); + +let useTtf = false; + +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 + //---------------------------------------------------------------------------------- + if (isKeyDown(KEY_SPACE)) useTtf = true; + else useTtf = false; + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + beginDrawing(); + + clearBackground(RAYWHITE); + + drawText("Hold SPACE to use TTF generated font", 20, 20, 20, LIGHTGRAY); + + if (!useTtf) + { + traceLog(LOG_INFO, fontBm.baseSize) + drawTextEx(fontBm, msg, new Vector2(20.0, 100.0), fontBm.baseSize/2, 2, MAROON); + drawText("Using BMFont (Angelcode) imported", 20, getScreenHeight() - 30, 20, GRAY); + } + else + { + drawTextEx(fontTtf, msg, new Vector2(20.0, 100.0), fontTtf.baseSize/2, 2, LIME); + drawText("Using TTF font generated", 20, getScreenHeight() - 30, 20, GRAY); + } + + endDrawing(); + //---------------------------------------------------------------------------------- +} + +// De-Initialization +//-------------------------------------------------------------------------------------- +unloadFont(fontBm); // AngelCode Font unloading +unloadFont(fontTtf); // TTF Font unloading + +closeWindow(); // Close window and OpenGL context +//-------------------------------------------------------------------------------------- \ No newline at end of file diff --git a/examples/text/text_font_sdf.c b/examples/text/text_font_sdf.c deleted file mode 100644 index 6a223ae..0000000 --- a/examples/text/text_font_sdf.c +++ /dev/null @@ -1,146 +0,0 @@ -/******************************************************************************************* -* -* raylib [text] example - Font SDF loading -* -* Example originally created with raylib 1.3, last time updated with raylib 4.0 -* -* 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) 2015-2023 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -#if defined(PLATFORM_DESKTOP) - #define GLSL_VERSION 330 -#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB - #define GLSL_VERSION 100 -#endif - -#include - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main(void) -{ - // Initialization - //-------------------------------------------------------------------------------------- - const int screenWidth = 800; - const int screenHeight = 450; - - InitWindow(screenWidth, screenHeight, "raylib [text] example - SDF fonts"); - - // NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required) - - const char msg[50] = "Signed Distance Fields"; - - // Loading file to memory - unsigned int fileSize = 0; - unsigned char *fileData = LoadFileData("resources/anonymous_pro_bold.ttf", &fileSize); - - // Default font generation from TTF font - Font fontDefault = { 0 }; - fontDefault.baseSize = 16; - fontDefault.glyphCount = 95; - - // Loading font data from memory data - // Parameters > font size: 16, no glyphs array provided (0), glyphs count: 95 (autogenerate chars array) - fontDefault.glyphs = LoadFontData(fileData, fileSize, 16, 0, 95, FONT_DEFAULT); - // Parameters > glyphs count: 95, font size: 16, glyphs padding in image: 4 px, pack method: 0 (default) - Image atlas = GenImageFontAtlas(fontDefault.glyphs, &fontDefault.recs, 95, 16, 4, 0); - fontDefault.texture = LoadTextureFromImage(atlas); - UnloadImage(atlas); - - // SDF font generation from TTF font - Font fontSDF = { 0 }; - fontSDF.baseSize = 16; - fontSDF.glyphCount = 95; - // Parameters > font size: 16, no glyphs array provided (0), glyphs count: 0 (defaults to 95) - fontSDF.glyphs = LoadFontData(fileData, fileSize, 16, 0, 0, FONT_SDF); - // Parameters > glyphs count: 95, font size: 16, glyphs padding in image: 0 px, pack method: 1 (Skyline algorythm) - atlas = GenImageFontAtlas(fontSDF.glyphs, &fontSDF.recs, 95, 16, 0, 1); - fontSDF.texture = LoadTextureFromImage(atlas); - UnloadImage(atlas); - - UnloadFileData(fileData); // Free memory from loaded file - - // Load SDF required shader (we use default vertex shader) - Shader shader = LoadShader(0, TextFormat("resources/shaders/glsl%i/sdf.fs", GLSL_VERSION)); - SetTextureFilter(fontSDF.texture, TEXTURE_FILTER_BILINEAR); // Required for SDF font - - Vector2 fontPosition = { 40, screenHeight/2.0f - 50 }; - Vector2 textSize = { 0.0f, 0.0f }; - float fontSize = 16.0f; - int currentFont = 0; // 0 - fontDefault, 1 - fontSDF - - 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 - //---------------------------------------------------------------------------------- - fontSize += GetMouseWheelMove()*8.0f; - - if (fontSize < 6) fontSize = 6; - - if (IsKeyDown(KEY_SPACE)) currentFont = 1; - else currentFont = 0; - - if (currentFont == 0) textSize = MeasureTextEx(fontDefault, msg, fontSize, 0); - else textSize = MeasureTextEx(fontSDF, msg, fontSize, 0); - - fontPosition.x = GetScreenWidth()/2 - textSize.x/2; - fontPosition.y = GetScreenHeight()/2 - textSize.y/2 + 80; - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - if (currentFont == 1) - { - // NOTE: SDF fonts require a custom SDf shader to compute fragment color - BeginShaderMode(shader); // Activate SDF font shader - DrawTextEx(fontSDF, msg, fontPosition, fontSize, 0, BLACK); - EndShaderMode(); // Activate our default shader for next drawings - - DrawTexture(fontSDF.texture, 10, 10, BLACK); - } - else - { - DrawTextEx(fontDefault, msg, fontPosition, fontSize, 0, BLACK); - DrawTexture(fontDefault.texture, 10, 10, BLACK); - } - - if (currentFont == 1) DrawText("SDF!", 320, 20, 80, RED); - else DrawText("default font", 315, 40, 30, GRAY); - - DrawText("FONT SIZE: 16.0", GetScreenWidth() - 240, 20, 20, DARKGRAY); - DrawText(TextFormat("RENDER SIZE: %02.02f", fontSize), GetScreenWidth() - 240, 50, 20, DARKGRAY); - DrawText("Use MOUSE WHEEL to SCALE TEXT!", GetScreenWidth() - 240, 90, 10, DARKGRAY); - - DrawText("HOLD SPACE to USE SDF FONT VERSION!", 340, GetScreenHeight() - 30, 20, MAROON); - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - UnloadFont(fontDefault); // Default font unloading - UnloadFont(fontSDF); // SDF font unloading - - UnloadShader(shader); // Unload SDF shader - - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} \ No newline at end of file diff --git a/examples/text/text_font_spritefont.c b/examples/text/text_font_spritefont.c deleted file mode 100644 index b5df2d0..0000000 --- a/examples/text/text_font_spritefont.c +++ /dev/null @@ -1,91 +0,0 @@ -/******************************************************************************************* -* -* raylib [text] example - Sprite font loading -* -* NOTE: Sprite fonts should be generated following this conventions: -* -* - Characters must be ordered starting with character 32 (Space) -* - Every character must be contained within the same Rectangle height -* - Every character and every line must be separated by the same distance (margin/padding) -* - Rectangles must be defined by a MAGENTA color background -* -* Following those constraints, a font can be provided just by an image, -* this is quite handy to avoid additional font descriptor files (like BMFonts use). -* -* Example originally created with raylib 1.0, last time updated with raylib 1.0 -* -* 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) 2014-2023 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main(void) -{ - // Initialization - //-------------------------------------------------------------------------------------- - const int screenWidth = 800; - const int screenHeight = 450; - - InitWindow(screenWidth, screenHeight, "raylib [text] example - sprite font loading"); - - const char msg1[50] = "THIS IS A custom SPRITE FONT..."; - const char msg2[50] = "...and this is ANOTHER CUSTOM font..."; - const char msg3[50] = "...and a THIRD one! GREAT! :D"; - - // NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required) - Font font1 = LoadFont("resources/custom_mecha.png"); // Font loading - Font font2 = LoadFont("resources/custom_alagard.png"); // Font loading - Font font3 = LoadFont("resources/custom_jupiter_crash.png"); // Font loading - - Vector2 fontPosition1 = { screenWidth/2.0f - MeasureTextEx(font1, msg1, (float)font1.baseSize, -3).x/2, - screenHeight/2.0f - font1.baseSize/2.0f - 80.0f }; - - Vector2 fontPosition2 = { screenWidth/2.0f - MeasureTextEx(font2, msg2, (float)font2.baseSize, -2.0f).x/2.0f, - screenHeight/2.0f - font2.baseSize/2.0f - 10.0f }; - - Vector2 fontPosition3 = { screenWidth/2.0f - MeasureTextEx(font3, msg3, (float)font3.baseSize, 2.0f).x/2.0f, - screenHeight/2.0f - font3.baseSize/2.0f + 50.0f }; - - 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 - //---------------------------------------------------------------------------------- - // TODO: Update variables here... - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - DrawTextEx(font1, msg1, fontPosition1, (float)font1.baseSize, -3, WHITE); - DrawTextEx(font2, msg2, fontPosition2, (float)font2.baseSize, -2, WHITE); - DrawTextEx(font3, msg3, fontPosition3, (float)font3.baseSize, 2, WHITE); - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - UnloadFont(font1); // Font unloading - UnloadFont(font2); // Font unloading - UnloadFont(font3); // Font unloading - - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} \ No newline at end of file diff --git a/examples/text/text_format_text.c b/examples/text/text_format_text.c deleted file mode 100644 index 6b1b045..0000000 --- a/examples/text/text_format_text.c +++ /dev/null @@ -1,67 +0,0 @@ -/******************************************************************************************* -* -* raylib [text] example - Text formatting -* -* Example originally created with raylib 1.1, last time updated with raylib 3.0 -* -* 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) 2014-2023 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main(void) -{ - // Initialization - //-------------------------------------------------------------------------------------- - const int screenWidth = 800; - const int screenHeight = 450; - - InitWindow(screenWidth, screenHeight, "raylib [text] example - text formatting"); - - int score = 100020; - int hiscore = 200450; - int lives = 5; - - 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 - //---------------------------------------------------------------------------------- - // TODO: Update your variables here - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - DrawText(TextFormat("Score: %08i", score), 200, 80, 20, RED); - - DrawText(TextFormat("HiScore: %08i", hiscore), 200, 120, 20, GREEN); - - DrawText(TextFormat("Lives: %02i", lives), 200, 160, 40, BLUE); - - DrawText(TextFormat("Elapsed Time: %02.02f ms", GetFrameTime()*1000), 200, 220, 20, BLACK); - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} \ No newline at end of file diff --git a/examples/text/text_input_box.c b/examples/text/text_input_box.c deleted file mode 100644 index f3923c1..0000000 --- a/examples/text/text_input_box.c +++ /dev/null @@ -1,132 +0,0 @@ -/******************************************************************************************* -* -* raylib [text] example - Input Box -* -* Example originally created with raylib 1.7, last time updated with raylib 3.5 -* -* 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) 2017-2023 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -#define MAX_INPUT_CHARS 9 - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main(void) -{ - // Initialization - //-------------------------------------------------------------------------------------- - const int screenWidth = 800; - const int screenHeight = 450; - - InitWindow(screenWidth, screenHeight, "raylib [text] example - input box"); - - char name[MAX_INPUT_CHARS + 1] = "\0"; // NOTE: One extra space required for null terminator char '\0' - int letterCount = 0; - - Rectangle textBox = { screenWidth/2.0f - 100, 180, 225, 50 }; - bool mouseOnText = false; - - int framesCounter = 0; - - SetTargetFPS(10); // Set our game to run at 10 frames-per-second - //-------------------------------------------------------------------------------------- - - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update - //---------------------------------------------------------------------------------- - if (CheckCollisionPointRec(GetMousePosition(), textBox)) mouseOnText = true; - else mouseOnText = false; - - if (mouseOnText) - { - // Set the window's cursor to the I-Beam - SetMouseCursor(MOUSE_CURSOR_IBEAM); - - // Get char pressed (unicode character) on the queue - int key = GetCharPressed(); - - // Check if more characters have been pressed on the same frame - while (key > 0) - { - // NOTE: Only allow keys in range [32..125] - if ((key >= 32) && (key <= 125) && (letterCount < MAX_INPUT_CHARS)) - { - name[letterCount] = (char)key; - name[letterCount+1] = '\0'; // Add null terminator at the end of the string. - letterCount++; - } - - key = GetCharPressed(); // Check next character in the queue - } - - if (IsKeyPressed(KEY_BACKSPACE)) - { - letterCount--; - if (letterCount < 0) letterCount = 0; - name[letterCount] = '\0'; - } - } - else SetMouseCursor(MOUSE_CURSOR_DEFAULT); - - if (mouseOnText) framesCounter++; - else framesCounter = 0; - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - DrawText("PLACE MOUSE OVER INPUT BOX!", 240, 140, 20, GRAY); - - DrawRectangleRec(textBox, LIGHTGRAY); - if (mouseOnText) DrawRectangleLines((int)textBox.x, (int)textBox.y, (int)textBox.width, (int)textBox.height, RED); - else DrawRectangleLines((int)textBox.x, (int)textBox.y, (int)textBox.width, (int)textBox.height, DARKGRAY); - - DrawText(name, (int)textBox.x + 5, (int)textBox.y + 8, 40, MAROON); - - DrawText(TextFormat("INPUT CHARS: %i/%i", letterCount, MAX_INPUT_CHARS), 315, 250, 20, DARKGRAY); - - if (mouseOnText) - { - if (letterCount < MAX_INPUT_CHARS) - { - // Draw blinking underscore char - if (((framesCounter/20)%2) == 0) DrawText("_", (int)textBox.x + 8 + MeasureText(name, 40), (int)textBox.y + 12, 40, MAROON); - } - else DrawText("Press BACKSPACE to delete chars...", 230, 300, 20, GRAY); - } - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} - -// Check if any key is pressed -// NOTE: We limit keys check to keys between 32 (KEY_SPACE) and 126 -bool IsAnyKeyPressed() -{ - bool keyPressed = false; - int key = GetKeyPressed(); - - if ((key >= 32) && (key <= 126)) keyPressed = true; - - return keyPressed; -} diff --git a/examples/text/text_raylib_fonts.c b/examples/text/text_raylib_fonts.c deleted file mode 100644 index 8ef67c7..0000000 --- a/examples/text/text_raylib_fonts.c +++ /dev/null @@ -1,110 +0,0 @@ -/******************************************************************************************* -* -* raylib [text] example - raylib fonts loading -* -* NOTE: raylib is distributed with some free to use fonts (even for commercial pourposes!) -* To view details and credits for those fonts, check raylib license file -* -* Example originally created with raylib 1.7, last time updated with raylib 3.7 -* -* 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) 2017-2023 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -#define MAX_FONTS 8 - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main(void) -{ - // Initialization - //-------------------------------------------------------------------------------------- - const int screenWidth = 800; - const int screenHeight = 450; - - InitWindow(screenWidth, screenHeight, "raylib [text] example - raylib fonts"); - - // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) - Font fonts[MAX_FONTS] = { 0 }; - - fonts[0] = LoadFont("resources/fonts/alagard.png"); - fonts[1] = LoadFont("resources/fonts/pixelplay.png"); - fonts[2] = LoadFont("resources/fonts/mecha.png"); - fonts[3] = LoadFont("resources/fonts/setback.png"); - fonts[4] = LoadFont("resources/fonts/romulus.png"); - fonts[5] = LoadFont("resources/fonts/pixantiqua.png"); - fonts[6] = LoadFont("resources/fonts/alpha_beta.png"); - fonts[7] = LoadFont("resources/fonts/jupiter_crash.png"); - - const char *messages[MAX_FONTS] = { "ALAGARD FONT designed by Hewett Tsoi", - "PIXELPLAY FONT designed by Aleksander Shevchuk", - "MECHA FONT designed by Captain Falcon", - "SETBACK FONT designed by Brian Kent (AEnigma)", - "ROMULUS FONT designed by Hewett Tsoi", - "PIXANTIQUA FONT designed by Gerhard Grossmann", - "ALPHA_BETA FONT designed by Brian Kent (AEnigma)", - "JUPITER_CRASH FONT designed by Brian Kent (AEnigma)" }; - - const int spacings[MAX_FONTS] = { 2, 4, 8, 4, 3, 4, 4, 1 }; - - Vector2 positions[MAX_FONTS] = { 0 }; - - for (int i = 0; i < MAX_FONTS; i++) - { - positions[i].x = screenWidth/2.0f - MeasureTextEx(fonts[i], messages[i], fonts[i].baseSize*2.0f, (float)spacings[i]).x/2.0f; - positions[i].y = 60.0f + fonts[i].baseSize + 45.0f*i; - } - - // Small Y position corrections - positions[3].y += 8; - positions[4].y += 2; - positions[7].y -= 8; - - Color colors[MAX_FONTS] = { MAROON, ORANGE, DARKGREEN, DARKBLUE, DARKPURPLE, LIME, GOLD, RED }; - - 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 - //---------------------------------------------------------------------------------- - // TODO: Update your variables here - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - DrawText("free fonts included with raylib", 250, 20, 20, DARKGRAY); - DrawLine(220, 50, 590, 50, DARKGRAY); - - for (int i = 0; i < MAX_FONTS; i++) - { - DrawTextEx(fonts[i], messages[i], positions[i], fonts[i].baseSize*2.0f, (float)spacings[i], colors[i]); - } - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - - // Fonts unloading - for (int i = 0; i < MAX_FONTS; i++) UnloadFont(fonts[i]); - - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} \ No newline at end of file diff --git a/examples/text/text_rectangle_bounds.c b/examples/text/text_rectangle_bounds.c deleted file mode 100644 index 886c348..0000000 --- a/examples/text/text_rectangle_bounds.c +++ /dev/null @@ -1,268 +0,0 @@ -/******************************************************************************************* -* -* raylib [text] example - Rectangle bounds -* -* Example originally created with raylib 2.5, last time updated with raylib 4.0 -* -* Example contributed by Vlad Adrian (@demizdor) 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) 2018-2023 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -static void DrawTextBoxed(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint); // Draw text using font inside rectangle limits -static void DrawTextBoxedSelectable(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint); // Draw text using font inside rectangle limits with support for text selection - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main(void) -{ - // Initialization - //-------------------------------------------------------------------------------------- - const int screenWidth = 800; - const int screenHeight = 450; - - InitWindow(screenWidth, screenHeight, "raylib [text] example - draw text inside a rectangle"); - - const char text[] = "Text cannot escape\tthis container\t...word wrap also works when active so here's \ -a long text for testing.\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod \ -tempor incididunt ut labore et dolore magna aliqua. Nec ullamcorper sit amet risus nullam eget felis eget."; - - bool resizing = false; - bool wordWrap = true; - - Rectangle container = { 25.0f, 25.0f, screenWidth - 50.0f, screenHeight - 250.0f }; - Rectangle resizer = { container.x + container.width - 17, container.y + container.height - 17, 14, 14 }; - - // Minimum width and heigh for the container rectangle - const float minWidth = 60; - const float minHeight = 60; - const float maxWidth = screenWidth - 50.0f; - const float maxHeight = screenHeight - 160.0f; - - Vector2 lastMouse = { 0.0f, 0.0f }; // Stores last mouse coordinates - Color borderColor = MAROON; // Container border color - Font font = GetFontDefault(); // Get default system font - - 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 - //---------------------------------------------------------------------------------- - if (IsKeyPressed(KEY_SPACE)) wordWrap = !wordWrap; - - Vector2 mouse = GetMousePosition(); - - // Check if the mouse is inside the container and toggle border color - if (CheckCollisionPointRec(mouse, container)) borderColor = Fade(MAROON, 0.4f); - else if (!resizing) borderColor = MAROON; - - // Container resizing logic - if (resizing) - { - if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) resizing = false; - - float width = container.width + (mouse.x - lastMouse.x); - container.width = (width > minWidth)? ((width < maxWidth)? width : maxWidth) : minWidth; - - float height = container.height + (mouse.y - lastMouse.y); - container.height = (height > minHeight)? ((height < maxHeight)? height : maxHeight) : minHeight; - } - else - { - // Check if we're resizing - if (IsMouseButtonDown(MOUSE_BUTTON_LEFT) && CheckCollisionPointRec(mouse, resizer)) resizing = true; - } - - // Move resizer rectangle properly - resizer.x = container.x + container.width - 17; - resizer.y = container.y + container.height - 17; - - lastMouse = mouse; // Update mouse - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - DrawRectangleLinesEx(container, 3, borderColor); // Draw container border - - // Draw text in container (add some padding) - DrawTextBoxed(font, text, (Rectangle){ container.x + 4, container.y + 4, container.width - 4, container.height - 4 }, 20.0f, 2.0f, wordWrap, GRAY); - - DrawRectangleRec(resizer, borderColor); // Draw the resize box - - // Draw bottom info - DrawRectangle(0, screenHeight - 54, screenWidth, 54, GRAY); - DrawRectangleRec((Rectangle){ 382.0f, screenHeight - 34.0f, 12.0f, 12.0f }, MAROON); - - DrawText("Word Wrap: ", 313, screenHeight-115, 20, BLACK); - if (wordWrap) DrawText("ON", 447, screenHeight - 115, 20, RED); - else DrawText("OFF", 447, screenHeight - 115, 20, BLACK); - - DrawText("Press [SPACE] to toggle word wrap", 218, screenHeight - 86, 20, GRAY); - - DrawText("Click hold & drag the to resize the container", 155, screenHeight - 38, 20, RAYWHITE); - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} - -//-------------------------------------------------------------------------------------- -// Module functions definition -//-------------------------------------------------------------------------------------- - -// Draw text using font inside rectangle limits -static void DrawTextBoxed(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint) -{ - DrawTextBoxedSelectable(font, text, rec, fontSize, spacing, wordWrap, tint, 0, 0, WHITE, WHITE); -} - -// Draw text using font inside rectangle limits with support for text selection -static void DrawTextBoxedSelectable(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint) -{ - int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop - - float textOffsetY = 0; // Offset between lines (on line break '\n') - float textOffsetX = 0.0f; // Offset X to next character to draw - - float scaleFactor = fontSize/(float)font.baseSize; // Character rectangle scaling factor - - // Word/character wrapping mechanism variables - enum { MEASURE_STATE = 0, DRAW_STATE = 1 }; - int state = wordWrap? MEASURE_STATE : DRAW_STATE; - - int startLine = -1; // Index where to begin drawing (where a line begins) - int endLine = -1; // Index where to stop drawing (where a line ends) - int lastk = -1; // Holds last value of the character position - - for (int i = 0, k = 0; i < length; i++, k++) - { - // Get next codepoint from byte string and glyph index in font - int codepointByteCount = 0; - int codepoint = GetCodepoint(&text[i], &codepointByteCount); - int index = GetGlyphIndex(font, codepoint); - - // NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f) - // but we need to draw all of the bad bytes using the '?' symbol moving one byte - if (codepoint == 0x3f) codepointByteCount = 1; - i += (codepointByteCount - 1); - - float glyphWidth = 0; - if (codepoint != '\n') - { - glyphWidth = (font.glyphs[index].advanceX == 0) ? font.recs[index].width*scaleFactor : font.glyphs[index].advanceX*scaleFactor; - - if (i + 1 < length) glyphWidth = glyphWidth + spacing; - } - - // NOTE: When wordWrap is ON we first measure how much of the text we can draw before going outside of the rec container - // We store this info in startLine and endLine, then we change states, draw the text between those two variables - // and change states again and again recursively until the end of the text (or until we get outside of the container). - // When wordWrap is OFF we don't need the measure state so we go to the drawing state immediately - // and begin drawing on the next line before we can get outside the container. - if (state == MEASURE_STATE) - { - // TODO: There are multiple types of spaces in UNICODE, maybe it's a good idea to add support for more - // Ref: http://jkorpela.fi/chars/spaces.html - if ((codepoint == ' ') || (codepoint == '\t') || (codepoint == '\n')) endLine = i; - - if ((textOffsetX + glyphWidth) > rec.width) - { - endLine = (endLine < 1)? i : endLine; - if (i == endLine) endLine -= codepointByteCount; - if ((startLine + codepointByteCount) == endLine) endLine = (i - codepointByteCount); - - state = !state; - } - else if ((i + 1) == length) - { - endLine = i; - state = !state; - } - else if (codepoint == '\n') state = !state; - - if (state == DRAW_STATE) - { - textOffsetX = 0; - i = startLine; - glyphWidth = 0; - - // Save character position when we switch states - int tmp = lastk; - lastk = k - 1; - k = tmp; - } - } - else - { - if (codepoint == '\n') - { - if (!wordWrap) - { - textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor; - textOffsetX = 0; - } - } - else - { - if (!wordWrap && ((textOffsetX + glyphWidth) > rec.width)) - { - textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor; - textOffsetX = 0; - } - - // When text overflows rectangle height limit, just stop drawing - if ((textOffsetY + font.baseSize*scaleFactor) > rec.height) break; - - // Draw selection background - bool isGlyphSelected = false; - if ((selectStart >= 0) && (k >= selectStart) && (k < (selectStart + selectLength))) - { - DrawRectangleRec((Rectangle){ rec.x + textOffsetX - 1, rec.y + textOffsetY, glyphWidth, (float)font.baseSize*scaleFactor }, selectBackTint); - isGlyphSelected = true; - } - - // Draw current character glyph - if ((codepoint != ' ') && (codepoint != '\t')) - { - DrawTextCodepoint(font, codepoint, (Vector2){ rec.x + textOffsetX, rec.y + textOffsetY }, fontSize, isGlyphSelected? selectTint : tint); - } - } - - if (wordWrap && (i == endLine)) - { - textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor; - textOffsetX = 0; - startLine = endLine; - endLine = -1; - glyphWidth = 0; - selectStart += lastk - k; - k = lastk; - - state = !state; - } - } - - if ((textOffsetX != 0) || (codepoint != ' ')) textOffsetX += glyphWidth; // avoid leading spaces - } -} diff --git a/examples/text/text_unicode.c b/examples/text/text_unicode.c deleted file mode 100644 index eb2a784..0000000 --- a/examples/text/text_unicode.c +++ /dev/null @@ -1,468 +0,0 @@ -/******************************************************************************************* -* -* raylib [text] example - Unicode -* -* Example originally created with raylib 2.5, last time updated with raylib 4.0 -* -* Example contributed by Vlad Adrian (@demizdor) 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) 2019-2023 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -#include -#include - -#define SIZEOF(A) (sizeof(A)/sizeof(A[0])) -#define EMOJI_PER_WIDTH 8 -#define EMOJI_PER_HEIGHT 4 - -// String containing 180 emoji codepoints separated by a '\0' char -const char *const emojiCodepoints = "\xF0\x9F\x8C\x80\x00\xF0\x9F\x98\x80\x00\xF0\x9F\x98\x82\x00\xF0\x9F\xA4\xA3\x00\xF0\x9F\x98\x83\x00\xF0\x9F\x98\x86\x00\xF0\x9F\x98\x89\x00" - "\xF0\x9F\x98\x8B\x00\xF0\x9F\x98\x8E\x00\xF0\x9F\x98\x8D\x00\xF0\x9F\x98\x98\x00\xF0\x9F\x98\x97\x00\xF0\x9F\x98\x99\x00\xF0\x9F\x98\x9A\x00\xF0\x9F\x99\x82\x00" - "\xF0\x9F\xA4\x97\x00\xF0\x9F\xA4\xA9\x00\xF0\x9F\xA4\x94\x00\xF0\x9F\xA4\xA8\x00\xF0\x9F\x98\x90\x00\xF0\x9F\x98\x91\x00\xF0\x9F\x98\xB6\x00\xF0\x9F\x99\x84\x00" - "\xF0\x9F\x98\x8F\x00\xF0\x9F\x98\xA3\x00\xF0\x9F\x98\xA5\x00\xF0\x9F\x98\xAE\x00\xF0\x9F\xA4\x90\x00\xF0\x9F\x98\xAF\x00\xF0\x9F\x98\xAA\x00\xF0\x9F\x98\xAB\x00" - "\xF0\x9F\x98\xB4\x00\xF0\x9F\x98\x8C\x00\xF0\x9F\x98\x9B\x00\xF0\x9F\x98\x9D\x00\xF0\x9F\xA4\xA4\x00\xF0\x9F\x98\x92\x00\xF0\x9F\x98\x95\x00\xF0\x9F\x99\x83\x00" - "\xF0\x9F\xA4\x91\x00\xF0\x9F\x98\xB2\x00\xF0\x9F\x99\x81\x00\xF0\x9F\x98\x96\x00\xF0\x9F\x98\x9E\x00\xF0\x9F\x98\x9F\x00\xF0\x9F\x98\xA4\x00\xF0\x9F\x98\xA2\x00" - "\xF0\x9F\x98\xAD\x00\xF0\x9F\x98\xA6\x00\xF0\x9F\x98\xA9\x00\xF0\x9F\xA4\xAF\x00\xF0\x9F\x98\xAC\x00\xF0\x9F\x98\xB0\x00\xF0\x9F\x98\xB1\x00\xF0\x9F\x98\xB3\x00" - "\xF0\x9F\xA4\xAA\x00\xF0\x9F\x98\xB5\x00\xF0\x9F\x98\xA1\x00\xF0\x9F\x98\xA0\x00\xF0\x9F\xA4\xAC\x00\xF0\x9F\x98\xB7\x00\xF0\x9F\xA4\x92\x00\xF0\x9F\xA4\x95\x00" - "\xF0\x9F\xA4\xA2\x00\xF0\x9F\xA4\xAE\x00\xF0\x9F\xA4\xA7\x00\xF0\x9F\x98\x87\x00\xF0\x9F\xA4\xA0\x00\xF0\x9F\xA4\xAB\x00\xF0\x9F\xA4\xAD\x00\xF0\x9F\xA7\x90\x00" - "\xF0\x9F\xA4\x93\x00\xF0\x9F\x98\x88\x00\xF0\x9F\x91\xBF\x00\xF0\x9F\x91\xB9\x00\xF0\x9F\x91\xBA\x00\xF0\x9F\x92\x80\x00\xF0\x9F\x91\xBB\x00\xF0\x9F\x91\xBD\x00" - "\xF0\x9F\x91\xBE\x00\xF0\x9F\xA4\x96\x00\xF0\x9F\x92\xA9\x00\xF0\x9F\x98\xBA\x00\xF0\x9F\x98\xB8\x00\xF0\x9F\x98\xB9\x00\xF0\x9F\x98\xBB\x00\xF0\x9F\x98\xBD\x00" - "\xF0\x9F\x99\x80\x00\xF0\x9F\x98\xBF\x00\xF0\x9F\x8C\xBE\x00\xF0\x9F\x8C\xBF\x00\xF0\x9F\x8D\x80\x00\xF0\x9F\x8D\x83\x00\xF0\x9F\x8D\x87\x00\xF0\x9F\x8D\x93\x00" - "\xF0\x9F\xA5\x9D\x00\xF0\x9F\x8D\x85\x00\xF0\x9F\xA5\xA5\x00\xF0\x9F\xA5\x91\x00\xF0\x9F\x8D\x86\x00\xF0\x9F\xA5\x94\x00\xF0\x9F\xA5\x95\x00\xF0\x9F\x8C\xBD\x00" - "\xF0\x9F\x8C\xB6\x00\xF0\x9F\xA5\x92\x00\xF0\x9F\xA5\xA6\x00\xF0\x9F\x8D\x84\x00\xF0\x9F\xA5\x9C\x00\xF0\x9F\x8C\xB0\x00\xF0\x9F\x8D\x9E\x00\xF0\x9F\xA5\x90\x00" - "\xF0\x9F\xA5\x96\x00\xF0\x9F\xA5\xA8\x00\xF0\x9F\xA5\x9E\x00\xF0\x9F\xA7\x80\x00\xF0\x9F\x8D\x96\x00\xF0\x9F\x8D\x97\x00\xF0\x9F\xA5\xA9\x00\xF0\x9F\xA5\x93\x00" - "\xF0\x9F\x8D\x94\x00\xF0\x9F\x8D\x9F\x00\xF0\x9F\x8D\x95\x00\xF0\x9F\x8C\xAD\x00\xF0\x9F\xA5\xAA\x00\xF0\x9F\x8C\xAE\x00\xF0\x9F\x8C\xAF\x00\xF0\x9F\xA5\x99\x00" - "\xF0\x9F\xA5\x9A\x00\xF0\x9F\x8D\xB3\x00\xF0\x9F\xA5\x98\x00\xF0\x9F\x8D\xB2\x00\xF0\x9F\xA5\xA3\x00\xF0\x9F\xA5\x97\x00\xF0\x9F\x8D\xBF\x00\xF0\x9F\xA5\xAB\x00" - "\xF0\x9F\x8D\xB1\x00\xF0\x9F\x8D\x98\x00\xF0\x9F\x8D\x9D\x00\xF0\x9F\x8D\xA0\x00\xF0\x9F\x8D\xA2\x00\xF0\x9F\x8D\xA5\x00\xF0\x9F\x8D\xA1\x00\xF0\x9F\xA5\x9F\x00" - "\xF0\x9F\xA5\xA1\x00\xF0\x9F\x8D\xA6\x00\xF0\x9F\x8D\xAA\x00\xF0\x9F\x8E\x82\x00\xF0\x9F\x8D\xB0\x00\xF0\x9F\xA5\xA7\x00\xF0\x9F\x8D\xAB\x00\xF0\x9F\x8D\xAF\x00" - "\xF0\x9F\x8D\xBC\x00\xF0\x9F\xA5\x9B\x00\xF0\x9F\x8D\xB5\x00\xF0\x9F\x8D\xB6\x00\xF0\x9F\x8D\xBE\x00\xF0\x9F\x8D\xB7\x00\xF0\x9F\x8D\xBB\x00\xF0\x9F\xA5\x82\x00" - "\xF0\x9F\xA5\x83\x00\xF0\x9F\xA5\xA4\x00\xF0\x9F\xA5\xA2\x00\xF0\x9F\x91\x81\x00\xF0\x9F\x91\x85\x00\xF0\x9F\x91\x84\x00\xF0\x9F\x92\x8B\x00\xF0\x9F\x92\x98\x00" - "\xF0\x9F\x92\x93\x00\xF0\x9F\x92\x97\x00\xF0\x9F\x92\x99\x00\xF0\x9F\x92\x9B\x00\xF0\x9F\xA7\xA1\x00\xF0\x9F\x92\x9C\x00\xF0\x9F\x96\xA4\x00\xF0\x9F\x92\x9D\x00" - "\xF0\x9F\x92\x9F\x00\xF0\x9F\x92\x8C\x00\xF0\x9F\x92\xA4\x00\xF0\x9F\x92\xA2\x00\xF0\x9F\x92\xA3\x00"; - -struct { - char *text; - char *language; -} const messages[] = { // Array containing all of the emojis messages - {"\x46\x61\x6C\x73\x63\x68\x65\x73\x20\xC3\x9C\x62\x65\x6E\x20\x76\x6F\x6E\x20\x58\x79\x6C\x6F\x70\x68\x6F\x6E\x6D\x75\x73\x69\x6B\x20\x71\x75\xC3\xA4\x6C" - "\x74\x20\x6A\x65\x64\x65\x6E\x20\x67\x72\xC3\xB6\xC3\x9F\x65\x72\x65\x6E\x20\x5A\x77\x65\x72\x67", "German"}, - {"\x42\x65\x69\xC3\x9F\x20\x6E\x69\x63\x68\x74\x20\x69\x6E\x20\x64\x69\x65\x20\x48\x61\x6E\x64\x2C\x20\x64\x69\x65\x20\x64\x69\x63\x68\x20\x66\xC3\xBC\x74" - "\x74\x65\x72\x74\x2E", "German"}, - {"\x41\x75\xC3\x9F\x65\x72\x6F\x72\x64\x65\x6E\x74\x6C\x69\x63\x68\x65\x20\xC3\x9C\x62\x65\x6C\x20\x65\x72\x66\x6F\x72\x64\x65\x72\x6E\x20\x61\x75\xC3\x9F" - "\x65\x72\x6F\x72\x64\x65\x6E\x74\x6C\x69\x63\x68\x65\x20\x4D\x69\x74\x74\x65\x6C\x2E", "German"}, - {"\xD4\xBF\xD6\x80\xD5\xB6\xD5\xA1\xD5\xB4\x20\xD5\xA1\xD5\xBA\xD5\xA1\xD5\xAF\xD5\xAB\x20\xD5\xB8\xD6\x82\xD5\xBF\xD5\xA5\xD5\xAC\x20\xD6\x87\x20\xD5\xAB" - "\xD5\xB6\xD5\xAE\xD5\xAB\x20\xD5\xA1\xD5\xB6\xD5\xB0\xD5\xA1\xD5\xB6\xD5\xA3\xD5\xAB\xD5\xBD\xD5\xBF\x20\xD5\xB9\xD5\xA8\xD5\xB6\xD5\xA5\xD6\x80", "Armenian"}, - {"\xD4\xB5\xD6\x80\xD5\xA2\x20\xD5\xB8\xD6\x80\x20\xD5\xAF\xD5\xA1\xD6\x81\xD5\xAB\xD5\xB6\xD5\xA8\x20\xD5\xA5\xD5\xAF\xD5\xA1\xD6\x82\x20\xD5\xA1\xD5\xB6\xD5" - "\xBF\xD5\xA1\xD5\xBC\x2C\x20\xD5\xAE\xD5\xA1\xD5\xBC\xD5\xA5\xD6\x80\xD5\xA8\x20\xD5\xA1\xD5\xBD\xD5\xA1\xD6\x81\xD5\xAB\xD5\xB6\x2E\x2E\x2E\x20\xC2\xAB\xD4\xBF" - "\xD5\xB8\xD5\xBF\xD5\xA8\x20\xD5\xB4\xD5\xA5\xD6\x80\xD5\xB8\xD5\xB6\xD6\x81\xD5\xAB\xD6\x81\x20\xD5\xA7\x3A\xC2\xBB", "Armenian"}, - {"\xD4\xB3\xD5\xA1\xD5\xBC\xD5\xA8\xD5\x9D\x20\xD5\xA3\xD5\xA1\xD6\x80\xD5\xB6\xD5\xA1\xD5\xB6\x2C\x20\xD5\xB1\xD5\xAB\xD6\x82\xD5\xB6\xD5\xA8\xD5\x9D\x20\xD5" - "\xB1\xD5\xB4\xD5\xBC\xD5\xA1\xD5\xB6", "Armenian"}, - {"\x4A\x65\xC5\xBC\x75\x20\x6B\x6C\xC4\x85\x74\x77\x2C\x20\x73\x70\xC5\x82\xC3\xB3\x64\xC5\xBA\x20\x46\x69\x6E\x6F\x6D\x20\x63\x7A\xC4\x99\xC5\x9B\xC4\x87" - "\x20\x67\x72\x79\x20\x68\x61\xC5\x84\x62\x21", "Polish"}, - {"\x44\x6F\x62\x72\x79\x6D\x69\x20\x63\x68\xC4\x99\x63\x69\x61\x6D\x69\x20\x6A\x65\x73\x74\x20\x70\x69\x65\x6B\xC5\x82\x6F\x20\x77\x79\x62\x72\x75\x6B\x6F" - "\x77\x61\x6E\x65\x2E", "Polish"}, - {"\xC3\x8E\xC8\x9B\x69\x20\x6D\x75\x6C\xC8\x9B\x75\x6D\x65\x73\x63\x20\x63\xC4\x83\x20\x61\x69\x20\x61\x6C\x65\x73\x20\x72\x61\x79\x6C\x69\x62\x2E\x0A\xC8\x98" - "\x69\x20\x73\x70\x65\x72\x20\x73\xC4\x83\x20\x61\x69\x20\x6F\x20\x7A\x69\x20\x62\x75\x6E\xC4\x83\x21", "Romanian"}, - {"\xD0\xAD\xD1\x85\x2C\x20\xD1\x87\xD1\x83\xD0\xB6\xD0\xB0\xD0\xBA\x2C\x20\xD0\xBE\xD0\xB1\xD1\x89\xD0\xB8\xD0\xB9\x20\xD1\x81\xD1\x8A\xD1\x91\xD0\xBC\x20" - "\xD1\x86\xD0\xB5\xD0\xBD\x20\xD1\x88\xD0\xBB\xD1\x8F\xD0\xBF\x20\x28\xD1\x8E\xD1\x84\xD1\x82\xD1\x8C\x29\x20\xD0\xB2\xD0\xB4\xD1\x80\xD1\x8B\xD0\xB7\xD0\xB3\x21", "Russian"}, - {"\xD0\xAF\x20\xD0\xBB\xD1\x8E\xD0\xB1\xD0\xBB\xD1\x8E\x20\x72\x61\x79\x6C\x69\x62\x21", "Russian"}, - {"\xD0\x9C\xD0\xBE\xD0\xBB\xD1\x87\xD0\xB8\x2C\x20\xD1\x81\xD0\xBA\xD1\x80\xD1\x8B\xD0\xB2\xD0\xB0\xD0\xB9\xD1\x81\xD1\x8F\x20\xD0\xB8\x20\xD1\x82\xD0\xB0\xD0\xB8" - "\x0A\xD0\x98\x20\xD1\x87\xD1\x83\xD0\xB2\xD1\x81\xD1\x82\xD0\xB2\xD0\xB0\x20\xD0\xB8\x20\xD0\xBC\xD0\xB5\xD1\x87\xD1\x82\xD1\x8B\x20\xD1\x81\xD0\xB2\xD0\xBE\xD0\xB8\x20" - "\xE2\x80\x93\x0A\xD0\x9F\xD1\x83\xD1\x81\xD0\xBA\xD0\xB0\xD0\xB9\x20\xD0\xB2\x20\xD0\xB4\xD1\x83\xD1\x88\xD0\xB5\xD0\xB2\xD0\xBD\xD0\xBE\xD0\xB9\x20\xD0\xB3\xD0\xBB\xD1" - "\x83\xD0\xB1\xD0\xB8\xD0\xBD\xD0\xB5\x0A\xD0\x98\x20\xD0\xB2\xD1\x81\xD1\x85\xD0\xBE\xD0\xB4\xD1\x8F\xD1\x82\x20\xD0\xB8\x20\xD0\xB7\xD0\xB0\xD0\xB9\xD0\xB4\xD1\x83\xD1" - "\x82\x20\xD0\xBE\xD0\xBD\xD0\xB5\x0A\xD0\x9A\xD0\xB0\xD0\xBA\x20\xD0\xB7\xD0\xB2\xD0\xB5\xD0\xB7\xD0\xB4\xD1\x8B\x20\xD1\x8F\xD1\x81\xD0\xBD\xD1\x8B\xD0\xB5\x20\xD0\xB2" - "\x20\xD0\xBD\xD0\xBE\xD1\x87\xD0\xB8\x2D\x0A\xD0\x9B\xD1\x8E\xD0\xB1\xD1\x83\xD0\xB9\xD1\x81\xD1\x8F\x20\xD0\xB8\xD0\xBC\xD0\xB8\x20\xE2\x80\x93\x20\xD0\xB8\x20\xD0\xBC" - "\xD0\xBE\xD0\xBB\xD1\x87\xD0\xB8\x2E", "Russian"}, - {"\x56\x6F\x69\x78\x20\x61\x6D\x62\x69\x67\x75\xC3\xAB\x20\x64\xE2\x80\x99\x75\x6E\x20\x63\xC5\x93\x75\x72\x20\x71\x75\x69\x20\x61\x75\x20\x7A\xC3\xA9\x70" - "\x68\x79\x72\x20\x70\x72\xC3\xA9\x66\xC3\xA8\x72\x65\x20\x6C\x65\x73\x20\x6A\x61\x74\x74\x65\x73\x20\x64\x65\x20\x6B\x69\x77\x69", "French"}, - {"\x42\x65\x6E\x6A\x61\x6D\xC3\xAD\x6E\x20\x70\x69\x64\x69\xC3\xB3\x20\x75\x6E\x61\x20\x62\x65\x62\x69\x64\x61\x20\x64\x65\x20\x6B\x69\x77\x69\x20\x79\x20" - "\x66\x72\x65\x73\x61\x3B\x20\x4E\x6F\xC3\xA9\x2C\x20\x73\x69\x6E\x20\x76\x65\x72\x67\xC3\xBC\x65\x6E\x7A\x61\x2C\x20\x6C\x61\x20\x6D\xC3\xA1\x73\x20\x65\x78" - "\x71\x75\x69\x73\x69\x74\x61\x20\x63\x68\x61\x6D\x70\x61\xC3\xB1\x61\x20\x64\x65\x6C\x20\x6D\x65\x6E\xC3\xBA\x2E", "Spanish"}, - {"\xCE\xA4\xCE\xB1\xCF\x87\xCE\xAF\xCF\x83\xCF\x84\xCE\xB7\x20\xCE\xB1\xCE\xBB\xCF\x8E\xCF\x80\xCE\xB7\xCE\xBE\x20\xCE\xB2\xCE\xB1\xCF\x86\xCE\xAE\xCF\x82\x20" - "\xCF\x88\xCE\xB7\xCE\xBC\xCE\xAD\xCE\xBD\xCE\xB7\x20\xCE\xB3\xCE\xB7\x2C\x20\xCE\xB4\xCF\x81\xCE\xB1\xCF\x83\xCE\xBA\xCE\xB5\xCE\xBB\xCE\xAF\xCE\xB6\xCE\xB5\xCE" - "\xB9\x20\xCF\x85\xCF\x80\xCE\xAD\xCF\x81\x20\xCE\xBD\xCF\x89\xCE\xB8\xCF\x81\xCE\xBF\xCF\x8D\x20\xCE\xBA\xCF\x85\xCE\xBD\xCF\x8C\xCF\x82", "Greek"}, - {"\xCE\x97\x20\xCE\xBA\xCE\xB1\xCE\xBB\xCF\x8D\xCF\x84\xCE\xB5\xCF\x81\xCE\xB7\x20\xCE\xAC\xCE\xBC\xCF\x85\xCE\xBD\xCE\xB1\x20\xCE\xB5\xCE\xAF\xCE\xBD" - "\xCE\xB1\xCE\xB9\x20\xCE\xB7\x20\xCE\xB5\xCF\x80\xCE\xAF\xCE\xB8\xCE\xB5\xCF\x83\xCE\xB7\x2E", "Greek"}, - {"\xCE\xA7\xCF\x81\xCF\x8C\xCE\xBD\xCE\xB9\xCE\xB1\x20\xCE\xBA\xCE\xB1\xCE\xB9\x20\xCE\xB6\xCE\xB1\xCE\xBC\xCE\xAC\xCE\xBD\xCE\xB9\xCE\xB1\x21", "Greek"}, - {"\xCE\xA0\xCF\x8E\xCF\x82\x20\xCF\x84\xCE\xB1\x20\xCF\x80\xCE\xB1\xCF\x82\x20\xCF\x83\xCE\xAE\xCE\xBC\xCE\xB5\xCF\x81\xCE\xB1\x3B", "Greek"}, - - {"\xE6\x88\x91\xE8\x83\xBD\xE5\x90\x9E\xE4\xB8\x8B\xE7\x8E\xBB\xE7\x92\x83\xE8\x80\x8C\xE4\xB8\x8D\xE4\xBC\xA4\xE8\xBA\xAB\xE4\xBD\x93\xE3\x80\x82", "Chinese"}, - {"\xE4\xBD\xA0\xE5\x90\x83\xE4\xBA\x86\xE5\x90\x97\xEF\xBC\x9F", "Chinese"}, - {"\xE4\xB8\x8D\xE4\xBD\x9C\xE4\xB8\x8D\xE6\xAD\xBB\xE3\x80\x82", "Chinese"}, - {"\xE6\x9C\x80\xE8\xBF\x91\xE5\xA5\xBD\xE5\x90\x97\xEF\xBC\x9F", "Chinese"}, - {"\xE5\xA1\x9E\xE7\xBF\x81\xE5\xA4\xB1\xE9\xA9\xAC\xEF\xBC\x8C\xE7\x84\x89\xE7\x9F\xA5\xE9\x9D\x9E\xE7\xA6\x8F\xE3\x80\x82", "Chinese"}, - {"\xE5\x8D\x83\xE5\x86\x9B\xE6\x98\x93\xE5\xBE\x97\x2C\x20\xE4\xB8\x80\xE5\xB0\x86\xE9\x9A\xBE\xE6\xB1\x82", "Chinese"}, - {"\xE4\xB8\x87\xE4\xBA\x8B\xE5\xBC\x80\xE5\xA4\xB4\xE9\x9A\xBE\xE3\x80\x82", "Chinese"}, - {"\xE9\xA3\x8E\xE6\x97\xA0\xE5\xB8\xB8\xE9\xA1\xBA\xEF\xBC\x8C\xE5\x85\xB5\xE6\x97\xA0\xE5\xB8\xB8\xE8\x83\x9C\xE3\x80\x82", "Chinese"}, - {"\xE6\xB4\xBB\xE5\x88\xB0\xE8\x80\x81\xEF\xBC\x8C\xE5\xAD\xA6\xE5\x88\xB0\xE8\x80\x81\xE3\x80\x82", "Chinese"}, - {"\xE4\xB8\x80\xE8\xA8\x80\xE6\x97\xA2\xE5\x87\xBA\xEF\xBC\x8C\xE9\xA9\xB7\xE9\xA9\xAC\xE9\x9A\xBE\xE8\xBF\xBD\xE3\x80\x82", "Chinese"}, - {"\xE8\xB7\xAF\xE9\x81\xA5\xE7\x9F\xA5\xE9\xA9\xAC\xE5\x8A\x9B\xEF\xBC\x8C\xE6\x97\xA5\xE4\xB9\x85\xE8\xA7\x81\xE4\xBA\xBA\xE5\xBF\x83", "Chinese"}, - {"\xE6\x9C\x89\xE7\x90\x86\xE8\xB5\xB0\xE9\x81\x8D\xE5\xA4\xA9\xE4\xB8\x8B\xEF\xBC\x8C\xE6\x97\xA0\xE7\x90\x86\xE5\xAF\xB8\xE6\xAD\xA5\xE9\x9A\xBE\xE8\xA1\x8C\xE3\x80\x82", "Chinese"}, - - {"\xE7\x8C\xBF\xE3\x82\x82\xE6\x9C\xA8\xE3\x81\x8B\xE3\x82\x89\xE8\x90\xBD\xE3\x81\xA1\xE3\x82\x8B", "Japanese"}, - {"\xE4\xBA\x80\xE3\x81\xAE\xE7\x94\xB2\xE3\x82\x88\xE3\x82\x8A\xE5\xB9\xB4\xE3\x81\xAE\xE5\x8A\x9F", "Japanese"}, - {"\xE3\x81\x86\xE3\x82\x89\xE3\x82\x84\xE3\x81\xBE\xE3\x81\x97\x20\x20\xE6\x80\x9D\xE3\x81\xB2\xE5\x88\x87\xE3\x82\x8B\xE6\x99\x82\x20\x20\xE7\x8C\xAB\xE3\x81\xAE\xE6\x81\x8B", "Japanese"}, - {"\xE8\x99\x8E\xE7\xA9\xB4\xE3\x81\xAB\xE5\x85\xA5\xE3\x82\x89\xE3\x81\x9A\xE3\x82\x93\xE3\x81\xB0\xE8\x99\x8E\xE5\xAD\x90\xE3\x82\x92\xE5\xBE\x97\xE3\x81\x9A\xE3\x80\x82", "Japanese"}, - {"\xE4\xBA\x8C\xE5\x85\x8E\xE3\x82\x92\xE8\xBF\xBD\xE3\x81\x86\xE8\x80\x85\xE3\x81\xAF\xE4\xB8\x80\xE5\x85\x8E\xE3\x82\x92\xE3\x82\x82\xE5\xBE\x97\xE3\x81\x9A\xE3\x80\x82", "Japanese"}, - {"\xE9\xA6\xAC\xE9\xB9\xBF\xE3\x81\xAF\xE6\xAD\xBB\xE3\x81\xAA\xE3\x81\xAA\xE3\x81\x8D\xE3\x82\x83\xE6\xB2\xBB\xE3\x82\x89\xE3\x81\xAA\xE3\x81\x84\xE3\x80\x82", "Japanese"}, - {"\xE6\x9E\xAF\xE9\x87\x8E\xE8\xB7\xAF\xE3\x81\xAB\xE3\x80\x80\xE5\xBD\xB1\xE3\x81\x8B\xE3\x81\x95\xE3\x81\xAA\xE3\x82\x8A\xE3\x81\xA6\xE3\x80\x80\xE3\x82\x8F\xE3\x81\x8B\xE3\x82\x8C\xE3\x81\x91\xE3\x82\x8A", "Japanese"}, - {"\xE7\xB9\xB0\xE3\x82\x8A\xE8\xBF\x94\xE3\x81\x97\xE9\xBA\xA6\xE3\x81\xAE\xE7\x95\x9D\xE7\xB8\xAB\xE3\x81\xB5\xE8\x83\xA1\xE8\x9D\xB6\xE5\x93\x89", "Japanese"}, - - {"\xEC\x95\x84\xEB\x93\x9D\xED\x95\x9C\x20\xEB\xB0\x94\xEB\x8B\xA4\x20\xEC\x9C\x84\xEC\x97\x90\x20\xEA\xB0\x88\xEB\xA7\xA4\xEA\xB8\xB0\x20\xEB\x91\x90\xEC\x97\x87\x20" - "\xEB\x82\xA0\xEC\x95\x84\x20\xEB\x8F\x88\xEB\x8B\xA4\x2E\x0A\xEB\x84\x88\xED\x9B\x8C\xEB\x84\x88\xED\x9B\x8C\x20\xEC\x8B\x9C\xEB\xA5\xBC\x20\xEC\x93\xB4\xEB\x8B\xA4\x2E" - "\x20\xEB\xAA\xA8\xEB\xA5\xB4\xEB\x8A\x94\x20\xEB\x82\x98\xEB\x9D\xBC\x20\xEA\xB8\x80\xEC\x9E\x90\xEB\x8B\xA4\x2E\x0A\xEB\x84\x90\xEB\x94\xB0\xEB\x9E\x80\x20\xED\x95\x98" - "\xEB\x8A\x98\x20\xEB\xB3\xB5\xED\x8C\x90\xEC\x97\x90\x20\xEB\x82\x98\xEB\x8F\x84\x20\xEA\xB0\x99\xEC\x9D\xB4\x20\xEC\x8B\x9C\xEB\xA5\xBC\x20\xEC\x93\xB4\xEB\x8B\xA4\x2E", "Korean"}, - {"\xEC\xA0\x9C\x20\xEB\x88\x88\xEC\x97\x90\x20\xEC\x95\x88\xEA\xB2\xBD\xEC\x9D\xB4\xEB\x8B\xA4", "Korean"}, - {"\xEA\xBF\xA9\x20\xEB\xA8\xB9\xEA\xB3\xA0\x20\xEC\x95\x8C\x20\xEB\xA8\xB9\xEB\x8A\x94\xEB\x8B\xA4", "Korean"}, - {"\xEB\xA1\x9C\xEB\xA7\x88\xEB\x8A\x94\x20\xED\x95\x98\xEB\xA3\xA8\xEC\x95\x84\xEC\xB9\xA8\xEC\x97\x90\x20\xEC\x9D\xB4\xEB\xA3\xA8\xEC\x96\xB4\xEC\xA7\x84\x20\xEA\xB2\x83\xEC\x9D\xB4" - "\x20\xEC\x95\x84\xEB\x8B\x88\xEB\x8B\xA4", "Korean"}, - {"\xEA\xB3\xA0\xEC\x83\x9D\x20\xEB\x81\x9D\xEC\x97\x90\x20\xEB\x82\x99\xEC\x9D\xB4\x20\xEC\x98\xA8\xEB\x8B\xA4", "Korean"}, - {"\xEA\xB0\x9C\xEC\xB2\x9C\xEC\x97\x90\xEC\x84\x9C\x20\xEC\x9A\xA9\x20\xEB\x82\x9C\xEB\x8B\xA4", "Korean"}, - {"\xEC\x95\x88\xEB\x85\x95\xED\x95\x98\xEC\x84\xB8\xEC\x9A\x94\x3F", "Korean"}, - {"\xEB\xA7\x8C\xEB\x82\x98\xEC\x84\x9C\x20\xEB\xB0\x98\xEA\xB0\x91\xEC\x8A\xB5\xEB\x8B\x88\xEB\x8B\xA4", "Korean"}, - {"\xED\x95\x9C\xEA\xB5\xAD\xEB\xA7\x90\x20\xED\x95\x98\xEC\x8B\xA4\x20\xEC\xA4\x84\x20\xEC\x95\x84\xEC\x84\xB8\xEC\x9A\x94\x3F", "Korean"}, -}; - -//-------------------------------------------------------------------------------------- -// Module functions declaration -//-------------------------------------------------------------------------------------- -static void RandomizeEmoji(void); // Fills the emoji array with random emojis - -static void DrawTextBoxed(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint); // Draw text using font inside rectangle limits -static void DrawTextBoxedSelectable(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint); // Draw text using font inside rectangle limits with support for text selection - -//-------------------------------------------------------------------------------------- -// Global variables -//-------------------------------------------------------------------------------------- -// Arrays that holds the random emojis -struct { - int index; // Index inside `emojiCodepoints` - int message; // Message index - Color color; // Emoji color -} emoji[EMOJI_PER_WIDTH*EMOJI_PER_HEIGHT] = { 0 }; - -static int hovered = -1, selected = -1; - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main(void) -{ - // Initialization - //-------------------------------------------------------------------------------------- - const int screenWidth = 800; - const int screenHeight = 450; - - SetConfigFlags(FLAG_MSAA_4X_HINT | FLAG_VSYNC_HINT); - InitWindow(screenWidth, screenHeight, "raylib [text] example - unicode"); - - // Load the font resources - // NOTE: fontAsian is for asian languages, - // fontEmoji is the emojis and fontDefault is used for everything else - Font fontDefault = LoadFont("resources/dejavu.fnt"); - Font fontAsian = LoadFont("resources/noto_cjk.fnt"); - Font fontEmoji = LoadFont("resources/symbola.fnt"); - - Vector2 hoveredPos = { 0.0f, 0.0f }; - Vector2 selectedPos = { 0.0f, 0.0f }; - - // Set a random set of emojis when starting up - RandomizeEmoji(); - - SetTargetFPS(60); // Set our game to run at 60 frames-per-second - //-------------------------------------------------------------------------------------- - - // Main loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update - //---------------------------------------------------------------------------------- - // Add a new set of emojis when SPACE is pressed - if (IsKeyPressed(KEY_SPACE)) RandomizeEmoji(); - - // Set the selected emoji and copy its text to clipboard - if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && (hovered != -1) && (hovered != selected)) - { - selected = hovered; - selectedPos = hoveredPos; - SetClipboardText(messages[emoji[selected].message].text); - } - - Vector2 mouse = GetMousePosition(); - Vector2 pos = { 28.8f, 10.0f }; - hovered = -1; - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - // Draw random emojis in the background - //------------------------------------------------------------------------------ - for (int i = 0; i < SIZEOF(emoji); ++i) - { - const char *txt = &emojiCodepoints[emoji[i].index]; - Rectangle emojiRect = { pos.x, pos.y, (float)fontEmoji.baseSize, (float)fontEmoji.baseSize }; - - if (!CheckCollisionPointRec(mouse, emojiRect)) - { - DrawTextEx(fontEmoji, txt, pos, (float)fontEmoji.baseSize, 1.0f, selected == i ? emoji[i].color : Fade(LIGHTGRAY, 0.4f)); - } - else - { - DrawTextEx(fontEmoji, txt, pos, (float)fontEmoji.baseSize, 1.0f, emoji[i].color ); - hovered = i; - hoveredPos = pos; - } - - if ((i != 0) && (i%EMOJI_PER_WIDTH == 0)) { pos.y += fontEmoji.baseSize + 24.25f; pos.x = 28.8f; } - else pos.x += fontEmoji.baseSize + 28.8f; - } - //------------------------------------------------------------------------------ - - // Draw the message when a emoji is selected - //------------------------------------------------------------------------------ - if (selected != -1) - { - const int message = emoji[selected].message; - const int horizontalPadding = 20, verticalPadding = 30; - Font *font = &fontDefault; - - // Set correct font for asian languages - if (TextIsEqual(messages[message].language, "Chinese") || - TextIsEqual(messages[message].language, "Korean") || - TextIsEqual(messages[message].language, "Japanese")) font = &fontAsian; - - // Calculate size for the message box (approximate the height and width) - Vector2 sz = MeasureTextEx(*font, messages[message].text, (float)font->baseSize, 1.0f); - if (sz.x > 300) { sz.y *= sz.x/300; sz.x = 300; } - else if (sz.x < 160) sz.x = 160; - - Rectangle msgRect = { selectedPos.x - 38.8f, selectedPos.y, 2 * horizontalPadding + sz.x, 2 * verticalPadding + sz.y }; - msgRect.y -= msgRect.height; - - // Coordinates for the chat bubble triangle - Vector2 a = { selectedPos.x, msgRect.y + msgRect.height }, b = {a.x + 8, a.y + 10}, c= { a.x + 10, a.y }; - - // Don't go outside the screen - if (msgRect.x < 10) msgRect.x += 28; - if (msgRect.y < 10) - { - msgRect.y = selectedPos.y + 84; - a.y = msgRect.y; - c.y = a.y; - b.y = a.y - 10; - - // Swap values so we can actually render the triangle :( - Vector2 tmp = a; - a = b; - b = tmp; - } - - if (msgRect.x + msgRect.width > screenWidth) msgRect.x -= (msgRect.x + msgRect.width) - screenWidth + 10; - - // Draw chat bubble - DrawRectangleRec(msgRect, emoji[selected].color); - DrawTriangle(a, b, c, emoji[selected].color); - - // Draw the main text message - Rectangle textRect = { msgRect.x + horizontalPadding/2, msgRect.y + verticalPadding/2, msgRect.width - horizontalPadding, msgRect.height }; - DrawTextBoxed(*font, messages[message].text, textRect, (float)font->baseSize, 1.0f, true, WHITE); - - // Draw the info text below the main message - int size = (int)strlen(messages[message].text); - int length = GetCodepointCount(messages[message].text); - const char *info = TextFormat("%s %u characters %i bytes", messages[message].language, length, size); - sz = MeasureTextEx(GetFontDefault(), info, 10, 1.0f); - Vector2 pos = { textRect.x + textRect.width - sz.x, msgRect.y + msgRect.height - sz.y - 2 }; - DrawText(info, (int)pos.x, (int)pos.y, 10, RAYWHITE); - } - //------------------------------------------------------------------------------ - - // Draw the info text - DrawText("These emojis have something to tell you, click each to find out!", (screenWidth - 650)/2, screenHeight - 40, 20, GRAY); - DrawText("Each emoji is a unicode character from a font, not a texture... Press [SPACEBAR] to refresh", (screenWidth - 484)/2, screenHeight - 16, 10, GRAY); - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - UnloadFont(fontDefault); // Unload font resource - UnloadFont(fontAsian); // Unload font resource - UnloadFont(fontEmoji); // Unload font resource - - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} - -// Fills the emoji array with random emoji (only those emojis present in fontEmoji) -static void RandomizeEmoji(void) -{ - hovered = selected = -1; - int start = GetRandomValue(45, 360); - - for (int i = 0; i < SIZEOF(emoji); ++i) - { - // 0-179 emoji codepoints (from emoji char array) each 4bytes + null char - emoji[i].index = GetRandomValue(0, 179)*5; - - // Generate a random color for this emoji - emoji[i].color = Fade(ColorFromHSV((float)((start*(i + 1))%360), 0.6f, 0.85f), 0.8f); - - // Set a random message for this emoji - emoji[i].message = GetRandomValue(0, SIZEOF(messages) - 1); - } -} - -//-------------------------------------------------------------------------------------- -// Module functions definition -//-------------------------------------------------------------------------------------- - -// Draw text using font inside rectangle limits -static void DrawTextBoxed(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint) -{ - DrawTextBoxedSelectable(font, text, rec, fontSize, spacing, wordWrap, tint, 0, 0, WHITE, WHITE); -} - -// Draw text using font inside rectangle limits with support for text selection -static void DrawTextBoxedSelectable(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint) -{ - int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop - - float textOffsetY = 0; // Offset between lines (on line break '\n') - float textOffsetX = 0.0f; // Offset X to next character to draw - - float scaleFactor = fontSize/(float)font.baseSize; // Character rectangle scaling factor - - // Word/character wrapping mechanism variables - enum { MEASURE_STATE = 0, DRAW_STATE = 1 }; - int state = wordWrap? MEASURE_STATE : DRAW_STATE; - - int startLine = -1; // Index where to begin drawing (where a line begins) - int endLine = -1; // Index where to stop drawing (where a line ends) - int lastk = -1; // Holds last value of the character position - - for (int i = 0, k = 0; i < length; i++, k++) - { - // Get next codepoint from byte string and glyph index in font - int codepointByteCount = 0; - int codepoint = GetCodepoint(&text[i], &codepointByteCount); - int index = GetGlyphIndex(font, codepoint); - - // NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f) - // but we need to draw all of the bad bytes using the '?' symbol moving one byte - if (codepoint == 0x3f) codepointByteCount = 1; - i += (codepointByteCount - 1); - - float glyphWidth = 0; - if (codepoint != '\n') - { - glyphWidth = (font.glyphs[index].advanceX == 0) ? font.recs[index].width*scaleFactor : font.glyphs[index].advanceX*scaleFactor; - - if (i + 1 < length) glyphWidth = glyphWidth + spacing; - } - - // NOTE: When wordWrap is ON we first measure how much of the text we can draw before going outside of the rec container - // We store this info in startLine and endLine, then we change states, draw the text between those two variables - // and change states again and again recursively until the end of the text (or until we get outside of the container). - // When wordWrap is OFF we don't need the measure state so we go to the drawing state immediately - // and begin drawing on the next line before we can get outside the container. - if (state == MEASURE_STATE) - { - // TODO: There are multiple types of spaces in UNICODE, maybe it's a good idea to add support for more - // Ref: http://jkorpela.fi/chars/spaces.html - if ((codepoint == ' ') || (codepoint == '\t') || (codepoint == '\n')) endLine = i; - - if ((textOffsetX + glyphWidth) > rec.width) - { - endLine = (endLine < 1)? i : endLine; - if (i == endLine) endLine -= codepointByteCount; - if ((startLine + codepointByteCount) == endLine) endLine = (i - codepointByteCount); - - state = !state; - } - else if ((i + 1) == length) - { - endLine = i; - state = !state; - } - else if (codepoint == '\n') state = !state; - - if (state == DRAW_STATE) - { - textOffsetX = 0; - i = startLine; - glyphWidth = 0; - - // Save character position when we switch states - int tmp = lastk; - lastk = k - 1; - k = tmp; - } - } - else - { - if (codepoint == '\n') - { - if (!wordWrap) - { - textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor; - textOffsetX = 0; - } - } - else - { - if (!wordWrap && ((textOffsetX + glyphWidth) > rec.width)) - { - textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor; - textOffsetX = 0; - } - - // When text overflows rectangle height limit, just stop drawing - if ((textOffsetY + font.baseSize*scaleFactor) > rec.height) break; - - // Draw selection background - bool isGlyphSelected = false; - if ((selectStart >= 0) && (k >= selectStart) && (k < (selectStart + selectLength))) - { - DrawRectangleRec((Rectangle){ rec.x + textOffsetX - 1, rec.y + textOffsetY, glyphWidth, (float)font.baseSize*scaleFactor }, selectBackTint); - isGlyphSelected = true; - } - - // Draw current character glyph - if ((codepoint != ' ') && (codepoint != '\t')) - { - DrawTextCodepoint(font, codepoint, (Vector2){ rec.x + textOffsetX, rec.y + textOffsetY }, fontSize, isGlyphSelected? selectTint : tint); - } - } - - if (wordWrap && (i == endLine)) - { - textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor; - textOffsetX = 0; - startLine = endLine; - endLine = -1; - glyphWidth = 0; - selectStart += lastk - k; - k = lastk; - - state = !state; - } - } - - textOffsetX += glyphWidth; - } -} \ No newline at end of file diff --git a/examples/text/text_writing_anim.c b/examples/text/text_writing_anim.c deleted file mode 100644 index 4ee6770..0000000 --- a/examples/text/text_writing_anim.c +++ /dev/null @@ -1,67 +0,0 @@ -/******************************************************************************************* -* -* raylib [text] example - Text Writing Animation -* -* Example originally created with raylib 1.4, last time updated with raylib 1.4 -* -* 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) 2016-2023 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main(void) -{ - // Initialization - //-------------------------------------------------------------------------------------- - const int screenWidth = 800; - const int screenHeight = 450; - - InitWindow(screenWidth, screenHeight, "raylib [text] example - text writing anim"); - - const char message[128] = "This sample illustrates a text writing\nanimation effect! Check it out! ;)"; - - int framesCounter = 0; - - 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 - //---------------------------------------------------------------------------------- - if (IsKeyDown(KEY_SPACE)) framesCounter += 8; - else framesCounter++; - - if (IsKeyPressed(KEY_ENTER)) framesCounter = 0; - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - DrawText(TextSubtext(message, 0, framesCounter/10), 210, 160, 20, MAROON); - - DrawText("PRESS [ENTER] to RESTART!", 240, 260, 20, LIGHTGRAY); - DrawText("PRESS [SPACE] to SPEED UP!", 239, 300, 20, LIGHTGRAY); - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} \ No newline at end of file diff --git a/readme.md b/readme.md index 5f6f8ab..49bf03e 100644 --- a/readme.md +++ b/readme.md @@ -61,9 +61,34 @@ The following raylib APIs are supported so far (with a few exceptions): - rcamera - rlights - raygui +- reasings Similar to including a header in C and for your convenience, all types/functions are provided globally. They are additionally available in a module called 'raylib' +To check which API functions are not available (yet) check `/bindings/src/index.ts` for `ignore` statements. + +## Additional APIs + +Rayjs comes with some additional functionality on top of raylib to make writing raylib code with Javascript easier +```typescript +/** Replace material in slot materialIndex (Material is NOT unloaded) */ +declare function setModelMaterial(model: Model, materialIndex: number, material: Material): void; +/** Get material in slot materialIndex */ +declare function getModelMaterial(model: Model, materialIndex: number): Material; +/** Get a single mesh from a model */ +declare function getModelMesh(model: Model, meshIndex: number): Mesh; +/** Set shader constant in shader locations array */ +declare function setShaderLocation(shader: Shader, constant: number, location: number): void; +/** Read a single pixel from an image */ +declare function imageReadPixel(image: Image, x: number, y: number): Color; +/** Make a deep-copy of an existing mesh */ +declare function meshCopy(mesh: Mesh): Mesh; +/** Create a new mesh that contains combined attributes of two meshes */ +declare function meshMerge(a: Mesh, b: Mesh): Mesh; +``` + +Additionally it also comes with bindings to [lightmapper.h](https://github.com/ands/lightmapper/tree/master). See below for more information. + ## Auto-Complete / Intellisense rayjs comes with full auto-complete support in the form of the definitions file `lib.raylib.d.ts`. These will work with Typescript and Javascript. In order to use them with Javascript you should create a Typescript configuration file in the project root (even if you are not using Typescript) called `tsconfig.json` with the following configuration @@ -80,6 +105,53 @@ rayjs comes with full auto-complete support in the form of the definitions file ``` ![](doc/auto-complete.png) +## Examples + +Some official raylib examples were already ported to Javascript and can be found in the `examples` folder. + +Additional examples are described here. + +``` +./rayjs examples/js_example_project +``` +Barebones example project on how to structure a project that uses Javascript +``` +./rayjs examples/js_mesh_generation.js +``` +Shows how to create a mesh from Javascript ArrayBuffers +``` +./rayjs examples/shaders/js_shaders_gradient_lighting.js +``` +Creates a gradient and uses it as lighting for a 3d scene +``` +./rayjs examples/ts_dungeon +``` +Small example game that uses Typescript with Webpack for transpilation and bundling +``` +./rayjs examples/ts_game +``` +Example how to integrate existing JS libraries. This example integrates the Inkjs library to compile and play a game written in the Ink interactive fiction language. + + +### Lightmapper usage +Rayjs integrates the [lightmapper.h](https://github.com/ands/lightmapper/tree/master) library to render baked lighting. +The example demonstrates it's usage. +``` +./rayjs examples/js_lightmapper.js +``` + +Meshes must have unwrapped lightmap uvs in the second UV channel. + +![](2023-07-20-13-08-52.png) + +The example uses an environment that is uniform white which will lead to baking pure ambient occlusion. To bake other light sources, lower the amount of ambient lighting and everything that is rendered with a color other than black will become an emissive lightsource during baking. Rendering will just work as usual and custom shaders are supported. E.g. while the raylib default shader does not support color intensities greater than 1.0, the lightmapper does support them for higher intensity lighting. + +The example will try to bake lighting alongside the render loop which is still buggy and leads to artifacts. Baking before rendering works better. + +## Performance +QuickJS is one of the [faster JS interpreters](https://bellard.org/quickjs/bench.html). I'm getting about 13000 bunnys in the unmodified bunnmark before dropping any frames on my 2020 Macbook Air M1 which seems pretty good. +![Bunnymark](doc/bunny.png) + ## Building Here are some basic steps if you want to compile rayjs yourself. You should use CMake for building. **Please note that QuickJS needs Mingw in order to compile correctly on Windows** @@ -100,6 +172,4 @@ cmake .. make ``` -## Performance -QuickJS is one of the [faster JS interpreters](https://bellard.org/quickjs/bench.html). I'm getting about 13000 bunnys in the unmodified bunnmark before dropping any frames on my 2020 Macbook Air M1 which seems pretty good. -![Bunnymark](doc/bunny.png) +