7 Commits

Author SHA1 Message Date
4ebe7d6215 win32 clipboard: fix for BI_ALPHABITFIELDS narrow support (#5586)
* win32 clipbaord: fix for BI_ALPHABITFIELDS narrow support

* Define BI_ALPHABITFIELDS even if wingdi headers are already included

since BI_ALPHABITFIELDS is not always defined there
2026-02-24 12:56:16 +01:00
Ray
29b5844119 REVIEWED: Comments and header 2026-02-24 12:48:54 +01:00
Ray
aec6e85ec3 Update raygui.h 2026-02-24 12:40:17 +01:00
Ray
25e521553d Update models_animation_blending.c 2026-02-24 12:33:00 +01:00
Ray
d504e400ea Merge branch 'master' of https://github.com/raysan5/raylib 2026-02-24 12:32:50 +01:00
Ray
406861a4a1 Update raudio.c 2026-02-24 12:32:48 +01:00
ace4d77bfa New example: textures_magnifying_glass (#5587) 2026-02-24 11:26:30 +01:00
8 changed files with 163 additions and 18 deletions

View File

@ -6,15 +6,16 @@
*
* Example originally created with raylib 5.5, last time updated with raylib 5.5
*
* Example contributed by dmitrii-brand (@dmitrii-brand) and reviewed by Ramon Santamaria (@raysan5)
*
* DETAILS: Example demonstrates per-bone animation blending, allowing smooth transitions
* between two animations by interpolating bone transforms. This is useful for:
* - Blending movement animations (walk/run) with action animations (jump/attack)
* - Creating smooth animation transitions
* - Layering animations (e.g., upper body attack while lower body walks)
*
* Example contributed by dmitrii-brand (@dmitrii-brand) and reviewed by Ramon Santamaria (@raysan5)
*
* NOTE: Due to limitations in the Apple OpenGL driver, this feature does not work on MacOS
* WARNING: GPU skinning must be enabled in raylib with a compilation flag,
* if not enabled, CPU skinning will be used instead
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software

View File

@ -2,20 +2,19 @@
*
* raylib [models] example - animation blending
*
* Example complexity rating: [☆☆☆☆] 0/4
* Example complexity rating: [★★★★] 4/4
*
* Example originally created with raylib 5.5, last time updated with raylib 5.6-dev
*
* Example contributed by Kirandeep (@Kirandeep-Singh-Khehra)
* Example contributed by Kirandeep (@Kirandeep-Singh-Khehra) and reviewed by Ramon Santamaria (@raysan5)
*
* WARNING: GPU skinning must be enabled in raylib with a compilation flag,
* if not enabled, CPU skinning will be used instead
*
* 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) 2024 Kirandeep (@Kirandeep-Singh-Khehra)
*
* Note: Due to limitations in the Apple OpenGL driver, this feature does not work on MacOS
* Note: This example uses CPU for updating meshes.
* For GPU skinning see comments with 'INFO:'.
* Copyright (c) 2024-2026 Kirandeep (@Kirandeep-Singh-Khehra) and Ramon Santamaria (@raysan5)
*
********************************************************************************************/
@ -184,7 +183,7 @@ int main(void)
if (animCurrentFrame0 >= anims[animIndex0].keyframeCount) animCurrentFrame0 = 0.0f;
UpdateModelAnimation(model, anims[animIndex0], animCurrentFrame0);
//UpdateModelAnimationEx(model, anims[animIndex0], animCurrentFrame0,
// anims[animIndex1], animCurrentFrame1, 0.0f);
// anims[animIndex1], animCurrentFrame1, 0.0f); // Same as above, first animation frame blend
}
else if (currentAnimPlaying == 1)
{
@ -193,7 +192,7 @@ int main(void)
if (animCurrentFrame1 >= anims[animIndex1].keyframeCount) animCurrentFrame1 = 0.0f;
UpdateModelAnimation(model, anims[animIndex1], animCurrentFrame1);
//UpdateModelAnimationEx(model, anims[animIndex0], animCurrentFrame0,
// anims[animIndex1], animCurrentFrame1, 1.0f);
// anims[animIndex1], animCurrentFrame1, 1.0f); // Same as above, second animation frame blend
}
}
}
@ -221,6 +220,15 @@ int main(void)
// Draw UI elements
//---------------------------------------------------------------------------------------------
if (dropdownEditMode0) GuiDisable();
GuiSlider((Rectangle){ 10, 38, 160, 12 },
NULL, TextFormat("x%.1f", animFrameSpeed0), &animFrameSpeed0, 0.1f, 2.0f);
GuiEnable();
if (dropdownEditMode1) GuiDisable();
GuiSlider((Rectangle){ GetScreenWidth() - 170, 38, 160, 12 },
TextFormat("%.1fx", animFrameSpeed1), NULL, &animFrameSpeed1, 0.1f, 2.0f);
GuiEnable();
// Draw animation selectors for blending transition
// NOTE: Transition does not start until requested
GuiSetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING, 1);

