Add scissor stack and allow user to query current scissor region

This commit is contained in:
Dan Bechard 2024-01-04 13:15:08 -05:00
parent eb6dcab308
commit faa8e7d7e9
3 changed files with 84 additions and 17 deletions

View File

@ -76,6 +76,8 @@
#define MAX_FILEPATH_CAPACITY 8192 // Maximum file paths capacity #define MAX_FILEPATH_CAPACITY 8192 // Maximum file paths capacity
#define MAX_FILEPATH_LENGTH 4096 // Maximum length for filepaths (Linux PATH_MAX default value) #define MAX_FILEPATH_LENGTH 4096 // Maximum length for filepaths (Linux PATH_MAX default value)
#define MAX_SCISSOR_STACK_SIZE 8 // Maximum number of nested scissor calls supported
#define MAX_KEYBOARD_KEYS 512 // Maximum number of keyboard keys supported #define MAX_KEYBOARD_KEYS 512 // Maximum number of keyboard keys supported
#define MAX_MOUSE_BUTTONS 8 // Maximum number of mouse buttons supported #define MAX_MOUSE_BUTTONS 8 // Maximum number of mouse buttons supported
#define MAX_GAMEPADS 4 // Maximum number of gamepads supported #define MAX_GAMEPADS 4 // Maximum number of gamepads supported

View File

@ -1027,6 +1027,7 @@ RLAPI void EndShaderMode(void); // End custom
RLAPI void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied, subtract, custom) RLAPI void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied, subtract, custom)
RLAPI void EndBlendMode(void); // End blending mode (reset to default: alpha blending) RLAPI void EndBlendMode(void); // End blending mode (reset to default: alpha blending)
RLAPI void BeginScissorMode(int x, int y, int width, int height); // Begin scissor mode (define screen area for following drawing) RLAPI void BeginScissorMode(int x, int y, int width, int height); // Begin scissor mode (define screen area for following drawing)
RLAPI Rectangle GetScissorRect(void); // Get active scissor region (or entire render area, if scissor mode not enabled)
RLAPI void EndScissorMode(void); // End scissor mode RLAPI void EndScissorMode(void); // End scissor mode
RLAPI void BeginVrStereoMode(VrStereoConfig config); // Begin stereo rendering (requires VR simulator) RLAPI void BeginVrStereoMode(VrStereoConfig config); // Begin stereo rendering (requires VR simulator)
RLAPI void EndVrStereoMode(void); // End stereo rendering (requires VR simulator) RLAPI void EndVrStereoMode(void); // End stereo rendering (requires VR simulator)

View File

