diff --git a/Examples/Core/BasicWindow.cs b/Examples/Core/BasicWindow.cs
index 51f8d76..4180912 100644
--- a/Examples/Core/BasicWindow.cs
+++ b/Examples/Core/BasicWindow.cs
@@ -1,21 +1,28 @@
/*******************************************************************************************
*
-* raylib [core] example - Basic window
+* raylib [core] example - basic window
+*
+* Example complexity rating: [★☆☆☆] 1/4
*
* Welcome to raylib!
*
-* To test examples, just press F6 and execute raylib_compile_execute script
+* To test examples, just press F6 and execute 'raylib_compile_execute' script
* Note that compiled executable is placed in the same folder as .c file
*
+* To test the examples on Web, press F6 and execute 'raylib_compile_execute_web' script
+* Web version of the program is generated in the same folder as .c file
+*
* You can find all basic examples on C:\raylib\raylib\examples folder or
* raylib official webpage: www.raylib.com
*
* Enjoy using raylib. :)
*
-* This example has been created using raylib 1.0 (www.raylib.com)
-* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+* Example originally created with raylib 1.0, last time updated with raylib 1.0
*
-* Copyright (c) 2013-2016 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) 2013-2026 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
@@ -53,7 +60,7 @@ public class BasicWindow
BeginDrawing();
ClearBackground(Color.RayWhite);
- DrawText("Congrats! You created your first window!", 190, 200, 20, Color.Maroon);
+ DrawText("Congrats! You created your first window!", 190, 200, 20, Color.LightGray);
EndDrawing();
//----------------------------------------------------------------------------------
diff --git a/Examples/Core/Camera2dDemo.cs b/Examples/Core/Camera2dDemo.cs
index 2c2568e..1463c24 100644
--- a/Examples/Core/Camera2dDemo.cs
+++ b/Examples/Core/Camera2dDemo.cs
@@ -2,10 +2,14 @@
*
* raylib [core] example - 2d camera
*
-* This example has been created using raylib 1.5 (www.raylib.com)
-* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+* Example complexity rating: [★★☆☆] 2/4
*
-* Copyright (c) 2016 Ramon Santamaria (@raysan5)
+* Example originally created with raylib 1.5, 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-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
diff --git a/Examples/Core/Customlogging.cs b/Examples/Core/Customlogging.cs
index bf0efe7..3fdf64a 100644
--- a/Examples/Core/Customlogging.cs
+++ b/Examples/Core/Customlogging.cs
@@ -50,7 +50,7 @@ public unsafe class CustomLogging
// First thing we do is setting our custom logger to ensure everything raylib logs
// will use our own logger instead of its internal one
- Raylib.SetTraceLogCallback(&LogCustom);
+ SetTraceLogCallback(&LogCustom);
InitWindow(screenWidth, screenHeight, "raylib [core] example - custom logging");
@@ -79,7 +79,7 @@ public unsafe class CustomLogging
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow();
- Raylib.SetTraceLogCallback(&Logging.LogConsole);
+ SetTraceLogCallback(&Logging.LogConsole);
//--------------------------------------------------------------------------------------
return 0;
diff --git a/Examples/Core/DeltaTime.cs b/Examples/Core/DeltaTime.cs
new file mode 100644
index 0000000..8577636
--- /dev/null
+++ b/Examples/Core/DeltaTime.cs
@@ -0,0 +1,129 @@
+using System.Numerics;
+
+namespace Examples.Core;
+/*******************************************************************************************
+ *
+ * raylib [core] example - delta time
+ *
+ * Example complexity rating: [★☆☆☆] 1/4
+ *
+ * Example originally created with raylib 5.5, last time updated with raylib 6.0
+ *
+ * Example contributed by Robin (@RobinsAviary) and reviewed by Ramon Santamaria (@raysan5)
+ *
+ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
+ * BSD-like license that allows static linking with closed source software
+ *
+ * Copyright (c) 2025 Robin (@RobinsAviary)
+ *
+ ********************************************************************************************/
+
+using static Raylib_cs.Raylib;
+
+public class DeltaTime
+{
+ public static int Main()
+ {
+ // Initialization
+ //--------------------------------------------------------------------------------------
+ const int screenWidth = 800;
+ const int screenHeight = 450;
+
+ InitWindow(screenWidth, screenHeight, "raylib [core] example - delta time");
+
+ int currentFps = 60;
+
+ Vector2 deltaCircle = new Vector2(0, (float)screenHeight / 3.0f);
+ Vector2 frameCircle = new Vector2(0, (float)screenHeight * (2.0f / 3.0f));
+
+ SetTargetFPS(60);
+ //--------------------------------------------------------------------------------------
+
+ const float speed = 10.0f;
+ const float circleRadius = 32.0f;
+
+ // Main game loop
+ while (!WindowShouldClose())
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ // Adjust the FPS target based on the mouse wheel
+ float mouseWheel = GetMouseWheelMove();
+ if (mouseWheel != 0)
+ {
+ currentFps += (int)mouseWheel;
+ if (currentFps < 0)
+ {
+ currentFps = 0;
+ }
+ SetTargetFPS(currentFps);
+ }
+
+ // GetFrameTime() returns the time it took to draw the last frame, in seconds (usually called delta time)
+ // Uses the delta time to make the circle look like it's moving at a "consistent" speed regardless of FPS
+
+ // Multiply by 6.0 (an arbitrary value) in order to make the speed
+ // visually closer to the other circle (at 60 fps), for comparison
+ deltaCircle.X += GetFrameTime() * 6.0f * speed;
+ // This circle can move faster or slower visually depending on the FPS
+ frameCircle.X += 0.1f * speed;
+
+ // If either circle is off the screen, reset it back to the start
+ if (deltaCircle.X > screenWidth)
+ {
+ deltaCircle.X = 0;
+ }
+
+ if (frameCircle.X > screenWidth)
+ {
+ frameCircle.X = 0;
+ }
+
+ // Reset both circles positions
+ if (IsKeyPressed(KeyboardKey.R))
+ {
+ deltaCircle.X = 0;
+ frameCircle.X = 0;
+ }
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+ ClearBackground(Color.RayWhite);
+
+ // Draw both circles to the screen
+ DrawCircleV(deltaCircle, circleRadius, Color.Red);
+ DrawCircleV(frameCircle, circleRadius, Color.Blue);
+
+ // Draw the help text
+ // Determine what help text to show depending on the current FPS target
+ var fpsText = "";
+ if (currentFps <= 0)
+ {
+ fpsText = $"FPS: unlimited ({GetFPS()})";
+ }
+ else
+ {
+ fpsText = $"FPS: {GetFPS()} (target: {currentFps})";
+ }
+ DrawText(fpsText, 10, 10, 20, Color.DarkGray);
+ DrawText($"Frame time: {GetFrameTime():F2} ms", 10, 30, 20, Color.DarkGray);
+ DrawText("Use the scroll wheel to change the fps limit, r to reset", 10, 50, 20, Color.DarkGray);
+
+ // Draw the text above the circles
+ DrawText("FUNC: x += GetFrameTime()*speed", 10, 90, 20, Color.Red);
+ DrawText("FUNC: x += speed", 10, 240, 20, Color.Blue);
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+ }
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ CloseWindow();
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+ }
+}
diff --git a/Examples/Core/InputGamepad.cs b/Examples/Core/InputGamepad.cs
index 39fe911..883ab4e 100644
--- a/Examples/Core/InputGamepad.cs
+++ b/Examples/Core/InputGamepad.cs
@@ -1,19 +1,24 @@
/*******************************************************************************************
-*
-* raylib [core] example - Gamepad input
-*
-* NOTE: This example requires a Gamepad connected to the system
-* raylib is configured to work with the following gamepads:
-* - Xbox 360 Controller (Xbox 360, Xbox One)
-* - PLAYSTATION(R)3 Controller
-* Check raylib.h for buttons configuration
-*
-* This example has been created using raylib 1.6 (www.raylib.com)
-* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
-*
-* Copyright (c) 2013-2016 Ramon Santamaria (@raysan5)
-*
-********************************************************************************************/
+ *
+ * raylib [core] example - input gamepad
+ *
+ * Example complexity rating: [★☆☆☆] 1/4
+ *
+ * NOTE: This example requires a Gamepad connected to the system
+ * raylib is configured to work with the following gamepads:
+ * - Xbox 360 Controller (Xbox 360, Xbox One)
+ * - PLAYSTATION(R)3 Controller
+ * Check raylib.h for buttons configuration
+ *
+ * Example originally created with raylib 1.1, 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-2025 Ramon Santamaria (@raysan5)
+ *
+ ********************************************************************************************/
+
using System.Numerics;
using Raylib_cs;
@@ -25,10 +30,10 @@ public class InputGamepad
{
// NOTE: Gamepad name ID depends on drivers and OS
// These are some possible names the gamepads could have.
- public const string XBOX360_LEGACY_NAME_ID = "Xbox Controller";
- public const string XBOX360_NAME_ID = "Xbox 360 Controller";
- public const string XBOX360_NAME_ID_RPI = "Microsoft X-Box 360 pad";
- public const string PS3_NAME_ID = "PLAYSTATION(R)3 Controller";
+ public const string XBOX_ALIAS_1 = "xbox";
+ public const string XBOX_ALIAS_2 = "x-box";
+ public const string PS_ALIAS_1 = "playstation";
+ public const string PS_ALIAS_2 = "sony";
public static int Main()
{
@@ -47,12 +52,32 @@ public class InputGamepad
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
+ int gamepad = 0;
+ Rectangle vibrateButton = new Rectangle();
+
// Main game loop
while (!WindowShouldClose())
{
// Update
//----------------------------------------------------------------------------------
- // ...
+ if (IsKeyPressed(KeyboardKey.Left) && gamepad > 0)
+ {
+ gamepad--;
+ }
+
+ if (IsKeyPressed(KeyboardKey.Right))
+ {
+ gamepad++;
+ }
+
+ Vector2 mousePosition = GetMousePosition();
+
+ vibrateButton = new Rectangle(10, 70.0f + 20 * GetGamepadAxisCount(gamepad) + 20, 75, 24);
+ if (IsMouseButtonPressed(MouseButton.Left) && CheckCollisionPointRec(mousePosition, vibrateButton))
+ {
+ SetGamepadVibration(gamepad, 1.0f, 1.0f, 1.0f);
+ }
+
//----------------------------------------------------------------------------------
// Draw
@@ -60,50 +85,49 @@ public class InputGamepad
BeginDrawing();
ClearBackground(Color.RayWhite);
- if (IsGamepadAvailable(0))
+ if (IsGamepadAvailable(gamepad))
{
- string gamepadName = GetGamepadName_(0);
- DrawText($"GP1: {gamepadName}", 10, 10, 10, Color.Black);
+ string gamepadName = GetGamepadName_(gamepad);
+ DrawText($"GP{gamepad}: {gamepadName}", 10, 10, 10, Color.Black);
- if (gamepadName == XBOX360_LEGACY_NAME_ID ||
- gamepadName == XBOX360_NAME_ID ||
- gamepadName == XBOX360_NAME_ID_RPI)
+ if (gamepadName.Contains(XBOX_ALIAS_1, StringComparison.OrdinalIgnoreCase)||
+ gamepadName.Contains(XBOX_ALIAS_2, StringComparison.OrdinalIgnoreCase))
{
DrawTexture(texXboxPad, 0, 0, Color.DarkGray);
// Draw buttons: xbox home
- if (IsGamepadButtonDown(0, GamepadButton.Middle))
+ if (IsGamepadButtonDown(gamepad, GamepadButton.Middle))
{
DrawCircle(394, 89, 19, Color.Red);
}
// Draw buttons: basic
- if (IsGamepadButtonDown(0, GamepadButton.MiddleRight))
+ if (IsGamepadButtonDown(gamepad, GamepadButton.MiddleRight))
{
DrawCircle(436, 150, 9, Color.Red);
}
- if (IsGamepadButtonDown(0, GamepadButton.MiddleLeft))
+ if (IsGamepadButtonDown(gamepad, GamepadButton.MiddleLeft))
{
DrawCircle(352, 150, 9, Color.Red);
}
- if (IsGamepadButtonDown(0, GamepadButton.RightFaceLeft))
+ if (IsGamepadButtonDown(gamepad, GamepadButton.RightFaceLeft))
{
DrawCircle(501, 151, 15, Color.Blue);
}
- if (IsGamepadButtonDown(0, GamepadButton.RightFaceDown))
+ if (IsGamepadButtonDown(gamepad, GamepadButton.RightFaceDown))
{
DrawCircle(536, 187, 15, Color.Lime);
}
- if (IsGamepadButtonDown(0, GamepadButton.RightFaceRight))
+ if (IsGamepadButtonDown(gamepad, GamepadButton.RightFaceRight))
{
DrawCircle(572, 151, 15, Color.Maroon);
}
- if (IsGamepadButtonDown(0, GamepadButton.RightFaceUp))
+ if (IsGamepadButtonDown(gamepad, GamepadButton.RightFaceUp))
{
DrawCircle(536, 115, 15, Color.Gold);
}
@@ -111,33 +135,33 @@ public class InputGamepad
// Draw buttons: d-pad
DrawRectangle(317, 202, 19, 71, Color.Black);
DrawRectangle(293, 228, 69, 19, Color.Black);
- if (IsGamepadButtonDown(0, GamepadButton.LeftFaceUp))
+ if (IsGamepadButtonDown(gamepad, GamepadButton.LeftFaceUp))
{
DrawRectangle(317, 202, 19, 26, Color.Red);
}
- if (IsGamepadButtonDown(0, GamepadButton.LeftFaceDown))
+ if (IsGamepadButtonDown(gamepad, GamepadButton.LeftFaceDown))
{
DrawRectangle(317, 202 + 45, 19, 26, Color.Red);
}
- if (IsGamepadButtonDown(0, GamepadButton.LeftFaceLeft))
+ if (IsGamepadButtonDown(gamepad, GamepadButton.LeftFaceLeft))
{
DrawRectangle(292, 228, 25, 19, Color.Red);
}
- if (IsGamepadButtonDown(0, GamepadButton.LeftFaceRight))
+ if (IsGamepadButtonDown(gamepad, GamepadButton.LeftFaceRight))
{
DrawRectangle(292 + 44, 228, 26, 19, Color.Red);
}
// Draw buttons: left-right back
- if (IsGamepadButtonDown(0, GamepadButton.LeftTrigger1))
+ if (IsGamepadButtonDown(gamepad, GamepadButton.LeftTrigger1))
{
DrawCircle(259, 61, 20, Color.Red);
}
- if (IsGamepadButtonDown(0, GamepadButton.RightTrigger1))
+ if (IsGamepadButtonDown(gamepad, GamepadButton.RightTrigger1))
{
DrawCircle(536, 61, 20, Color.Red);
}
@@ -146,8 +170,8 @@ public class InputGamepad
DrawCircle(259, 152, 39, Color.Black);
DrawCircle(259, 152, 34, Color.LightGray);
DrawCircle(
- 259 + (int)(GetGamepadAxisMovement(0, GamepadAxis.LeftX) * 20),
- 152 + (int)(GetGamepadAxisMovement(0, GamepadAxis.LeftY) * 20),
+ 259 + (int)(GetGamepadAxisMovement(gamepad, GamepadAxis.LeftX) * 20),
+ 152 + (int)(GetGamepadAxisMovement(gamepad, GamepadAxis.LeftY) * 20),
25,
Color.Black
);
@@ -156,36 +180,36 @@ public class InputGamepad
DrawCircle(461, 237, 38, Color.Black);
DrawCircle(461, 237, 33, Color.LightGray);
DrawCircle(
- 461 + (int)(GetGamepadAxisMovement(0, GamepadAxis.RightX) * 20),
- 237 + (int)(GetGamepadAxisMovement(0, GamepadAxis.RightY) * 20),
+ 461 + (int)(GetGamepadAxisMovement(gamepad, GamepadAxis.RightX) * 20),
+ 237 + (int)(GetGamepadAxisMovement(gamepad, GamepadAxis.RightY) * 20),
25, Color.Black
);
// Draw axis: left-right triggers
- float leftTriggerX = GetGamepadAxisMovement(0, GamepadAxis.LeftTrigger);
- float rightTriggerX = GetGamepadAxisMovement(0, GamepadAxis.RightTrigger);
+ float leftTriggerX = GetGamepadAxisMovement(gamepad, GamepadAxis.LeftTrigger);
+ float rightTriggerX = GetGamepadAxisMovement(gamepad, GamepadAxis.RightTrigger);
DrawRectangle(170, 30, 15, 70, Color.Gray);
DrawRectangle(604, 30, 15, 70, Color.Gray);
DrawRectangle(170, 30, 15, (int)(((1.0f + leftTriggerX) / 2.0f) * 70), Color.Red);
DrawRectangle(604, 30, 15, (int)(((1.0f + rightTriggerX) / 2.0f) * 70), Color.Red);
}
- else if (gamepadName == PS3_NAME_ID)
+ else if (gamepadName.Contains(PS_ALIAS_1, StringComparison.OrdinalIgnoreCase) || gamepadName.Contains(PS_ALIAS_2, StringComparison.OrdinalIgnoreCase))
{
DrawTexture(texPs3Pad, 0, 0, Color.DarkGray);
// Draw buttons: ps
- if (IsGamepadButtonDown(0, GamepadButton.Middle))
+ if (IsGamepadButtonDown(gamepad, GamepadButton.Middle))
{
DrawCircle(396, 222, 13, Color.Red);
}
// Draw buttons: basic
- if (IsGamepadButtonDown(0, GamepadButton.MiddleLeft))
+ if (IsGamepadButtonDown(gamepad, GamepadButton.MiddleLeft))
{
DrawRectangle(328, 170, 32, 13, Color.Red);
}
- if (IsGamepadButtonDown(0, GamepadButton.MiddleRight))
+ if (IsGamepadButtonDown(gamepad, GamepadButton.MiddleRight))
{
DrawTriangle(
new Vector2(436, 168),
@@ -195,22 +219,22 @@ public class InputGamepad
);
}
- if (IsGamepadButtonDown(0, GamepadButton.RightFaceUp))
+ if (IsGamepadButtonDown(gamepad, GamepadButton.RightFaceUp))
{
DrawCircle(557, 144, 13, Color.Lime);
}
- if (IsGamepadButtonDown(0, GamepadButton.RightFaceRight))
+ if (IsGamepadButtonDown(gamepad, GamepadButton.RightFaceRight))
{
DrawCircle(586, 173, 13, Color.Red);
}
- if (IsGamepadButtonDown(0, GamepadButton.RightFaceDown))
+ if (IsGamepadButtonDown(gamepad, GamepadButton.RightFaceDown))
{
DrawCircle(557, 203, 13, Color.Violet);
}
- if (IsGamepadButtonDown(0, GamepadButton.RightFaceLeft))
+ if (IsGamepadButtonDown(gamepad, GamepadButton.RightFaceLeft))
{
DrawCircle(527, 173, 13, Color.Pink);
}
@@ -218,33 +242,33 @@ public class InputGamepad
// Draw buttons: d-pad
DrawRectangle(225, 132, 24, 84, Color.Black);
DrawRectangle(195, 161, 84, 25, Color.Black);
- if (IsGamepadButtonDown(0, GamepadButton.LeftFaceUp))
+ if (IsGamepadButtonDown(gamepad, GamepadButton.LeftFaceUp))
{
DrawRectangle(225, 132, 24, 29, Color.Red);
}
- if (IsGamepadButtonDown(0, GamepadButton.LeftFaceDown))
+ if (IsGamepadButtonDown(gamepad, GamepadButton.LeftFaceDown))
{
DrawRectangle(225, 132 + 54, 24, 30, Color.Red);
}
- if (IsGamepadButtonDown(0, GamepadButton.LeftFaceLeft))
+ if (IsGamepadButtonDown(gamepad, GamepadButton.LeftFaceLeft))
{
DrawRectangle(195, 161, 30, 25, Color.Red);
}
- if (IsGamepadButtonDown(0, GamepadButton.LeftFaceRight))
+ if (IsGamepadButtonDown(gamepad, GamepadButton.LeftFaceRight))
{
DrawRectangle(195 + 54, 161, 30, 25, Color.Red);
}
// Draw buttons: left-right back buttons
- if (IsGamepadButtonDown(0, GamepadButton.LeftTrigger1))
+ if (IsGamepadButtonDown(gamepad, GamepadButton.LeftTrigger1))
{
DrawCircle(239, 82, 20, Color.Red);
}
- if (IsGamepadButtonDown(0, GamepadButton.RightTrigger1))
+ if (IsGamepadButtonDown(gamepad, GamepadButton.RightTrigger1))
{
DrawCircle(557, 82, 20, Color.Red);
}
@@ -253,8 +277,8 @@ public class InputGamepad
DrawCircle(319, 255, 35, Color.Black);
DrawCircle(319, 255, 31, Color.LightGray);
DrawCircle(
- 319 + (int)(GetGamepadAxisMovement(0, GamepadAxis.LeftX) * 20),
- 255 + (int)(GetGamepadAxisMovement(0, GamepadAxis.LeftY) * 20),
+ 319 + (int)(GetGamepadAxisMovement(gamepad, GamepadAxis.LeftX) * 20),
+ 255 + (int)(GetGamepadAxisMovement(gamepad, GamepadAxis.LeftY) * 20),
25,
Color.Black
);
@@ -263,15 +287,15 @@ public class InputGamepad
DrawCircle(475, 255, 35, Color.Black);
DrawCircle(475, 255, 31, Color.LightGray);
DrawCircle(
- 475 + (int)(GetGamepadAxisMovement(0, GamepadAxis.RightX) * 20),
- 255 + (int)(GetGamepadAxisMovement(0, GamepadAxis.RightY) * 20),
+ 475 + (int)(GetGamepadAxisMovement(gamepad, GamepadAxis.RightX) * 20),
+ 255 + (int)(GetGamepadAxisMovement(gamepad, GamepadAxis.RightY) * 20),
25,
Color.Black
);
// Draw axis: left-right triggers
- float leftTriggerX = GetGamepadAxisMovement(0, GamepadAxis.LeftTrigger);
- float rightTriggerX = GetGamepadAxisMovement(0, GamepadAxis.RightTrigger);
+ float leftTriggerX = GetGamepadAxisMovement(gamepad, GamepadAxis.LeftTrigger);
+ float rightTriggerX = GetGamepadAxisMovement(gamepad, GamepadAxis.RightTrigger);
DrawRectangle(169, 48, 15, 70, Color.Gray);
DrawRectangle(611, 48, 15, 70, Color.Gray);
DrawRectangle(169, 48, 15, (int)(((1.0f - leftTriggerX) / 2.0f) * 70), Color.Red);
@@ -283,12 +307,12 @@ public class InputGamepad
// TODO: Draw generic gamepad
}
- DrawText($"DETECTED AXIS [{GetGamepadAxisCount(0)}]:", 10, 50, 10, Color.Maroon);
+ DrawText($"DETECTED AXIS [{GetGamepadAxisCount(gamepad)}]:", 10, 50, 10, Color.Maroon);
- for (int i = 0; i < GetGamepadAxisCount(0); i++)
+ for (int i = 0; i < GetGamepadAxisCount(gamepad); i++)
{
DrawText(
- $"AXIS {i}: {GetGamepadAxisMovement(0, (GamepadAxis)i)}",
+ $"AXIS {i}: {GetGamepadAxisMovement(gamepad, (GamepadAxis)i)}",
20,
70 + 20 * i,
10,
@@ -296,6 +320,10 @@ public class InputGamepad
);
}
+ DrawRectangleRec(vibrateButton, Color.SkyBlue);
+ DrawText("VIBRATE", (int)(vibrateButton.X + 14), (int)(vibrateButton.Y + 1), 10, Color.DarkGray);
+
+
if (GetGamepadButtonPressed() != (int)GamepadButton.Unknown)
{
DrawText($"DETECTED BUTTON: {GetGamepadButtonPressed()}", 10, 430, 10, Color.Red);
@@ -307,7 +335,7 @@ public class InputGamepad
}
else
{
- DrawText("GP1: NOT DETECTED", 10, 10, 10, Color.Gray);
+ DrawText($"GP{gamepad}: NOT DETECTED", 10, 10, 10, Color.Gray);
DrawTexture(texXboxPad, 0, 0, Color.LightGray);
}
diff --git a/Examples/Core/InputGestures.cs b/Examples/Core/InputGestures.cs
index 8367e9e..fda7d5c 100644
--- a/Examples/Core/InputGestures.cs
+++ b/Examples/Core/InputGestures.cs
@@ -1,11 +1,15 @@
/*******************************************************************************************
*
-* raylib [core] example - Gestures Detection
+* raylib [core] example - input gestures
*
-* This example has been created using raylib 1.4 (www.raylib.com)
-* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+* Example complexity rating: [★★☆☆] 2/4
*
-* Copyright (c) 2016 Ramon Santamaria (@raysan5)
+* 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-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
@@ -25,7 +29,7 @@ public class InputGestures
const int screenWidth = 800;
const int screenHeight = 450;
- InitWindow(screenWidth, screenHeight, "raylib [core] example - gestures detection");
+ InitWindow(screenWidth, screenHeight, "raylib [core] example - input gestures");
Vector2 touchPosition = new(0, 0);
Rectangle touchArea = new(220, 10, screenWidth - 230, screenHeight - 20);
diff --git a/Examples/Core/InputGesturesTestBed.cs b/Examples/Core/InputGesturesTestBed.cs
new file mode 100644
index 0000000..6595051
--- /dev/null
+++ b/Examples/Core/InputGesturesTestBed.cs
@@ -0,0 +1,434 @@
+/*******************************************************************************************
+ *
+ * raylib [core] example - input gestures testbed
+ *
+ * Example complexity rating: [★★★☆] 3/4
+ *
+ * Example originally created with raylib 5.0, last time updated with raylib 6.0
+ *
+ * Example contributed by ubkp (@ubkp) 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) 2023-2025 ubkp (@ubkp)
+ *
+ ********************************************************************************************/
+
+using System.Numerics;
+
+namespace Examples.Core;
+
+using static Raylib_cs.Raylib;
+
+public class InputGesturesTestBed
+{
+ public const int GESTURE_LOG_SIZE = 20;
+ public const int MAX_TOUCH_COUNT = 32;
+
+ //------------------------------------------------------------------------------------
+ // Program main entry point
+ //------------------------------------------------------------------------------------
+
+ public static int Main()
+ {
+// Initialization
+ //--------------------------------------------------------------------------------------
+ const int screenWidth = 800;
+ const int screenHeight = 450;
+
+ InitWindow(screenWidth, screenHeight, "raylib [core] example - input gestures testbed");
+
+ Vector2 messagePosition = new Vector2( 160, 7 );
+
+ // Last gesture variables definitions
+ Gesture lastGesture = 0;
+ Vector2 lastGesturePosition = new Vector2( 165, 130 );
+
+ // Gesture log variables definitions
+ // NOTE: The gesture log uses an array (as an inverted circular queue) to store the performed gestures
+ string[] gestureLog = new string[GESTURE_LOG_SIZE + 1];
+ for (int i= 0; i < GESTURE_LOG_SIZE; i++)
+ {
+ gestureLog[i] = new string(new char[12]);
+ }
+ ;
+ // NOTE: The index for the inverted circular queue (moving from last to first direction, then looping around)
+ int gestureLogIndex = GESTURE_LOG_SIZE;
+ Gesture previousGesture = 0;
+
+ // Log mode values:
+ // - 0 shows repeated events
+ // - 1 hides repeated events
+ // - 2 shows repeated events but hide hold events
+ // - 3 hides repeated events and hide hold events
+ int logMode = 1;
+
+ Color gestureColor = new Color(0, 0, 0, 255 );
+ Rectangle logButton1 = new Rectangle( 53, 7, 48, 26 );
+ Rectangle logButton2 = new Rectangle( 108, 7, 36, 26 );
+ Vector2 gestureLogPosition = new Vector2( 10, 10 );
+
+ // Protractor variables definitions
+ float angleLength = 90.0f;
+ float currentAngleDegrees = 0.0f;
+ Vector2 finalVector = new Vector2( 0.0f, 0.0f );
+ Vector2 protractorPosition = new Vector2( 266.0f, 315.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
+ //--------------------------------------------------------------------------------------
+ // Handle common gestures data
+ int i, ii; // Iterators that will be reused by all for loops
+ Gesture currentGesture = GetGestureDetected();
+ float currentDragDegrees = GetGestureDragAngle();
+ float currentPitchDegrees = GetGesturePinchAngle();
+ int touchCount = GetTouchPointCount();
+
+ // Handle last gesture
+ if ((currentGesture != 0) && ((int)currentGesture != 4) && (currentGesture != previousGesture))
+ {
+ lastGesture = currentGesture; // Filter the meaningful gestures (1, 2, 8 to 512) for the display
+ }
+
+ // Handle gesture log
+ if (IsMouseButtonReleased(MouseButton.Left))
+ {
+ if (CheckCollisionPointRec(GetMousePosition(), logButton1))
+ {
+ switch (logMode)
+ {
+ case 3: logMode = 2; break;
+ case 2: logMode = 3; break;
+ case 1: logMode = 0; break;
+ default: logMode = 1; break;
+ }
+ }
+ else if (CheckCollisionPointRec(GetMousePosition(), logButton2))
+ {
+ switch (logMode)
+ {
+ case 3: logMode = 1; break;
+ case 2: logMode = 0; break;
+ case 1: logMode = 3; break;
+ default: logMode = 2; break;
+ }
+ }
+ }
+
+ int fillLog = 0; // Gate variable to be used to allow or not the gesture log to be filled
+ if (currentGesture != 0)
+ {
+ if (logMode == 3) // 3 hides repeated events and hide hold events
+ {
+ if ((((int)currentGesture != 4) && (currentGesture != previousGesture)) || ((int)currentGesture < 3))
+ {
+ fillLog = 1;
+ }
+ }
+ else if (logMode == 2) // 2 shows repeated events but hide hold events
+ {
+ if ((int)currentGesture != 4)
+ {
+ fillLog = 1;
+ }
+ }
+ else if (logMode == 1) // 1 hides repeated events
+ {
+ if (currentGesture != previousGesture)
+ {
+ fillLog = 1;
+ }
+ }
+ else // 0 shows repeated events
+ {
+ fillLog = 1;
+ }
+ }
+
+ if (fillLog > 0) // If one of the conditions from logMode was met, fill the gesture log
+ {
+ previousGesture = currentGesture;
+ gestureColor = GetGestureColor((int)currentGesture);
+ if (gestureLogIndex <= 0)
+ {
+ gestureLogIndex = GESTURE_LOG_SIZE;
+ }
+ gestureLogIndex--;
+
+ // Copy the gesture respective name to the gesture log array
+ gestureLog[gestureLogIndex] = GetGestureName((int)currentGesture);
+ }
+
+ // Handle protractor
+ if ((int)currentGesture > 255)
+ {
+ currentAngleDegrees = currentPitchDegrees; // Pinch In and Pinch Out
+ }
+ else if ((int)currentGesture > 15)
+ {
+ currentAngleDegrees = currentDragDegrees; // Swipe Right, Swipe Left, Swipe Up and Swipe Down
+ }
+ else if (currentGesture > 0)
+ {
+ currentAngleDegrees = 0.0f; // Tap, Doubletap, Hold and Grab
+ }
+
+ float currentAngleRadians =
+ ((currentAngleDegrees + 90.0f) * MathF.PI / 180); // Convert the current angle to Radians
+ // Calculate the final vector for display
+ finalVector = new Vector2(
+ (angleLength * MathF.Sin(currentAngleRadians)) + protractorPosition.X,
+ (angleLength * MathF.Cos(currentAngleRadians)) + protractorPosition.Y
+ )
+ ;
+
+ // Handle touch and mouse pointer points
+ Vector2[] touchPosition = new Vector2[MAX_TOUCH_COUNT];
+
+ Vector2 mousePosition = Vector2.Zero;
+ if (currentGesture != Gesture.None)
+ {
+ if (touchCount != 0)
+ {
+ for (i = 0; i < touchCount; i++)
+ {
+ touchPosition[i] = GetTouchPosition(i); // Fill the touch positions
+ }
+ }
+ else
+ {
+ mousePosition = GetMousePosition();
+ }
+ }
+ //--------------------------------------------------------------------------------------
+
+ // Draw
+ //--------------------------------------------------------------------------------------
+ BeginDrawing();
+ ClearBackground(Color.RayWhite);
+
+ // Draw common elements
+ DrawText("*", (int)messagePosition.X + 5, (int)messagePosition.Y + 5, 10, Color.Black);
+ DrawText("Example optimized for Web/HTML5\non Smartphones with Touch Screen.", (int)messagePosition.X + 15,
+ (int)messagePosition.Y + 5, 10, Color.Black);
+ DrawText("*", (int)messagePosition.X + 5, (int)messagePosition.Y + 35, 10, Color.Black);
+ DrawText("While running on Desktop Web Browsers,\ninspect and turn on Touch Emulation.",
+ (int)messagePosition.X + 15, (int)messagePosition.Y + 35, 10, Color.Black);
+
+ // Draw last gesture
+ DrawText("Last gesture", (int)lastGesturePosition.X + 33, (int)lastGesturePosition.Y - 47, 20, Color.Black);
+ DrawText("Swipe Tap Pinch Touch", (int)lastGesturePosition.X + 17,
+ (int)lastGesturePosition.Y - 18, 10, Color.Black);
+ DrawRectangle((int)lastGesturePosition.X + 20, (int)lastGesturePosition.Y, 20, 20,
+ lastGesture == Gesture.SwipeUp ? Color.Red : Color.LightGray);
+ DrawRectangle((int)lastGesturePosition.X, (int)lastGesturePosition.Y + 20, 20, 20,
+ lastGesture == Gesture.SwipeLeft ? Color.Red : Color.LightGray);
+ DrawRectangle((int)lastGesturePosition.X + 40, (int)lastGesturePosition.Y + 20, 20, 20,
+ lastGesture == Gesture.SwipeRight ? Color.Red : Color.LightGray);
+ DrawRectangle((int)lastGesturePosition.X + 20, (int)lastGesturePosition.Y + 40, 20, 20,
+ lastGesture == Gesture.SwipeDown ? Color.Red : Color.LightGray);
+ DrawCircle((int)lastGesturePosition.X + 80, (int)lastGesturePosition.Y + 16, 10,
+ lastGesture == Gesture.Tap ? Color.Blue : Color.LightGray);
+ DrawRing(new Vector2(
+ lastGesturePosition.X + 103, lastGesturePosition.Y + 16
+ ), 6.0f, 11.0f, 0.0f, 360.0f, 0, lastGesture == Gesture.Drag ? Color.Lime : Color.LightGray);
+ DrawCircle((int)lastGesturePosition.X + 80, (int)lastGesturePosition.Y + 43, 10,
+ lastGesture == Gesture.DoubleTap ? Color.SkyBlue : Color.LightGray);
+ DrawCircle((int)lastGesturePosition.X + 103, (int)lastGesturePosition.Y + 43, 10,
+ lastGesture == Gesture.DoubleTap ? Color.SkyBlue : Color.LightGray);
+ DrawTriangle(new Vector2(
+ lastGesturePosition.X + 122, lastGesturePosition.Y + 16
+ ), new Vector2(
+ lastGesturePosition.X + 137, lastGesturePosition.Y + 26
+ ), new Vector2(
+ lastGesturePosition.X + 137, lastGesturePosition.Y + 6
+ ), lastGesture == Gesture.PinchOut ? Color.Orange : Color.LightGray);
+ DrawTriangle(new Vector2(
+ lastGesturePosition.X + 147, lastGesturePosition.Y + 6
+ ), new Vector2(
+ lastGesturePosition.X + 147, lastGesturePosition.Y + 26
+ ), new Vector2(
+ lastGesturePosition.X + 162, lastGesturePosition.Y + 16
+ ), lastGesture == Gesture.PinchOut ? Color.Orange : Color.Gray);
+ DrawTriangle(new Vector2(
+ lastGesturePosition.X + 125, lastGesturePosition.Y + 33
+ ), new Vector2(
+ lastGesturePosition.X + 125, lastGesturePosition.Y + 53
+ ), new Vector2(
+ lastGesturePosition.X + 140, lastGesturePosition.Y + 43
+ ), lastGesture == Gesture.PinchIn ? Color.Violet : Color.LightGray);
+ DrawTriangle(new Vector2(
+ lastGesturePosition.X + 144, lastGesturePosition.Y + 43
+ ), new Vector2(
+ lastGesturePosition.X + 159, lastGesturePosition.Y + 53
+ ), new Vector2(
+ lastGesturePosition.X + 159, lastGesturePosition.Y + 33
+ ), lastGesture == Gesture.PinchIn ? Color.Violet : Color.LightGray);
+ for (i = 0; i < 4; i++)
+ {
+ DrawCircle((int)lastGesturePosition.X + 180, (int)lastGesturePosition.Y + 7 + i * 15, 5,
+ touchCount <= i ? Color.LightGray : gestureColor);
+ }
+
+ // Draw gesture log
+ DrawText("Log", (int)gestureLogPosition.X, (int)gestureLogPosition.Y, 20, Color.Black);
+
+ // Loop in both directions to print the gesture log array in the inverted order (and looping around if the index started somewhere in the middle)
+ for (i = 0, ii = gestureLogIndex; i < GESTURE_LOG_SIZE; i++, ii = (ii + 1) % GESTURE_LOG_SIZE)
+ {
+ DrawText(gestureLog[ii], (int)gestureLogPosition.X, (int)gestureLogPosition.Y + 410 - i * 20, 20,
+ (i == 0 ? gestureColor : Color.LightGray));
+ }
+
+ Color logButton1Color, logButton2Color;
+ switch (logMode)
+ {
+ case 3:
+ logButton1Color = Color.Maroon;
+ logButton2Color = Color.Maroon;
+ break;
+ case 2:
+ logButton1Color = Color.Gray;
+ logButton2Color = Color.Maroon;
+ break;
+ case 1:
+ logButton1Color = Color.Maroon;
+ logButton2Color = Color.Gray;
+ break;
+ default:
+ logButton1Color = Color.Gray;
+ logButton2Color = Color.Gray;
+ break;
+ }
+
+ DrawRectangleRec(logButton1, logButton1Color);
+ DrawText("Hide", (int)logButton1.X + 7, (int)logButton1.Y + 3, 10, Color.White);
+ DrawText("Repeat", (int)logButton1.X + 7, (int)logButton1.Y + 13, 10, Color.White);
+ DrawRectangleRec(logButton2, logButton2Color);
+ DrawText("Hide", (int)logButton1.X + 62, (int)logButton1.Y + 3, 10, Color.White);
+ DrawText("Hold", (int)logButton1.X + 62, (int)logButton1.Y + 13, 10, Color.White);
+
+ // Draw protractor
+ DrawText("Angle", (int)protractorPosition.X + 55, (int)protractorPosition.Y + 76, 10, Color.Black);
+
+ // Note: Official it's using raylibs functions for string manipulation. But in C# it will end up in an unsafe handling.
+ string angleString = currentAngleDegrees.ToString("F3");
+ int angleStringDot = angleString.IndexOf('.');
+ string angleStringTrim = angleString.Substring(0, angleStringDot + 3);
+
+ DrawText(angleStringTrim, (int)protractorPosition.X + 55, (int)protractorPosition.Y + 92, 20, gestureColor);
+ DrawCircleV(protractorPosition, 80.0f, Color.White);
+ DrawLineEx(new Vector2(
+ protractorPosition.X - 90, protractorPosition.Y
+ ), new Vector2(
+ protractorPosition.X + 90, protractorPosition.Y
+ ), 3.0f, Color.LightGray);
+ DrawLineEx(new Vector2(
+ protractorPosition.X, protractorPosition.Y - 90
+ ), new Vector2(
+ protractorPosition.X, protractorPosition.Y + 90
+ ), 3.0f, Color.LightGray);
+ DrawLineEx(new Vector2(
+ protractorPosition.X - 80, protractorPosition.Y - 45
+ ), new Vector2(
+ protractorPosition.X + 80, protractorPosition.Y + 45
+ ), 3.0f, Color.Green);
+ DrawLineEx(new Vector2(
+ protractorPosition.X - 80, protractorPosition.Y + 45
+ ), new Vector2(
+ protractorPosition.X + 80, protractorPosition.Y - 45
+ ), 3.0f, Color.Green);
+ DrawText("0", (int)protractorPosition.X + 96, (int)protractorPosition.Y - 9, 20, Color.Black);
+ DrawText("30", (int)protractorPosition.X + 74, (int)protractorPosition.Y - 68, 20, Color.Black);
+ DrawText("90", (int)protractorPosition.X - 11, (int)protractorPosition.Y - 110, 20, Color.Black);
+ DrawText("150", (int)protractorPosition.X - 100, (int)protractorPosition.Y - 68, 20, Color.Black);
+ DrawText("180", (int)protractorPosition.X - 124, (int)protractorPosition.Y - 9, 20, Color.Black);
+ DrawText("210", (int)protractorPosition.X - 100, (int)protractorPosition.Y + 50, 20, Color.Black);
+ DrawText("270", (int)protractorPosition.X - 18, (int)protractorPosition.Y + 92, 20, Color.Black);
+ DrawText("330", (int)protractorPosition.X + 72, (int)protractorPosition.Y + 50, 20, Color.Black);
+ if (currentAngleDegrees != 0.0f)
+ {
+ DrawLineEx(protractorPosition, finalVector, 3.0f, gestureColor);
+ }
+
+ // Draw touch and mouse pointer points
+ if (currentGesture != Gesture.None)
+ {
+ if (touchCount != 0)
+ {
+ for (i = 0; i < touchCount; i++)
+ {
+ DrawCircleV(touchPosition[i], 50.0f, Fade(gestureColor, 0.5f));
+ DrawCircleV(touchPosition[i], 5.0f, gestureColor);
+ }
+
+ if (touchCount == 2)
+ {
+ DrawLineEx(touchPosition[0], touchPosition[1], (((int)currentGesture == 512) ? 8.0f : 12.0f),
+ gestureColor);
+ }
+ }
+ else
+ {
+ DrawCircleV(mousePosition, 35.0f, Fade(gestureColor, 0.5f));
+ DrawCircleV(mousePosition, 5.0f, gestureColor);
+ }
+ }
+
+ EndDrawing();
+ //--------------------------------------------------------------------------------------
+ }
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+ }
+
+ static string GetGestureName(int gesture)
+ {
+ switch (gesture)
+ {
+ case 0: return "None"; break;
+ case 1: return "Tap"; break;
+ case 2: return "Double Tap"; break;
+ case 4: return "Hold"; break;
+ case 8: return "Drag"; break;
+ case 16: return "Swipe Right"; break;
+ case 32: return "Swipe Left"; break;
+ case 64: return "Swipe Up"; break;
+ case 128: return "Swipe Down"; break;
+ case 256: return "Pinch In"; break;
+ case 512: return "Pinch Out"; break;
+ default: return "Unknown"; break;
+ }
+ }
+
+// Get color for gesture value
+ static Color GetGestureColor(int gesture)
+ {
+ switch (gesture)
+ {
+ case 0: return Color.Black; break;
+ case 1: return Color.Blue; break;
+ case 2: return Color.SkyBlue; break;
+ case 4: return Color.Black; break;
+ case 8: return Color.Lime; break;
+ case 16: return Color.Red; break;
+ case 32: return Color.Red; break;
+ case 64: return Color.Red; break;
+ case 128: return Color.Red; break;
+ case 256: return Color.Violet; break;
+ case 512: return Color.Orange; break;
+ default: return Color.Black; break;
+ }
+ }
+}
diff --git a/Examples/Core/InputKeys.cs b/Examples/Core/InputKeys.cs
index 252f09d..56e7823 100644
--- a/Examples/Core/InputKeys.cs
+++ b/Examples/Core/InputKeys.cs
@@ -1,11 +1,15 @@
/*******************************************************************************************
*
-* raylib [core] example - Keyboard input
+* raylib [core] example - input keys
*
-* This example has been created using raylib 1.0 (www.raylib.com)
-* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+* Example complexity rating: [★☆☆☆] 1/4
*
-* Copyright (c) 2014 Ramon Santamaria (@raysan5)
+* 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-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
diff --git a/Examples/Core/InputMouse.cs b/Examples/Core/InputMouse.cs
index 6d4ae15..6207883 100644
--- a/Examples/Core/InputMouse.cs
+++ b/Examples/Core/InputMouse.cs
@@ -1,14 +1,19 @@
/*******************************************************************************************
*
-* raylib [core] example - Mouse input
+* raylib [core] example - input mouse
*
-* This example has been created using raylib 1.0 (www.raylib.com)
-* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+* Example complexity rating: [★☆☆☆] 1/4
*
-* Copyright (c) 2014 Ramon Santamaria (@raysan5)
+* Example originally created with raylib 1.0, last time updated with raylib 5.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) 2014-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
+
using System.Numerics;
using static Raylib_cs.Raylib;
@@ -36,6 +41,19 @@ public class InputMouse
{
// Update
//----------------------------------------------------------------------------------
+
+ if (IsKeyPressed(KeyboardKey.H))
+ {
+ if (IsCursorHidden())
+ {
+ ShowCursor();
+ }
+ else
+ {
+ HideCursor();
+ }
+ }
+
ballPosition = GetMousePosition();
if (IsMouseButtonPressed(MouseButton.Left))
@@ -50,6 +68,18 @@ public class InputMouse
{
ballColor = Color.DarkBlue;
}
+ else if (IsMouseButtonPressed(MouseButton.Extra))
+ {
+ ballColor = Color.Yellow;
+ }
+ else if (IsMouseButtonPressed(MouseButton.Forward))
+ {
+ ballColor = Color.Orange;
+ }
+ else if (IsMouseButtonPressed(MouseButton.Back))
+ {
+ ballColor = Color.Beige;
+ }
//----------------------------------------------------------------------------------
// Draw
@@ -60,6 +90,16 @@ public class InputMouse
DrawCircleV(ballPosition, 40, ballColor);
DrawText("move ball with mouse and click mouse button to change color", 10, 10, 20, Color.DarkGray);
+ DrawText("Press 'H' to toggle cursor visibility", 10, 30, 20, Color.DarkGray);
+
+ if (IsCursorHidden())
+ {
+ DrawText("CURSOR HIDDEN", 20, 60, 20, Color.Red);
+ }
+ else
+ {
+ DrawText("CURSOR VISIBLE", 20, 60, 20, Color.Lime);
+ }
EndDrawing();
//----------------------------------------------------------------------------------
diff --git a/Examples/Core/InputMouseWheel.cs b/Examples/Core/InputMouseWheel.cs
index fe144ec..d0c4c5f 100644
--- a/Examples/Core/InputMouseWheel.cs
+++ b/Examples/Core/InputMouseWheel.cs
@@ -1,11 +1,15 @@
/*******************************************************************************************
*
-* raylib [core] examples - Mouse wheel input
+* raylib [core] example - input mouse wheel
*
-* This test has been created using raylib 1.1 (www.raylib.com)
-* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+* Example complexity rating: [★☆☆☆] 1/4
*
-* Copyright (c) 2014 Ramon Santamaria (@raysan5)
+* Example originally created with raylib 1.1, last time updated with raylib 1.3
+*
+* 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-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
@@ -24,10 +28,8 @@ public class InputMouseWheel
InitWindow(screenWidth, screenHeight, "raylib [core] example - input mouse wheel");
- int boxPositionY = screenHeight / 2 - 40;
-
- // Scrolling speed in pixels
- int scrollSpeed = 4;
+ int boxPositionY = screenHeight/2 - 40;
+ int scrollSpeed = 4; // Scrolling speed in pixels
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
diff --git a/Examples/Core/InputMultitouch.cs b/Examples/Core/InputMultitouch.cs
index 266d198..f075bd8 100644
--- a/Examples/Core/InputMultitouch.cs
+++ b/Examples/Core/InputMultitouch.cs
@@ -1,13 +1,17 @@
/*******************************************************************************************
*
-* raylib [core] example - Input multitouch
+* raylib [core] example - input multitouch
*
-* This example has been created using raylib 2.1 (www.raylib.com)
-* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+* Example complexity rating: [★☆☆☆] 1/4
+*
+* 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)
*
-* Copyright (c) 2019 Berni (@Berni8k) and 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-2025 Berni (@Berni8k) and Ramon Santamaria (@raysan5)
*
********************************************************************************************/
diff --git a/Examples/Core/InputVirtualControls.cs b/Examples/Core/InputVirtualControls.cs
new file mode 100644
index 0000000..be1b0aa
--- /dev/null
+++ b/Examples/Core/InputVirtualControls.cs
@@ -0,0 +1,216 @@
+/*******************************************************************************************
+ *
+ * raylib [core] example - input virtual controls
+ *
+ * Example complexity rating: [★★☆☆] 2/4
+ *
+ * Example originally created with raylib 5.0, last time updated with raylib 5.0
+ *
+ * Example contributed by GreenSnakeLinux (@GreenSnakeLinux),
+ * reviewed by Ramon Santamaria (@raysan5), oblerion (@oblerion) and danilwhale (@danilwhale)
+ *
+ * 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-2025 GreenSnakeLinux (@GreenSnakeLinux) and Ramon Santamaria (@raysan5)
+ *
+ ********************************************************************************************/
+
+using System.Numerics;
+
+namespace Examples.Core;
+
+using static Raylib_cs.Raylib;
+
+public enum PadButton
+{
+ BUTTON_NONE = -1,
+ BUTTON_UP,
+ BUTTON_LEFT,
+ BUTTON_RIGHT,
+ BUTTON_DOWN,
+ BUTTON_MAX
+}
+
+public class InputVirtualControls
+{
+ public static int Main()
+ {
+ // Initialization
+ //--------------------------------------------------------------------------------------
+ const int screenWidth = 800;
+ const int screenHeight = 450;
+
+ InitWindow(screenWidth, screenHeight, "raylib [core] example - input virtual controls");
+
+ Vector2 padPosition = new Vector2(100, 350);
+ float buttonRadius = 30;
+
+ Vector2[] buttonPositions =
+ [
+ new Vector2(
+ padPosition.X,padPosition.Y - buttonRadius * 1.5f
+ ), // Up
+ new Vector2(
+ padPosition.X - buttonRadius * 1.5f, padPosition.Y
+ ), // Left
+ new Vector2(
+ padPosition.X + buttonRadius * 1.5f, padPosition.Y
+ ), // Right
+ new Vector2(
+ padPosition.X, padPosition.Y + buttonRadius * 1.5f
+ ) // Down
+ ];
+
+ Vector2[][] arrowTris = [
+ // Up
+ [
+ new Vector2(
+ buttonPositions[0].X, buttonPositions[0].Y - 12
+ ),
+ new Vector2(
+ buttonPositions[0].X - 9, buttonPositions[0].Y + 9
+ ),
+ new Vector2(
+ buttonPositions[0].X + 9, buttonPositions[0].Y + 9
+ )
+ ],
+ // Left
+ [
+ new Vector2(
+ buttonPositions[1].X + 9, buttonPositions[1].Y - 9
+ ),
+ new Vector2(
+ buttonPositions[1].X - 12, buttonPositions[1].Y
+ ),
+ new Vector2(
+ buttonPositions[1].X + 9, buttonPositions[1].Y + 9
+ )
+ ],
+ // Right
+ [
+ new Vector2(
+ buttonPositions[2].X + 12, buttonPositions[2].Y
+ ),
+ new Vector2(
+ buttonPositions[2].X - 9, buttonPositions[2].Y - 9
+ ),
+ new Vector2(
+ buttonPositions[2].X - 9, buttonPositions[2].Y + 9
+ )
+ ],
+ // Down
+ [
+ new Vector2(
+ buttonPositions[3].X - 9, buttonPositions[3].Y - 9
+ ),
+ new Vector2(
+ buttonPositions[3].X, buttonPositions[3].Y + 12
+ ),
+ new Vector2(
+ buttonPositions[3].X + 9, buttonPositions[3].Y - 9
+ )
+ ]
+ ]
+ ;
+
+ Color[] buttonLabelColors = [
+ Color.Yellow, // Up
+ Color.Blue, // Left
+ Color.Red, // Right
+ Color.Green // Down
+ ];
+
+ int pressedButton = (int)PadButton.BUTTON_NONE;
+ Vector2 inputPosition = new Vector2( 0, 0 );
+
+ Vector2 playerPosition = new Vector2( (float)screenWidth / 2, (float)screenHeight / 2 );
+ float playerSpeed = 75f;
+
+ SetTargetFPS(60);
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //--------------------------------------------------------------------------
+ if ((GetTouchPointCount() > 0))
+ {
+ inputPosition = GetTouchPosition(0); // Use touch position
+ }
+ else
+ {
+ inputPosition = GetMousePosition(); // Use mouse position
+ }
+
+ // Reset pressed button to none
+ pressedButton = (int)PadButton.BUTTON_NONE;
+
+ // Make sure user is pressing left mouse button if they're from desktop
+ if ((GetTouchPointCount() > 0) ||
+ ((GetTouchPointCount() == 0) && IsMouseButtonDown(MouseButton.Left)))
+ {
+ // Find nearest D-Pad button to the input position
+ for (int i = 0; i < (int)PadButton.BUTTON_MAX; i++)
+ {
+ float distX = MathF.Abs(buttonPositions[i].X - inputPosition.X);
+ float distY = MathF.Abs(buttonPositions[i].Y - inputPosition.Y);
+
+ if ((distX + distY < buttonRadius))
+ {
+ pressedButton = i;
+ break;
+ }
+ }
+ }
+
+ // Move player according to pressed button
+ switch ((PadButton)pressedButton)
+ {
+ case PadButton.BUTTON_UP: playerPosition.Y -= playerSpeed * GetFrameTime(); break;
+ case PadButton.BUTTON_LEFT: playerPosition.X -= playerSpeed * GetFrameTime(); break;
+ case PadButton.BUTTON_RIGHT: playerPosition.X += playerSpeed * GetFrameTime(); break;
+ case PadButton.BUTTON_DOWN: playerPosition.Y += playerSpeed * GetFrameTime(); break;
+ default: break;
+ }
+
+ ;
+ //--------------------------------------------------------------------------
+
+ // Draw
+ //--------------------------------------------------------------------------
+ BeginDrawing();
+
+ ClearBackground(Color.RayWhite);
+
+ // Draw world
+ DrawCircleV(playerPosition, 50, Color.Maroon);
+
+ // Draw GUI
+ for (int i = 0; i < (int)PadButton.BUTTON_MAX; i++)
+ {
+ DrawCircleV(buttonPositions[i], buttonRadius, (i == pressedButton) ? Color.DarkGray : Color.Black);
+
+ DrawTriangle(
+ arrowTris[i][0],
+ arrowTris[i][1],
+ arrowTris[i][2],
+ buttonLabelColors[i]
+ );
+ }
+
+ DrawText("move the player with D-Pad buttons", 10, 10, 20, Color.DarkGray);
+
+ EndDrawing();
+ //--------------------------------------------------------------------------
+ }
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+ }
+}
diff --git a/Examples/Models/AnimationDemo.cs b/Examples/Models/LoadingIqm.cs
similarity index 65%
rename from Examples/Models/AnimationDemo.cs
rename to Examples/Models/LoadingIqm.cs
index 708f753..6905544 100644
--- a/Examples/Models/AnimationDemo.cs
+++ b/Examples/Models/LoadingIqm.cs
@@ -1,28 +1,31 @@
/*******************************************************************************************
*
-* raylib [models] example - Load 3d model with animations and play them
+* raylib [models] example - loading iqm
*
-* This example has been created using raylib 2.5 (www.raylib.com)
-* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+* Example complexity rating: [★★☆☆] 2/4
+*
+* Example originally created with raylib 2.5, last time updated with raylib 3.5
*
* Example contributed by Culacant (@culacant) and reviewed by Ramon Santamaria (@raysan5)
*
-* Copyright (c) 2019 Culacant (@culacant) and Ramon Santamaria (@raysan5)
+* NOTES: To export an IQM model from blender, make sure it is not posed, the vertices need
+* to be in the same position as they would be in edit mode and the scale of the models is
+* set to 0; scaling can be set from the export menu
*
-********************************************************************************************
+* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
+* BSD-like license that allows static linking with closed source software
*
-* To export a model from blender, make sure it is not posed, the vertices need to be in the
-* same position as they would be in edit mode.
-* and that the scale of your models is set to 0. Scaling can be done from the export menu.
+* Copyright (c) 2019-2025 Culacant (@culacant) and Ramon Santamaria (@raysan5)
*
********************************************************************************************/
using System.Numerics;
+using System.Runtime.InteropServices;
using static Raylib_cs.Raylib;
namespace Examples.Models;
-public class AnimationDemo
+public class LoadingIqm
{
public unsafe static int Main()
{
@@ -36,20 +39,22 @@ public class AnimationDemo
// Define the camera to look into our 3d world
Camera3D camera = new();
camera.Position = new Vector3(10.0f, 10.0f, 10.0f);
- camera.Target = new Vector3(0.0f, 0.0f, 0.0f);
+ camera.Target = new Vector3(0.0f, 4.0f, 0.0f);
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
camera.FovY = 45.0f;
camera.Projection = CameraProjection.Perspective;
Model model = LoadModel("resources/models/iqm/guy.iqm");
Texture2D texture = LoadTexture("resources/models/iqm/guytex.png");
- Raylib.SetMaterialTexture(ref model, 0, MaterialMapIndex.Albedo, ref texture);
-
+ Raylib.SetMaterialTexture(ref model, 0, MaterialMapIndex.Diffuse, ref texture);
Vector3 position = new(0.0f, 0.0f, 0.0f);
+
// Load animation data
- int animsCount = 0;
- var anims = LoadModelAnimations("resources/models/iqm/guyanim.iqm", ref animsCount);
- int animFrameCounter = 0;
+ var anims = LoadModelAnimations("resources/models/iqm/guyanim.iqm");
+
+ // Animation playing variables
+ int animIndex = 0;
+ float animCurrentFrame = 0.0f;
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
@@ -59,17 +64,15 @@ public class AnimationDemo
{
// Update
//----------------------------------------------------------------------------------
- UpdateCamera(ref camera, CameraMode.Free);
+ UpdateCamera(ref camera, CameraMode.Orbital);
// Play animation when spacebar is held down
- if (IsKeyDown(KeyboardKey.Space))
+ animCurrentFrame += 1.0f;
+ UpdateModelAnimation(model, anims[0], animCurrentFrame);
+
+ if (animCurrentFrame >= anims[0].KeyFrameCount)
{
- animFrameCounter++;
- UpdateModelAnimation(model, anims[0], animFrameCounter);
- if (animFrameCounter >= anims[0].FrameCount)
- {
- animFrameCounter = 0;
- }
+ animCurrentFrame = 0;
}
//----------------------------------------------------------------------------------
@@ -89,17 +92,10 @@ public class AnimationDemo
Color.White
);
- for (int i = 0; i < model.BoneCount; i++)
- {
- var framePoses = anims[0].FramePoses;
- DrawCube(framePoses[animFrameCounter][i].Translation, 0.2f, 0.2f, 0.2f, Color.Red);
- }
-
DrawGrid(10, 1.0f);
EndMode3D();
-
- DrawText("PRESS SPACE to PLAY MODEL ANIMATION", 10, 10, 20, Color.Maroon);
+ DrawText($"Current animation: {anims[animIndex].NameToString()}", 10, 10, 20, Color.Maroon);
DrawText("(c) Guy IQM 3D model by @culacant", screenWidth - 200, screenHeight - 20, 10, Color.Gray);
EndDrawing();
@@ -109,9 +105,7 @@ public class AnimationDemo
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadTexture(texture);
-
- UnloadModelAnimations(anims, animsCount);
-
+ UnloadModelAnimations(anims);
UnloadModel(model);
CloseWindow();
diff --git a/Examples/Program.cs b/Examples/Program.cs
index ba32773..27e8996 100644
--- a/Examples/Program.cs
+++ b/Examples/Program.cs
@@ -1,4 +1,3 @@
-using System;
using System.Diagnostics;
using Examples.Core;
using Examples.Shapes;
@@ -34,6 +33,9 @@ public class ExampleList
public static ExampleInfo[] AllExamples = new[]
{
// Core
+ new ExampleInfo("DeltaTime", DeltaTime.Main),
+ new ExampleInfo("InputGesturesTestBed", InputGesturesTestBed.Main),
+ new ExampleInfo("InputVirtualControls", InputVirtualControls.Main),
new ExampleInfo("Camera2dPlatformer", Camera2dPlatformer.Main),
new ExampleInfo("Camera2dDemo", Camera2dDemo.Main),
new ExampleInfo("Camera3dFirstPerson", Camera3dFirstPerson.Main),
@@ -110,7 +112,7 @@ public class ExampleList
new ExampleInfo("WritingAnim", WritingAnim.Main),
// Models
- new ExampleInfo("AnimationDemo", AnimationDemo.Main),
+ new ExampleInfo("LoadingIqm", LoadingIqm.Main),
new ExampleInfo("BillboardDemo", BillboardDemo.Main),
new ExampleInfo("BoxCollisions", BoxCollisions.Main),
new ExampleInfo("CubicmapDemo", CubicmapDemo.Main),
diff --git a/Examples/resources/symbola.png b/Examples/resources/symbola.png
deleted file mode 100644
index e942606..0000000
Binary files a/Examples/resources/symbola.png and /dev/null differ
diff --git a/Raylib-cs/interop/Raylib.cs b/Raylib-cs/interop/Raylib.cs
index aa0f962..d9b6a1d 100644
--- a/Raylib-cs/interop/Raylib.cs
+++ b/Raylib-cs/interop/Raylib.cs
@@ -820,32 +820,32 @@ public static unsafe partial class Raylib
/// Rename file (if exists)
[LibraryImport(NativeLibName)]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- public static partial CBool FileRename(sbyte* fileName, sbyte* fileRename);
+ public static partial int FileRename(sbyte* fileName, sbyte* fileRename);
/// Remove file (if exists)
[LibraryImport(NativeLibName)]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- public static partial CBool FileRemove(sbyte* fileName);
+ public static partial int FileRemove(sbyte* fileName);
/// Copy file from one path to another, dstPath created if it doesn't exist
[LibraryImport(NativeLibName)]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- public static partial CBool FileCopy(sbyte* srcPath, sbyte* dstPath);
+ public static partial int FileCopy(sbyte* srcPath, sbyte* dstPath);
/// Move file from one path to another, dstPath created if it doesn't exist
[LibraryImport(NativeLibName)]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- public static partial CBool FileMove(sbyte* srcPath, sbyte* dstPath);
+ public static partial int FileMove(sbyte* srcPath, sbyte* dstPath);
/// Replace text in an existing file
[LibraryImport(NativeLibName)]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- public static partial CBool FileTextReplace(sbyte* fileName, sbyte* search, sbyte* replacement);
+ public static partial int FileTextReplace(sbyte* fileName, sbyte* search, sbyte* replacement);
/// Find text in existing file
[LibraryImport(NativeLibName)]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- public static partial CBool FileTextFindIndex(sbyte* fileName, sbyte* search);
+ public static partial int FileTextFindIndex(sbyte* fileName, sbyte* search);
/// Check if file exists
[LibraryImport(NativeLibName)]
@@ -962,7 +962,7 @@ public static unsafe partial class Raylib
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static partial FilePathList GetDirectoryFileCount(sbyte* dirPath);
- /// Get the file count in a directory
+ /// Load directory filepaths with extension filtering and subdir scan; some filters available: "*.*", "FILES*", "DIRS*"
[LibraryImport(NativeLibName)]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
public static partial FilePathList GetDirectoryFileCountEx(sbyte* dirPath, sbyte* filter, CBool scanSubdirs);
diff --git a/Raylib-cs/types/Mesh.cs b/Raylib-cs/types/Mesh.cs
index 10c389c..f4bf087 100644
--- a/Raylib-cs/types/Mesh.cs
+++ b/Raylib-cs/types/Mesh.cs
@@ -248,4 +248,6 @@ public unsafe struct Mesh
public const int VboIdIndexIndices = 6;
#endregion
+
+
}
diff --git a/Raylib-cs/types/Model.cs b/Raylib-cs/types/Model.cs
index 945db48..16bac95 100644
--- a/Raylib-cs/types/Model.cs
+++ b/Raylib-cs/types/Model.cs
@@ -19,6 +19,14 @@ public unsafe struct BoneInfo
/// Bone parent
///
public int Parent;
+
+ public string NameToString()
+ {
+ fixed (sbyte* name = Name)
+ {
+ return Utf8StringUtils.GetUTF8String(name);
+ }
+ }
}
///
@@ -41,6 +49,16 @@ public unsafe struct ModelSkeleton
/// Bones base transformation (Transform[])
///
public Transform* ModelAnimPose;
+
+ public Span ModelAnimPoseAsSpan()
+ {
+ return new Span(ModelAnimPose, BoneCount);
+ }
+
+ public Span BonesAsSpan()
+ {
+ return new Span(Bones, BoneCount);
+ }
}
// Note:
@@ -84,29 +102,52 @@ public unsafe struct Model
public int* MeshMaterial;
///
- /// Number of bones
+ /// Skeleton for animation
///
- public int BoneCount;
+ ModelSkeleton Skeleton;
- //TODO: Span
///
- /// Bones information (skeleton, BoneInfo *)
+ /// Current animation pose (Transform[])
///
- public BoneInfo* Bones;
+ public Transform* CurrentPose;
- //TODO: Span
///
- /// Bones base transformation (pose, Transform *)
+ /// Bones animated transformation matrices
///
- public Transform* BindPose;
+ public Matrix4x4* BoneMatrices;
+
+ public Span BoneMatricesAsSpan()
+ {
+ return new Span(BoneMatrices, Skeleton.BoneCount);
+ }
+
+ public Span CurrentPoseAsSpan()
+ {
+ return new Span(CurrentPose, Skeleton.BoneCount);
+ }
+
+ public Span MeshMaterialAsSpan()
+ {
+ return new Span(MeshMaterial, MeshCount);
+ }
+
+ public Span MeshesAsSpan()
+ {
+ return new Span(Meshes, MeshCount);
+ }
}
///
-/// Model animation
+/// ModelAnimation, contains a full animation sequence
///
[StructLayout(LayoutKind.Sequential)]
public unsafe struct ModelAnimation
{
+ ///
+ /// Animation name (char[32])
+ ///
+ public fixed sbyte Name[32];
+
///
/// Number of bones
///
@@ -115,61 +156,23 @@ public unsafe struct ModelAnimation
///
/// Number of animation frames
///
- public readonly int FrameCount;
+ public readonly int KeyFrameCount;
///
- /// Bones information (skeleton, BoneInfo *)
+ /// Animation sequence keyframe poses [keyframe][pose]
///
- public readonly BoneInfo* Bones;
+ public Transform* KeyframePoses;
- ///
- public readonly ReadOnlySpan BoneInfo => new ReadOnlySpan(Bones, BoneCount);
-
- ///
- /// Poses array by frame (Transform **)
- ///
- public readonly Transform** FramePoses;
-
- ///
- /// Animation name (char[32])
- ///
- public fixed sbyte Name[32];
-
- ///
- public readonly FramePosesCollection FramePosesColl => new FramePosesCollection(FramePoses, FrameCount, BoneCount);
-
- public readonly struct FramePosesCollection
+ public Span KeyFramePosesAsSpan()
{
- readonly Transform** _framePoses;
+ return new Span(KeyframePoses, KeyFrameCount);
+ }
- readonly int _frameCount;
-
- readonly int _boneCount;
-
- public readonly FramePoses this[int index] => new FramePoses(_framePoses[index], _boneCount);
-
- public readonly Transform this[int index1, int index2] => new FramePoses(_framePoses[index1], _boneCount)[index2];
-
- internal FramePosesCollection(Transform** framePoses, int frameCount, int boneCount)
+ public string NameToString()
+ {
+ fixed (sbyte* name = Name)
{
- this._framePoses = framePoses;
- this._frameCount = frameCount;
- this._boneCount = boneCount;
+ return Utf8StringUtils.GetUTF8String(name);
}
}
}
-
-public readonly unsafe struct FramePoses
-{
- readonly Transform* _poses;
-
- readonly int _count;
-
- public readonly ref Transform this[int index] => ref _poses[index];
-
- internal FramePoses(Transform* poses, int count)
- {
- this._poses = poses;
- this._count = count;
- }
-}
diff --git a/Raylib-cs/types/Raylib.Utils.cs b/Raylib-cs/types/Raylib.Utils.cs
index eb12e24..859b85b 100644
--- a/Raylib-cs/types/Raylib.Utils.cs
+++ b/Raylib-cs/types/Raylib.Utils.cs
@@ -1085,6 +1085,24 @@ public static unsafe partial class Raylib
}
}
+ /// Load model animations from file
+ public static Span LoadModelAnimations(string fileName)
+ {
+ using AnsiBuffer str1 = fileName.ToAnsiBuffer();
+ int count;
+
+ ModelAnimation* result = LoadModelAnimations(str1.AsPointer(), &count);
+ return new Span(result, count);
+ }
+
+ public static void UnloadModelAnimations(Span animations)
+ {
+ fixed (ModelAnimation* ptr = animations)
+ {
+ UnloadModelAnimations(ptr, animations.Length);
+ }
+ }
+
/// Compute mesh tangents
public static void GenMeshTangents(ref Mesh mesh)
{
@@ -1549,6 +1567,155 @@ public static unsafe partial class Raylib
SaveFileText(fileBuffer.AsPointer(), textBuffer.AsPointer());
}
+ /// Rename file (if exists)
+ public static int FileRename(string filename, string fileRename)
+ {
+
+ using AnsiBuffer fileBuffer = filename.ToAnsiBuffer();
+ using AnsiBuffer textBuffer = fileRename.ToAnsiBuffer();
+ return FileRename(fileBuffer.AsPointer(), textBuffer.AsPointer());
+ }
+
+ /// Remove file (if exists)
+ public static int FileRemove(string filename)
+ {
+ using AnsiBuffer fileBuffer = filename.ToAnsiBuffer();
+ return FileRemove(fileBuffer.AsPointer());
+ }
+
+ /// Copy file from one path to another, dstPath created if it doesn't exist
+ public static int FileCopy(string srcPath, string dstPath)
+ {
+ using AnsiBuffer srcBuffer = srcPath.ToAnsiBuffer();
+ using AnsiBuffer dstBuffer = dstPath.ToAnsiBuffer();
+ return FileCopy(srcBuffer.AsPointer(), dstBuffer.AsPointer());
+ }
+
+ /// Move file from one path to another, dstPath created if it doesn't exist
+ public static int FileMove(string srcPath, string dstPath)
+ {
+ using AnsiBuffer srcBuffer = srcPath.ToAnsiBuffer();
+ using AnsiBuffer dstBuffer = dstPath.ToAnsiBuffer();
+ return FileMove(srcBuffer.AsPointer(), dstBuffer.AsPointer());
+ }
+
+ /// Replace text in an existing file
+ public static int FileTextReplace(string fileName, string search, string replacement)
+ {
+ using AnsiBuffer fileBuffer = fileName.ToAnsiBuffer();
+ using AnsiBuffer searchBuffer = search.ToAnsiBuffer();
+ using AnsiBuffer replaceBuffer = replacement.ToAnsiBuffer();
+ return FileTextReplace(fileBuffer.AsPointer(), searchBuffer.AsPointer(), replaceBuffer.AsPointer());
+ }
+
+ /// Find text in existing file
+ public static int FileTextFindIndex(string fileName, string search)
+ {
+ using AnsiBuffer fileBuffer = fileName.ToAnsiBuffer();
+ using AnsiBuffer searchBuffer = search.ToAnsiBuffer();
+ return FileTextFindIndex(fileBuffer.AsPointer(), searchBuffer.AsPointer());
+ }
+
+ /// Check if file exists
+ public static CBool FileExists(string fileName)
+ {
+ using AnsiBuffer fileBuffer = fileName.ToAnsiBuffer();
+ return FileExists(fileBuffer.AsPointer());
+ }
+
+ /// Check if a directory path exists
+ public static CBool DirectoryExists(string dirPath)
+ {
+ using AnsiBuffer dirBuffer = dirPath.ToAnsiBuffer();
+ return DirectoryExists(dirBuffer.AsPointer());
+ }
+
+ /// Get file length in bytes
+ public static int GetFileLength(string fileName)
+ {
+ using AnsiBuffer fileBuffer = fileName.ToAnsiBuffer();
+ return GetFileLength(fileBuffer.AsPointer());
+ }
+
+ /// Get string to extension for a filename string (includes dot: '.png')
+ public static string GetFileExtension(string fileName)
+ {
+ using AnsiBuffer fileBuffer = fileName.ToAnsiBuffer();
+ return new string(GetFileExtension(fileBuffer.AsPointer()));
+ }
+
+ /// Get string to filename for a path string
+ public static string GetFileName(string fileName)
+ {
+ using AnsiBuffer fileBuffer = fileName.ToAnsiBuffer();
+ return new string(GetFileName(fileBuffer.AsPointer()));
+ }
+
+ /// Get filename string without extension
+ public static string GetFileNameWithoutExt(string fileName)
+ {
+ using AnsiBuffer fileBuffer = fileName.ToAnsiBuffer();
+ return new string(GetFileNameWithoutExt(fileBuffer.AsPointer()));
+ }
+
+ /// Get full path for a given fileName with path
+ public static string GetDirectoryPath(string filePath)
+ {
+ using AnsiBuffer fileBuffer = filePath.ToAnsiBuffer();
+ return new string(GetDirectoryPath(fileBuffer.AsPointer()));
+ }
+
+ /// Get previous directory path for a given path
+ public static string GetPrevDirectoryPath(string dirPath)
+ {
+ using AnsiBuffer dirBuffer = dirPath.ToAnsiBuffer();
+ return new string(GetPrevDirectoryPath(dirBuffer.AsPointer()));
+ }
+
+ /// Get current working directory
+ public static string GetWorkingDirectoryAsString()
+ {
+ return new string(GetWorkingDirectory());
+ }
+
+ /// Get the directory of the running application
+ public static string GetApplicationDirectoryAsString()
+ {
+ return new string(GetApplicationDirectory());
+ }
+
+ /// Change working directory, return true on success
+ public static CBool ChangeDirectory(string dirPath)
+ {
+ using AnsiBuffer dirBuffer = dirPath.ToAnsiBuffer();
+ return ChangeDirectory(dirBuffer.AsPointer());
+ }
+
+ /// Check if a given path is a file or a directory
+ public static CBool IsPathFile(string path)
+ {
+ using AnsiBuffer pathBuffer = path.ToAnsiBuffer();
+ return IsPathFile(pathBuffer.AsPointer());
+ }
+
+ /// Load directory filepaths
+ public static FilePathList LoadDirectoryFiles(string dirPath, out int count)
+ {
+ using AnsiBuffer dirBuffer = dirPath.ToAnsiBuffer();
+ int c = 0;
+ var result = LoadDirectoryFiles(dirBuffer.AsPointer(), &c);
+ count = c;
+ return result;
+ }
+
+ /// Load directory filepaths with extension filtering and subdir scan; some filters available: "*.*", "FILES*", "DIRS*"
+ public static FilePathList LoadDirectoryFilesEx(string basePath, string filter, CBool scanSubDirs)
+ {
+ using AnsiBuffer baseBuffer = basePath.ToAnsiBuffer();
+ using AnsiBuffer filterBuffer = filter.ToAnsiBuffer();
+ return LoadDirectoryFilesEx(baseBuffer.AsPointer(), filterBuffer.AsPointer(), scanSubDirs);
+ }
+
///
/// Loads text from a file, reads it, saves it, unloads the file, and returns the loaded text.
///
@@ -1569,4 +1736,5 @@ public static unsafe partial class Raylib
center.Y = GetScreenHeight() / 2.0f;
return center;
}
+
}
diff --git a/Raylib-cs/types/native/FilePathList.cs b/Raylib-cs/types/native/FilePathList.cs
index 9c50a3b..206b9a2 100644
--- a/Raylib-cs/types/native/FilePathList.cs
+++ b/Raylib-cs/types/native/FilePathList.cs
@@ -1,3 +1,4 @@
+using System;
using System.Runtime.InteropServices;
namespace Raylib_cs;
diff --git a/Raylib-cs/types/native/Utf8Buffer.cs b/Raylib-cs/types/native/Utf8Buffer.cs
index 3acb824..98d9aaa 100644
--- a/Raylib-cs/types/native/Utf8Buffer.cs
+++ b/Raylib-cs/types/native/Utf8Buffer.cs
@@ -21,6 +21,11 @@ public readonly ref struct Utf8Buffer
return (sbyte*)_data.ToPointer();
}
+ public unsafe byte* AsBytePointer()
+ {
+ return (byte*)_data.ToPointer();
+ }
+
public void Dispose()
{
Marshal.ZeroFreeCoTaskMemUTF8(_data);