View File

@ -2,7 +2,7 @@
*
* raylib [models] example - animation timing
*
* Example complexity rating: [★★☆] 2/4
* Example complexity rating: [★★☆] 3/4
*
* Example originally created with raylib 5.6, last time updated with raylib 5.6
*

View File

@ -5128,11 +5128,11 @@ static const char *GetTextIcon(const char *text, int *iconId)
// Get text divided into lines (by line-breaks '\n')
// WARNING: It returns pointers to new lines but it does not add NULL ('\0') terminator!
static char **GetTextLines(const char *text, int *count)
static const char **GetTextLines(const char *text, int *count)
{
#define RAYGUI_MAX_TEXT_LINES 128
static char *lines[RAYGUI_MAX_TEXT_LINES] = { 0 };
static const char *lines[RAYGUI_MAX_TEXT_LINES] = { 0 };
for (int i = 0; i < RAYGUI_MAX_TEXT_LINES; i++) lines[i] = NULL; // Init NULL pointers to substrings
int textLength = (int)strlen(text);
@ -5202,7 +5202,7 @@ static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, C
// WARNING: GuiTextSplit() function can't be used now because it can have already been used
// before the GuiDrawText() call and its buffer is static, it would be overriden :(
int lineCount = 0;
char **lines = GetTextLines(text, &lineCount);
const char **lines = GetTextLines(text, &lineCount);
// Text style variables
//int alignment = GuiGetStyle(DEFAULT, TEXT_ALIGNMENT);

View File

@ -0,0 +1,134 @@
/*******************************************************************************************
*
* raylib textures example - magnifying glass
*
* Example complexity rating: [★★★☆] 3/4
*
* Example originally created with raylib 5.6, last time updated with raylib 5.6
*
* Example contributed by Luke Vaughan (@badram) 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) 2026 Luke Vaughan (@badram)
*
********************************************************************************************/
#include "raylib.h"
#include "rlgl.h" // for rlSetBlendFactorsSeparate()
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [textures] example - magnifying glass");
Texture2D bunny = LoadTexture("resources/raybunny.png");
Texture2D parrots = LoadTexture("resources/parrots.png");
// Use image draw to generate a mask texture instead of loading it from a file.
Image circle = GenImageColor(256, 256, BLANK);
ImageDrawCircle(&circle, 128, 128, 128, WHITE);
Texture2D mask = LoadTextureFromImage(circle); // Copy the mask image from RAM to VRAM
UnloadImage(circle); // Unload the image from RAM
RenderTexture2D magnifiedWorld = LoadRenderTexture(256, 256);
Camera2D camera = { 0 };
// Set magnifying glass zoom
camera.zoom = 2;
// Offset by half the size of the magnifying glass to counteract drawing the texture centered on the mouse position
camera.offset = (Vector2){128, 128};
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
Vector2 mPos = GetMousePosition();
camera.target = mPos;
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
// Draw the normal version of the world
DrawTexture(parrots, 144, 33, WHITE);
DrawText("Use the magnifying glass to find hidden bunnies!", 154, 6, 20, BLACK);
// Render to a the magnifying glass
BeginTextureMode(magnifiedWorld);
ClearBackground(RAYWHITE);
BeginMode2D(camera);
// Draw the same things in the magnified world as were in the normal version
DrawTexture(parrots, 144, 33, WHITE);
DrawText("Use the magnifying glass to find hidden bunnies!", 154, 6, 20, BLACK);
// Draw bunnies only in the magnified world.
// BLEND_MULTIPLIED lets them take on the color of the image below them.
BeginBlendMode(BLEND_MULTIPLIED);
DrawTexture(bunny, 250, 350, WHITE);
DrawTexture(bunny, 500, 100, WHITE);
DrawTexture(bunny, 420, 300, WHITE);
DrawTexture(bunny, 650, 10, WHITE);
EndBlendMode();
EndMode2D();
// Mask the magnifying glass view texture to a circle
// To make the mask affect only alpha, a CUSTOM blend mode is used with SEPARATE color/alpha functions
BeginBlendMode(BLEND_CUSTOM_SEPARATE);
// C: Color, A: Alpha, s: source (texture to draw), d: destination (texture drawn to)
// glSrcRGB: RL_ZERO - Cs * 0 = 0 - discard source rgb because we don't want to draw our texture's colors at all
// glDstRGB: RL_ONE - Cd * 1 = Cd - use destination colors unmodified
// glSrcAlpha: RL_ONE - As * 1 = As - use source alpha unmodified
// glDstAlpha: RL_ZERO - Ad * 0 = 0 - discard destination alpha
// glEqRGB: RL_FUNC_ADD - Cs(0) + Cd = Cd - destination color is unmodified
// glEqAlpha: RL_FUNC_ADD - As + Ad(0) = As - destination alpha is set to source alpha
rlSetBlendFactorsSeparate(RL_ZERO, RL_ONE, RL_ONE, RL_ZERO, RL_FUNC_ADD, RL_FUNC_ADD);
DrawTexture(mask, 0, 0, WHITE);
EndBlendMode();
EndTextureMode();
// Draw magnifiedWorld to screen, centered on cursor
DrawTextureRec(magnifiedWorld.texture, (Rectangle){0, 0, 256, -256}, (Vector2){mPos.x - 128, mPos.y - 128}, WHITE);
// Draw the outer ring of the magnifying glass
DrawRing(mPos, 126, 130, 0, 360, 64, BLACK);
// Draw floating specular highlight on the glass
float rx = mPos.x/800;
float ry = mPos.y/800;
DrawCircle((int)(mPos.x - 64*rx) - 32, (int)(mPos.y - 64*ry) - 32, 4, ColorAlpha(WHITE, 0.5));
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadTexture(parrots);
UnloadTexture(bunny);
UnloadTexture(mask);
UnloadRenderTexture(magnifiedWorld);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 KiB

View File

@ -178,7 +178,9 @@ typedef struct tagRGBQUAD {
#define BI_CMYK 0x000B
#define BI_CMYKRLE8 0x000C
#define BI_CMYKRLE4 0x000D
#endif
#ifndef BI_ALPHABITFIELDS
// Bitmap not compressed and that the color table consists of four DWORD color masks,
// that specify the red, green, blue, and alpha components of each pixel
#define BI_ALPHABITFIELDS 0x0006
@ -317,7 +319,7 @@ static int GetPixelDataOffset(BITMAPINFOHEADER bih)
// If (bih.biCompression == BI_RGB) no need to be offset more
if (bih.biCompression == BI_BITFIELDS) offset += 3*rgbaSize;
else if (bih.biCompression == BI_ALPHABITFIELDS) offset += 4*rgbaSize; // Not widely supported, but valid
else if (bih.biCompression == BI_ALPHABITFIELDS) offset += 4 * rgbaSize; // Not widely supported, but valid
}
}

View File

@ -2487,7 +2487,7 @@ static ma_uint32 ReadAudioBufferFramesInMixingFormat(AudioBuffer *audioBuffer, f
{
float *runningFramesOut = framesOut + (totalOutputFramesProcessed*audioBuffer->converter.channelsOut);
ma_uint64 outputFramesToProcessThisIteration = frameCount - totalOutputFramesProcessed;
ma_uint64 inputFramesToProcessThisIteration = 0;
//ma_uint64 inputFramesToProcessThisIteration = 0;
// Process any residual input frames from the previous read first.
if (audioBuffer->converterResidualCount > 0)