@ -196,6 +196,10 @@ __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigne
#endif #endif
#endif #endif
#ifndef MAX_SCISSOR_STACK_SIZE
#define MAX_SCISSOR_STACK_SIZE 8 // Maximum number of nested scissor calls supported
#endif
#ifndef MAX_KEYBOARD_KEYS #ifndef MAX_KEYBOARD_KEYS
#define MAX_KEYBOARD_KEYS 512 // Maximum number of keyboard keys supported #define MAX_KEYBOARD_KEYS 512 // Maximum number of keyboard keys supported
#endif #endif
@ -266,6 +270,8 @@ typedef struct CoreData {
Size currentFbo; // Current render width and height (depends on active fbo) Size currentFbo; // Current render width and height (depends on active fbo)
Size render; // Framebuffer width and height (render area, including black bars if required) Size render; // Framebuffer width and height (render area, including black bars if required)
Point renderOffset; // Offset from render area (must be divided by 2) Point renderOffset; // Offset from render area (must be divided by 2)
Rectangle scissorStack[MAX_SCISSOR_STACK_SIZE];// Scissor stack for nested scissor calls
int scissorStackCounter; // Scissor stack counter
Size screenMin; // Screen minimum width and height (for resizable window) Size screenMin; // Screen minimum width and height (for resizable window)
Size screenMax; // Screen maximum width and height (for resizable window) Size screenMax; // Screen maximum width and height (for resizable window)
Matrix screenScale; // Matrix to scale screen (framebuffer rendering) Matrix screenScale; // Matrix to scale screen (framebuffer rendering)
@ -1085,38 +1091,96 @@ void EndBlendMode(void)
rlSetBlendMode(BLEND_ALPHA); rlSetBlendMode(BLEND_ALPHA);
} }
static void SetScissorRectDPIAware(Rectangle scissorRect)
{
#if defined(__APPLE__)
if (!CORE.Window.usingFbo)
{
Vector2 scale = GetWindowScaleDPI();
rlScissor(
(int)(scissorRect.x*scale.x),
(int)(GetScreenHeight()*scale.y - ((scissorRect.y + scissorRect.height)*scale.y)),
(int)(scissorRect.width*scale.x),
(int)(scissorRect.height*scale.y)
);
}
#else
if (!CORE.Window.usingFbo && ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0))
{
Vector2 scale = GetWindowScaleDPI();
rlScissor(
(int)(scissorRect.x*scale.x),
(int)(CORE.Window.currentFbo.height - (scissorRect.y + scissorRect.height)*scale.y),
(int)(scissorRect.width*scale.x),
(int)(scissorRect.height*scale.y)
);
}
#endif
else
{
rlScissor(
scissorRect.x,
CORE.Window.currentFbo.height - (scissorRect.y + scissorRect.height),
scissorRect.width,
scissorRect.height
);
}
}
// Begin scissor mode (define screen area for following drawing) // Begin scissor mode (define screen area for following drawing)
// NOTE: Scissor rec refers to bottom-left corner, we change it to upper-left // NOTE: Scissor rec refers to bottom-left corner, we change it to upper-left
void BeginScissorMode(int x, int y, int width, int height) void BeginScissorMode(int x, int y, int width, int height)
{ {
rlDrawRenderBatchActive(); // Update and draw internal render batch rlDrawRenderBatchActive(); // Update and draw internal render batch
rlEnableScissorTest(); // Counter > MAX_SCISSOR_STACK_SIZE isn't possible without a bug in Raylib, but check anyway to be safe
if (CORE.Window.scissorStackCounter >= MAX_SCISSOR_STACK_SIZE)
{
TRACELOG(LOG_ERROR, "SYSTEM: Scissor stack overflow (MAX_SCISSOR_STACK_SIZE)");
return;
}
#if defined(__APPLE__) if (CORE.Window.scissorStackCounter == 0)
if (!CORE.Window.usingFbo)
{ {
Vector2 scale = GetWindowScaleDPI(); rlEnableScissorTest();
rlScissor((int)(x*scale.x), (int)(GetScreenHeight()*scale.y - (((y + height)*scale.y))), (int)(width*scale.x), (int)(height*scale.y));
} }
#else
if (!CORE.Window.usingFbo && ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0)) Rectangle scissorRect = (Rectangle){ x, y, width, height };
{ SetScissorRectDPIAware(scissorRect);
Vector2 scale = GetWindowScaleDPI();
rlScissor((int)(x*scale.x), (int)(CORE.Window.currentFbo.height - (y + height)*scale.y), (int)(width*scale.x), (int)(height*scale.y)); CORE.Window.scissorStack[CORE.Window.scissorStackCounter] = scissorRect;
} CORE.Window.scissorStackCounter++;
#endif }
else
{ // Get active scissor region (or entire render area, if scissor mode not enabled)
rlScissor(x, CORE.Window.currentFbo.height - (y + height), width, height); Rectangle GetScissorRect(void)
{
if (CORE.Window.scissorStackCounter > 0) {
return CORE.Window.scissorStack[CORE.Window.scissorStackCounter - 1];
} else {
return (Rectangle){ 0, 0, CORE.Window.currentFbo.width, CORE.Window.currentFbo.height };
} }
} }
// End scissor mode // End scissor mode
void EndScissorMode(void) void EndScissorMode(void)
{ {
// Counter < 0 isn't possible without a bug in Raylib, but check anyway to be safe
if (CORE.Window.scissorStackCounter <= 0)
{
TRACELOG(LOG_ERROR, "SYSTEM: Scissor stack empty, are you sure your EndScissorMode calls match your BeginScissorMode calls?");
return;
}
rlDrawRenderBatchActive(); // Update and draw internal render batch rlDrawRenderBatchActive(); // Update and draw internal render batch
rlDisableScissorTest();
CORE.Window.scissorStackCounter--;
if (CORE.Window.scissorStackCounter > 0) {
Rectangle scissorRect = CORE.Window.scissorStack[CORE.Window.scissorStackCounter - 1];
SetScissorRectDPIAware(scissorRect);
} else {
rlDisableScissorTest();
}
} }
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------