Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,7 @@ SHAPES = \
shapes/shapes_lines_bezier \
shapes/shapes_logo_raylib \
shapes/shapes_logo_raylib_anim \
shapes/shapes_pie_chart \
shapes/shapes_rectangle_advanced \
shapes/shapes_rectangle_scaling \
shapes/shapes_ring_drawing \
Expand Down
4 changes: 4 additions & 0 deletions examples/Makefile.Web
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,7 @@ SHAPES = \
shapes/shapes_lines_bezier \
shapes/shapes_logo_raylib \
shapes/shapes_logo_raylib_anim \
shapes/shapes_pie_chart \
shapes/shapes_rectangle_advanced \
shapes/shapes_rectangle_scaling \
shapes/shapes_ring_drawing \
Expand Down Expand Up @@ -862,6 +863,9 @@ shapes/shapes_logo_raylib: shapes/shapes_logo_raylib.c
shapes/shapes_logo_raylib_anim: shapes/shapes_logo_raylib_anim.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)

shapes/shapes_pie_chart: shapes/shapes_pie_chart.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)

shapes/shapes_rectangle_advanced: shapes/shapes_rectangle_advanced.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)

Expand Down
5 changes: 3 additions & 2 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ You may find it easier to use than other toolchains, especially when it comes to
- `zig build [module]` to compile all examples for a module (e.g. `zig build core`)
- `zig build [example]` to compile _and run_ a particular example (e.g. `zig build core_basic_window`)

## EXAMPLES COLLECTION [TOTAL: 172]
## EXAMPLES COLLECTION [TOTAL: 173]

### category: core [40]

Expand Down Expand Up @@ -66,7 +66,7 @@ Examples using raylib[core](../src/rcore.c) platform functionality like window c
| [core_undo_redo](core/core_undo_redo.c) | <img src="core/core_undo_redo.png" alt="core_undo_redo" width="80"> | ⭐⭐⭐☆ | 5.5 | 5.6 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_input_actions](core/core_input_actions.c) | <img src="core/core_input_actions.png" alt="core_input_actions" width="80"> | ⭐⭐☆☆ | 5.5 | 5.6 | [Jett](https://github.com/JettMonstersGoBoom) |

### category: shapes [23]
### category: shapes [24]

Examples using raylib shapes drawing functionality, provided by raylib [shapes](../src/rshapes.c) module.

Expand Down Expand Up @@ -95,6 +95,7 @@ Examples using raylib shapes drawing functionality, provided by raylib [shapes](
| [shapes_double_pendulum](shapes/shapes_double_pendulum.c) | <img src="shapes/shapes_double_pendulum.png" alt="shapes_double_pendulum" width="80"> | ⭐⭐☆☆ | 5.5 | 5.5 | [JoeCheong](https://github.com/Joecheong2006) |
| [shapes_dashed_line](shapes/shapes_dashed_line.c) | <img src="shapes/shapes_dashed_line.png" alt="shapes_dashed_line" width="80"> | ⭐☆☆☆ | 5.5 | 5.5 | [Luís Almeida](https://github.com/luis605) |
| [shapes_vector_angle](shapes/shapes_vector_angle.c) | <img src="shapes/shapes_vector_angle.png" alt="shapes_vector_angle" width="80"> | ⭐⭐☆☆ | 1.0 | 5.0 | [Ramon Santamaria](https://github.com/raysan5) |
| [shapes_pie_chart](shapes/shapes_pie_chart.c) | <img src="shapes/shapes_pie_chart.png" alt="shapes_pie_chart" width="80"> | ⭐☆☆☆ | 5.5 | 5.6 | [Gideon Serfontein](https://github.com/GideonSerf) |

### category: textures [26]

Expand Down
1 change: 1 addition & 0 deletions examples/examples_list.txt
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ shapes;shapes_digital_clock;★★★★;5.5;5.6;2025;2025;"Hamza RAHAL";@hmz-rh
shapes;shapes_double_pendulum;★★☆☆;5.5;5.5;2025;2025;"JoeCheong";@Joecheong2006
shapes;shapes_dashed_line;★☆☆☆;5.5;5.5;2025;2025;"Luís Almeida";@luis605
shapes;shapes_vector_angle;★★☆☆;1.0;5.0;2023;2025;"Ramon Santamaria";@raysan5
shapes;shapes_pie_chart;★☆☆☆;5.5;5.6;2025;2025;"Gideon Serfontein";@GideonSerf
textures;textures_logo_raylib;★☆☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5
textures;textures_srcrec_dstrec;★★★☆;1.3;1.3;2015;2025;"Ramon Santamaria";@raysan5
textures;textures_image_drawing;★★☆☆;1.4;1.4;2016;2025;"Ramon Santamaria";@raysan5
Expand Down
224 changes: 224 additions & 0 deletions examples/shapes/shapes_pie_chart.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
/*******************************************************************************************
*
* raylib [shapes] example - pie chart
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
*
* Example contributed by Gideon Serfontein (@GideonSerf) and reviewed by Ramon Santamaria (@raysan5)
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2025 Gideon Serfontein (@GideonSerf)
*
********************************************************************************************/

#include "raylib.h"
#include <math.h>
#include <stdio.h>

#define RAYGUI_IMPLEMENTATION
#include "raygui.h"

//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;

InitWindow(screenWidth, screenHeight, "raylib [shapes] example - interactive pie chart");

#define MAX_SLICES 10
int sliceCount = 7;
float values[MAX_SLICES] = {300.0f, 100.0f, 450.0f, 350.0f, 600.0f, 380.0f, 750.0f}; //initial slice values
char labels[MAX_SLICES][32];
bool editingLabel[MAX_SLICES] = {false};

for (int i = 0; i < MAX_SLICES; i++)
snprintf(labels[i], 32, "Slice %i", i + 1);

bool showValues = true;
bool showPercentages = false;
int hoveredSlice = -1;
Rectangle scrollPanelBounds = {0};
Vector2 scrollContentOffset = {0};
Rectangle view = {0};

SetTargetFPS(60);
//--------------------------------------------------------------------------------------

// Main game loop
while (!WindowShouldClose())
{
// Update
//----------------------------------------------------------------------------------
//UI layout parameters
const int panelWidth = 270;
const int panelMargin = 5;

// UI Panel top-left anchor
const Vector2 panelPos = {
(float)screenWidth - panelMargin - panelWidth,
(float)panelMargin
};

// UI Panel rectangle
const Rectangle panelRect = {
panelPos.x, panelPos.y,
(float)panelWidth,
(float)screenHeight - 2.0f*panelMargin
};

// Pie chart geometry
const Rectangle canvas = { 0, 0, panelPos.x, (float)screenHeight };
const Vector2 center = {canvas.width / 2.0f, canvas.height / 2.0f};
const float radius = 205.0f;

// Calculate total value for percentage calculations
float totalValue = 0.0f;
for (int i = 0; i < sliceCount; i++)
totalValue += values[i];

// Check for mouse hover over slices
hoveredSlice = -1; // Reset hovered slice
Vector2 mousePos = GetMousePosition();
if (CheckCollisionPointRec(mousePos, canvas)) // Only check if mouse is inside the canvas
{
float dx = mousePos.x - center.x;
float dy = mousePos.y - center.y;
float distance = sqrtf(dx * dx + dy * dy);

if (distance <= radius) // Inside the pie radius
{
float angle = atan2f(dy, dx) * RAD2DEG;
if (angle < 0)
angle += 360;

float currentAngle = 0.0f;
for (int i = 0; i < sliceCount; i++)
{
float sweep = (totalValue > 0) ? (values[i] / totalValue) * 360.0f : 0.0f;
if (angle >= currentAngle && angle < (currentAngle + sweep))
{
hoveredSlice = i;
break;
}
currentAngle += sweep;
}
}
}
//----------------------------------------------------------------------------------

// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);

// Draw the pie chart on the canvas
//------------------------------------------------------------------------------
float startAngle = 0.0f;
for (int i = 0; i < sliceCount; i++)
{
float sweepAngle = (totalValue > 0) ? (values[i] / totalValue) * 360.0f : 0.0f;
float midAngle = startAngle + sweepAngle / 2.0f; // Middle angle for label positioning

Color color = ColorFromHSV((float)i / sliceCount * 360.0f, 0.75f, 0.9f);
float currentRadius = radius;

// Make the hovered slice pop out by adding 5 pixels to its radius
if (i == hoveredSlice)
currentRadius += 5.0f;

// Draw the pie slice using raylib's DrawCircleSector function
DrawCircleSector(center, currentRadius, startAngle, startAngle + sweepAngle, 120, color);

// Draw the label for the current slice
if (values[i] > 0)
{
char labelText[64];
if (showValues && showPercentages)
snprintf(labelText, 64, "%.1f (%.0f%%)", values[i], (values[i] / totalValue) * 100.0f);
else if (showValues)
snprintf(labelText, 64, "%.1f", values[i]);
else if (showPercentages)
snprintf(labelText, 64, "%.0f%%", (values[i] / totalValue) * 100.0f);
else
labelText[0] = '\0';

Vector2 textSize = MeasureTextEx(GetFontDefault(), labelText, 18, 1);
float labelRadius = radius * 0.7f;
Vector2 labelPos = {
center.x + cosf(midAngle * DEG2RAD) * labelRadius - textSize.x / 2,
center.y + sinf(midAngle * DEG2RAD) * labelRadius - textSize.y / 2};
DrawText(labelText, (int)labelPos.x, (int)labelPos.y, 18, WHITE);
}

startAngle += sweepAngle;
}
//------------------------------------------------------------------------------

// UI control panel
//------------------------------------------------------------------------------
DrawRectangleRec(panelRect, Fade(LIGHTGRAY, 0.5f));
DrawRectangleLinesEx(panelRect, 1.0f, GRAY);

int currentY = (int)panelPos.y + 12; // Start a bit lower for margin

GuiSpinner((Rectangle){ panelPos.x + 95, (float)currentY, 125, 25 }, "Slices ", &sliceCount, 1, MAX_SLICES, false);
currentY += 40;

GuiCheckBox((Rectangle){ panelPos.x + 20, (float)currentY, 20, 20 }, "Show Values", &showValues);
currentY += 30;

GuiCheckBox((Rectangle){ panelPos.x + 20, (float)currentY, 20, 20 }, "Show Percentages", &showPercentages);
currentY += 40;

GuiLine((Rectangle){ panelPos.x + 10, (float)currentY, panelRect.width - 20, 1 }, NULL);
currentY += 20;

// Scrollable area for slice editors
scrollPanelBounds = (Rectangle){ panelPos.x+panelMargin, (float)currentY, panelRect.width-panelMargin*2, panelRect.y + panelRect.height - currentY - panelMargin };
int contentHeight = sliceCount * 35;

GuiScrollPanel(scrollPanelBounds, NULL,
(Rectangle){ 0, 0, panelRect.width - 20, (float)contentHeight },
&scrollContentOffset, &view);

const float contentX = view.x + scrollContentOffset.x; // left of content
const float contentY = view.y + scrollContentOffset.y; // top of content

BeginScissorMode((int)view.x, (int)view.y, (int)view.width, (int)view.height);
for (int i = 0; i < sliceCount; i++)
{
const int rowY = (int)(contentY + 5 + i * 35);

// Color indicator
Color color = ColorFromHSV((float)i / sliceCount * 360.0f, 0.75f, 0.9f);
DrawRectangle((int)(contentX + 15), rowY + 5, 20, 20, color);

// Label textbox
if (GuiTextBox((Rectangle){contentX + 45, (float)rowY, 75, 30}, labels[i], 32, editingLabel[i]))
editingLabel[i] = !editingLabel[i];

GuiSliderBar((Rectangle){contentX + 130, (float)rowY, 110, 30},
NULL, NULL, &values[i], 0.0f, 1000.0f);
}
EndScissorMode();

EndDrawing();
//----------------------------------------------------------------------------------
}

// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------

return 0;
}
Binary file added examples/shapes/shapes_pie_chart.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading