From bd525b99211b196a1474c2e90a902daeddefd32e Mon Sep 17 00:00:00 2001 From: ChrisDill Date: Mon, 22 Oct 2018 16:10:20 +0100 Subject: [PATCH] Porting examples - Test.Common now used for Examples project. - Testing examples alot. --- .gitignore | 1 - Examples/Examples.projitems | 81 +++++++++ .../Examples.shproj | 2 +- Examples/RayForm.cs | 102 ----------- Examples/audio/audio_module_playing.cs | 8 +- Examples/audio/audio_music_stream.cs | 4 +- Examples/audio/audio_raw_stream.cs | 10 +- Examples/audio/audio_sound_loading.cs | 4 +- Examples/core/core_2d_camera.cs | 6 +- Examples/core/core_3d_camera_first_person.cs | 6 +- Examples/core/core_3d_camera_free.cs | 6 +- Examples/core/core_3d_mode.cs | 5 +- Examples/core/core_3d_picking.cs | 6 +- Examples/core/core_basic_window.cs | 2 +- Examples/core/core_color_select.cs | 4 +- Examples/core/core_drop_files.cs | 4 +- Examples/core/core_gestures_detection.cs | 7 +- Examples/core/core_input_gamepad.cs | 171 +++++++++++++++++- Examples/core/core_input_keys.cs | 8 +- Examples/core/core_input_mouse.cs | 8 +- Examples/core/core_mouse_wheel.cs | 12 +- Examples/core/core_random_values.cs | 5 +- Examples/core/core_storage_values.cs | 14 +- Examples/core/core_vr_simulator.cs | 7 +- Examples/core/core_world_screen.cs | 6 +- Examples/iqm_loader/models_iqm_animation.cs | 7 - Examples/models/models_billboard.cs | 6 +- Examples/models/models_box_collisions.cs | 4 +- Examples/models/models_cubicmap.cs | 6 +- Examples/models/models_geometric_shapes.cs | 5 +- Examples/models/models_heightmap.cs | 6 +- Examples/models/models_material_pbr.cs | 4 +- Examples/models/models_mesh_generation.cs | 6 +- Examples/models/models_mesh_picking.cs | 7 +- Examples/models/models_obj_loading.cs | 6 +- .../models/models_orthographic_projection.cs | 6 +- Examples/models/models_skybox.cs | 6 +- Examples/models/models_yaw_pitch_roll.cs | 7 +- Examples/others/audio_standalone.cs | 7 - Examples/others/bunnymark.cs | 11 +- Examples/others/resources/wabbit_alpha.png | Bin 0 -> 449 bytes Examples/others/rlgl_standalone.cs | 7 - Examples/others/standard_lighting.cs | 7 - Examples/physac/physics_demo.cs | 4 +- Examples/physac/physics_friction.cs | 4 +- Examples/physac/physics_movement.cs | 7 +- Examples/physac/physics_restitution.cs | 4 +- Examples/physac/physics_shatter.cs | 5 +- Examples/raylib-cs.ico | Bin 0 -> 142667 bytes .../resources/shaders/glsl100/swirl.fs | 6 +- Examples/shaders/shaders_custom_uniform.cs | 7 +- Examples/shaders/shaders_model_shader.cs | 7 +- Examples/shaders/shaders_postprocessing.cs | 7 +- Examples/shaders/shaders_shapes_textures.cs | 4 +- Examples/shapes/shapes_basic_shapes.cs | 4 +- Examples/shapes/shapes_colors_palette.cs | 4 +- Examples/shapes/shapes_lines_bezier.cs | 4 +- Examples/shapes/shapes_logo_raylib.cs | 4 +- Examples/shapes/shapes_logo_raylib_anim.cs | 5 +- Examples/text/resources/custom_alagard.png | Bin 37935 -> 45351 bytes .../text/resources/custom_jupiter_crash.png | Bin 23596 -> 29128 bytes Examples/text/resources/custom_mecha.png | Bin 26597 -> 32399 bytes Examples/text/resources/fonts/alagard.png | Bin 4424 -> 3626 bytes Examples/text/resources/fonts/alpha_beta.png | Bin 2442 -> 2424 bytes .../text/resources/fonts/jupiter_crash.png | Bin 3478 -> 2975 bytes Examples/text/resources/fonts/mecha.png | Bin 2399 -> 2355 bytes Examples/text/resources/fonts/pixantiqua.png | Bin 3003 -> 2739 bytes Examples/text/resources/fonts/pixelplay.png | Bin 2912 -> 2835 bytes Examples/text/resources/fonts/romulus.png | Bin 2932 -> 2702 bytes Examples/text/resources/fonts/setback.png | Bin 2539 -> 2517 bytes Examples/text/text_bmfont_ttf.cs | 4 +- Examples/text/text_bmfont_unordered.cs | 4 +- Examples/text/text_font_sdf.cs | 17 +- Examples/text/text_format_text.cs | 4 +- Examples/text/text_input_box.cs | 7 +- Examples/text/text_raylib_fonts.cs | 4 +- Examples/text/text_sprite_fonts.cs | 4 +- Examples/text/text_ttf_loading.cs | 5 +- Examples/text/text_writing_anim.cs | 4 +- .../resources/custom_jupiter_crash.png | Bin 23596 -> 29128 bytes .../textures/resources/ninepatch_button.png | Bin 0 -> 5923 bytes Examples/textures/resources/scarfy.png | Bin 33146 -> 10495 bytes Examples/textures/textures_image_drawing.cs | 4 +- .../textures/textures_image_generation.cs | 4 +- Examples/textures/textures_image_loading.cs | 4 +- .../textures/textures_image_processing.cs | 6 +- Examples/textures/textures_image_text.cs | 4 +- Examples/textures/textures_logo_raylib.cs | 4 +- .../textures/textures_particles_blending.cs | 10 +- Examples/textures/textures_raw_data.cs | 5 +- Examples/textures/textures_rectangle.cs | 4 +- Examples/textures/textures_srcrec_dstrec.cs | 4 +- Examples/textures/textures_to_image.cs | 4 +- Raylib-cs.sln | 32 +--- Test.Common/Test.Common.projitems | 14 -- Test.Common/Test.cs | 52 ------ Test.NetCore/Program.cs | 5 +- 97 files changed, 516 insertions(+), 366 deletions(-) create mode 100644 Examples/Examples.projitems rename Test.Common/Test.Common.shproj => Examples/Examples.shproj (94%) delete mode 100644 Examples/RayForm.cs delete mode 100644 Examples/iqm_loader/models_iqm_animation.cs delete mode 100644 Examples/others/audio_standalone.cs create mode 100644 Examples/others/resources/wabbit_alpha.png delete mode 100644 Examples/others/rlgl_standalone.cs delete mode 100644 Examples/others/standard_lighting.cs create mode 100644 Examples/raylib-cs.ico create mode 100644 Examples/textures/resources/ninepatch_button.png delete mode 100644 Test.Common/Test.Common.projitems delete mode 100644 Test.Common/Test.cs diff --git a/.gitignore b/.gitignore index e31b171..bae0d48 100644 --- a/.gitignore +++ b/.gitignore @@ -31,7 +31,6 @@ bld/ [Dd]ebug [Oo]bj/ [Ll]og/ -[Ee]xamples/ # Visual Studio 2015 cache/options directory .vs/ diff --git a/Examples/Examples.projitems b/Examples/Examples.projitems new file mode 100644 index 0000000..376dd80 --- /dev/null +++ b/Examples/Examples.projitems @@ -0,0 +1,81 @@ + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + true + 36e54e2a-5899-4d4d-9d78-120db1b4c7b2 + + + Test.Common + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Test.Common/Test.Common.shproj b/Examples/Examples.shproj similarity index 94% rename from Test.Common/Test.Common.shproj rename to Examples/Examples.shproj index 0bc18d0..5949e1d 100644 --- a/Test.Common/Test.Common.shproj +++ b/Examples/Examples.shproj @@ -8,6 +8,6 @@ - + diff --git a/Examples/RayForm.cs b/Examples/RayForm.cs deleted file mode 100644 index 434d804..0000000 --- a/Examples/RayForm.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System; -using System.Drawing; -using System.Runtime.InteropServices; -using System.Threading; -using System.Windows.Forms; -using static Raylib.Raylib; - -namespace Raylib -{ - public partial class RayForms : Form - { - private Panel gamePanel; - private bool windowAttached = false; - - #region WinAPI Entry Points - - [DllImport("user32.dll")] - private static extern IntPtr SetWindowPos(IntPtr handle, IntPtr handleAfter, int x, int y, int cx, int cy, uint flags); - [DllImport("user32.dll")] - private static extern IntPtr SetParent(IntPtr child, IntPtr newParent); - [DllImport("user32.dll")] - private static extern IntPtr ShowWindow(IntPtr handle, int command); - - #endregion - - public RayForms() - { - Size = new Size(1024, 700); - Text = "Rayforms"; - - gamePanel = new Panel(); - gamePanel.Size = new Size(800, 500); - gamePanel.Location = new Point(50, 50); - - Button button = new Button(); - button.Text = "Attach window"; - button.Size = new Size(150, 20); - button.Location = new Point( - (Size.Width / 2) - (button.Size.Width / 2), - gamePanel.Location.Y + gamePanel.Size.Height + 10 - ); - button.Click += new EventHandler(ClickedButton); - Controls.Add(button); - Controls.Add(gamePanel); - } - - private void ClickedButton(object sender, EventArgs e) - { - if (!windowAttached) - { - // new Thread(Test).Start(); - Test(); - } - } - - private void Test() - { - SetConfigFlags((int)Flag.WINDOW_UNDECORATED); - InitWindow(800, 480, "Rayforms test"); - SetTargetFPS(60); - - IntPtr winHandle = GetWindowHandle(); - Invoke(new Action(() => - { - SetWindowPos(winHandle, Handle, 0, 0, 0, 0, 0x0401 /*NOSIZE | SHOWWINDOW */); - SetParent(winHandle, gamePanel.Handle); - ShowWindow(winHandle, 1); - windowAttached = true; - })); - - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update - //---------------------------------------------------------------------------------- - // TODO: Update your variables here - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - DrawText("Congrats! You created your first window!", 190, 200, 20, MAROON); - - DrawText(GetFrameTime().ToString(), 100, 10, 15, MAROON); - - DrawFPS(10, 10); - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - CloseWindow(); - } - - public static void Run() - { - Application.Run(new RayForms()); - } - } -} diff --git a/Examples/audio/audio_module_playing.cs b/Examples/audio/audio_module_playing.cs index f35fb95..7f0e842 100644 --- a/Examples/audio/audio_module_playing.cs +++ b/Examples/audio/audio_module_playing.cs @@ -1,7 +1,11 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class audio_module_playing { - /******************************************************************************************* * * raylib [audio] example - Module playing (streaming) * * NOTE: This example requires OpenAL Soft library installed * * 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) * * Copyright (c) 2016 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public const #define MAX_CIRCLES 64 struct CircleWave { public Vector2 position; public float radius; public float alpha; public float speed; public Color color; public } CircleWave; public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; SetConfigFlags((int)Flag.MSAA_4X_HINT); // NOTE: Try to enable MSAA 4X InitWindow(screenWidth, screenHeight, "raylib [audio] example - module playing (streaming)"); InitAudioDevice(); // Initialize audio device Color colors[14] = { ORANGE, RED, GOLD, LIME, BLUE, VIOLET, BROWN, LIGHTGRAY, PINK, YELLOW, GREEN, SKYBLUE, PURPLE, BEIGE }; // Creates ome circles for visual effect CircleWave[] circles = new CircleWave[MAX_CIRCLES]; for (int i = MAX_CIRCLES - 1; i >= 0; i--) { circles[i].alpha = 0.0f; circles[i].radius = GetRandomValue(10, 40); circles[i].position.x = GetRandomValue(circles[i].radius, screenWidth - circles[i].radius); circles[i].position.y = GetRandomValue(circles[i].radius, screenHeight - circles[i].radius); circles[i].speed = (float)GetRandomValue(1, 100)/20000.0f; circles[i].color = colors[GetRandomValue(0, 13)]; } IntPtr xm = LoadMusicStream("resources/mini1111.xm"); PlayMusicStream(xm); float timePlayed = 0.0f; bool pause = false; SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateMusicStream(xm); // Update music buffer with new stream data // Restart music playing (stop and play) if (IsKeyPressed((int)Key.SPACE)) { StopMusicStream(xm); PlayMusicStream(xm); } // Pause/Resume music playing if (IsKeyPressed((int)Key.P)) { pause = !pause; if (pause) PauseMusicStream(xm); else ResumeMusicStream(xm); } // Get timePlayed scaled to bar dimensions timePlayed = GetMusicTimePlayed(xm)/GetMusicTimeLength(xm)*(screenWidth - 40); // Color circles animation for (int i = MAX_CIRCLES - 1; (i >= 0) && !pause; i--) { circles[i].alpha += circles[i].speed; circles[i].radius += circles[i].speed*10.0f; if (circles[i].alpha > 1.0f) circles[i].speed *= -1; if (circles[i].alpha <= 0.0f) { circles[i].alpha = 0.0f; circles[i].radius = GetRandomValue(10, 40); circles[i].position.x = GetRandomValue(circles[i].radius, screenWidth - circles[i].radius); circles[i].position.y = GetRandomValue(circles[i].radius, screenHeight - circles[i].radius); circles[i].color = colors[GetRandomValue(0, 13)]; circles[i].speed = (float)GetRandomValue(1, 100)/20000.0f; } } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); for (int i = MAX_CIRCLES - 1; i >= 0; i--) { DrawCircleV(circles[i].position, circles[i].radius, Fade(circles[i].color, circles[i].alpha)); } // Draw time bar DrawRectangle(20, screenHeight - 20 - 12, screenWidth - 40, 12, LIGHTGRAY); DrawRectangle(20, screenHeight - 20 - 12, (int)timePlayed, 12, MAROON); DrawRectangleLines(20, screenHeight - 20 - 12, screenWidth - 40, 12, GRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadMusicStream(xm); // Unload music stream buffers from RAM CloseAudioDevice(); // Close audio device (music streaming is automatically stopped) CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [audio] example - Module playing (streaming) * * NOTE: This example requires OpenAL Soft library installed * * 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) * * Copyright (c) 2016 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public const int MAX_CIRCLES = 64; + + struct CircleWave { + public Vector2 position; public float radius; public float alpha; public float speed; public Color color; + } public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; SetConfigFlags(FLAG_MSAA_4X_HINT); // NOTE: Try to enable MSAA 4X InitWindow(screenWidth, screenHeight, "raylib [audio] example - module playing (streaming)"); InitAudioDevice(); // Initialize audio device Color[] colors = new Color[14] { ORANGE, RED, GOLD, LIME, BLUE, VIOLET, BROWN, LIGHTGRAY, PINK, YELLOW, GREEN, SKYBLUE, PURPLE, BEIGE }; // Creates ome circles for visual effect CircleWave[] circles = new CircleWave[MAX_CIRCLES]; for (int i = MAX_CIRCLES - 1; i >= 0; i--) { circles[i].alpha = 0.0f; circles[i].radius = GetRandomValue(10, 40); circles[i].position.x = GetRandomValue((int)circles[i].radius, screenWidth - (int)circles[i].radius); circles[i].position.y = GetRandomValue((int)circles[i].radius, screenHeight - (int)circles[i].radius); circles[i].speed = (float)GetRandomValue(1, 100)/20000.0f; circles[i].color = colors[GetRandomValue(0, 13)]; } var xm = LoadMusicStream("resources/mini1111.xm"); PlayMusicStream(xm); float timePlayed = 0.0f; bool pause = false; SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateMusicStream(xm); // Update music buffer with new stream data // Restart music playing (stop and play) if (IsKeyPressed(KEY_SPACE)) { StopMusicStream(xm); PlayMusicStream(xm); } // Pause/Resume music playing if (IsKeyPressed(KEY_P)) { pause = !pause; if (pause) PauseMusicStream(xm); else ResumeMusicStream(xm); } // Get timePlayed scaled to bar dimensions timePlayed = GetMusicTimePlayed(xm)/GetMusicTimeLength(xm)*(screenWidth - 40); // Color circles animation for (int i = MAX_CIRCLES - 1; (i >= 0) && !pause; i--) { circles[i].alpha += circles[i].speed; circles[i].radius += circles[i].speed*10.0f; if (circles[i].alpha > 1.0f) circles[i].speed *= -1; if (circles[i].alpha <= 0.0f) { circles[i].alpha = 0.0f; circles[i].radius = GetRandomValue(10, 40); circles[i].position.x = GetRandomValue((int)circles[i].radius, screenWidth - (int)circles[i].radius); circles[i].position.y = GetRandomValue((int)circles[i].radius, screenHeight - (int)circles[i].radius); circles[i].color = colors[GetRandomValue(0, 13)]; circles[i].speed = (float)GetRandomValue(1, 100)/20000.0f; } } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); for (int i = MAX_CIRCLES - 1; i >= 0; i--) { DrawCircleV(circles[i].position, circles[i].radius, Fade(circles[i].color, circles[i].alpha)); } // Draw time bar DrawRectangle(20, screenHeight - 20 - 12, screenWidth - 40, 12, LIGHTGRAY); DrawRectangle(20, screenHeight - 20 - 12, (int)timePlayed, 12, MAROON); DrawRectangleLines(20, screenHeight - 20 - 12, screenWidth - 40, 12, GRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadMusicStream(xm); // Unload music stream buffers from RAM CloseAudioDevice(); // Close audio device (music streaming is automatically stopped) CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/audio/audio_music_stream.cs b/Examples/audio/audio_music_stream.cs index 701b006..5c8b8cf 100644 --- a/Examples/audio/audio_music_stream.cs +++ b/Examples/audio/audio_music_stream.cs @@ -1,7 +1,7 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class audio_music_stream { - /******************************************************************************************* * * raylib [audio] example - IntPtr playing (streaming) * * NOTE: This example requires OpenAL Soft library installed * * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [audio] example - music playing (streaming)"); InitAudioDevice(); // Initialize audio device IntPtr music = LoadMusicStream("resources/guitar_noodling.ogg"); PlayMusicStream(music); float timePlayed = 0.0f; bool pause = false; SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateMusicStream(music); // Update music buffer with new stream data // Restart music playing (stop and play) if (IsKeyPressed((int)Key.SPACE)) { StopMusicStream(music); PlayMusicStream(music); } // Pause/Resume music playing if (IsKeyPressed((int)Key.P)) { pause = !pause; if (pause) PauseMusicStream(music); else ResumeMusicStream(music); } // Get timePlayed scaled to bar dimensions (400 pixels) timePlayed = GetMusicTimePlayed(music)/GetMusicTimeLength(music)*400; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText("MUSIC SHOULD BE PLAYING!", 255, 150, 20, LIGHTGRAY); DrawRectangle(200, 200, 400, 12, LIGHTGRAY); DrawRectangle(200, 200, (int)timePlayed, 12, MAROON); DrawRectangleLines(200, 200, 400, 12, GRAY); DrawText("PRESS SPACE TO RESTART MUSIC", 215, 250, 20, LIGHTGRAY); DrawText("PRESS P TO PAUSE/RESUME MUSIC", 208, 280, 20, LIGHTGRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadMusicStream(music); // Unload music stream buffers from RAM CloseAudioDevice(); // Close audio device (music streaming is automatically stopped) CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [audio] example - IntPtr playing (streaming) * * NOTE: This example requires OpenAL Soft library installed * * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [audio] example - music playing (streaming)"); InitAudioDevice(); // Initialize audio device var music = LoadMusicStream("resources/guitar_noodling.ogg"); PlayMusicStream(music); float timePlayed = 0.0f; bool pause = false; SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateMusicStream(music); // Update music buffer with new stream data // Restart music playing (stop and play) if (IsKeyPressed(KEY_SPACE)) { StopMusicStream(music); PlayMusicStream(music); } // Pause/Resume music playing if (IsKeyPressed(KEY_P)) { pause = !pause; if (pause) PauseMusicStream(music); else ResumeMusicStream(music); } // Get timePlayed scaled to bar dimensions (400 pixels) timePlayed = GetMusicTimePlayed(music)/GetMusicTimeLength(music)*400; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText("MUSIC SHOULD BE PLAYING!", 255, 150, 20, LIGHTGRAY); DrawRectangle(200, 200, 400, 12, LIGHTGRAY); DrawRectangle(200, 200, (int)timePlayed, 12, MAROON); DrawRectangleLines(200, 200, 400, 12, GRAY); DrawText("PRESS SPACE TO RESTART MUSIC", 215, 250, 20, LIGHTGRAY); DrawText("PRESS P TO PAUSE/RESUME MUSIC", 208, 280, 20, LIGHTGRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadMusicStream(music); // Unload music stream buffers from RAM CloseAudioDevice(); // Close audio device (music streaming is automatically stopped) CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/audio/audio_raw_stream.cs b/Examples/audio/audio_raw_stream.cs index 2f30dfe..5d1f988 100644 --- a/Examples/audio/audio_raw_stream.cs +++ b/Examples/audio/audio_raw_stream.cs @@ -1,7 +1,11 @@ -using Raylib; +using System; +using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class audio_raw_stream { - /******************************************************************************************* * * raylib [audio] example - Raw audio streaming * * NOTE: This example requires OpenAL Soft library installed * * 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) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public const #define MAX_SAMPLES 22050 public const #define MAX_SAMPLES_PER_UPDATE 4096 public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [audio] example - raw audio streaming"); InitAudioDevice(); // Initialize audio device // Init raw audio stream (sample rate: 22050, sample size: 16bit-short, channels: 1-mono) AudioStream stream = InitAudioStream(22050, 16, 1); // Generate samples data from sine wave short *data = (short *)malloc(sizeof(short)*MAX_SAMPLES); // TODO: Review data generation, it seems data is discontinued for loop, // for that reason, there is a clip everytime audio stream is looped... for (int i = 0; i < MAX_SAMPLES; i++) { data[i] = (short)(sinf(((2*PI*(float)i)/2)*DEG2RAD)*32000); } PlayAudioStream(stream); // Start processing stream buffer (no data loaded currently) int totalSamples = MAX_SAMPLES; int samplesLeft = totalSamples; Vector2 position = { 0, 0 }; SetTargetFPS(30); // Set our game to run at 30 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // Refill audio stream if required // NOTE: Every update we check if stream data has been already consumed and we update // buffer with new data from the generated samples, we upload data at a rate (MAX_SAMPLES_PER_UPDATE), // but notice that at some point we update < MAX_SAMPLES_PER_UPDATE data... if (IsAudioBufferProcessed(stream)) { int numSamples = 0; if (samplesLeft >= MAX_SAMPLES_PER_UPDATE) numSamples = MAX_SAMPLES_PER_UPDATE; else numSamples = samplesLeft; UpdateAudioStream(stream, data + (totalSamples - samplesLeft), numSamples); samplesLeft -= numSamples; // Reset samples feeding (loop audio) if (samplesLeft <= 0) samplesLeft = totalSamples; } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText("SINE WAVE SHOULD BE PLAYING!", 240, 140, 20, LIGHTGRAY); // NOTE: Draw a part of the sine wave (only screen width, proportional values) for (int i = 0; i < GetScreenWidth(); i++) { position.x = i; position.y = 250 + 50*data[i]/32000; DrawPixelV(position, RED); } EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- free(data); // Unload sine wave data CloseAudioStream(stream); // Close raw audio stream and delete buffers from RAM CloseAudioDevice(); // Close audio device (music streaming is automatically stopped) CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [audio] example - Raw audio streaming * * NOTE: This example requires OpenAL Soft library installed * * 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) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public const int MAX_SAMPLES = 22050; public const int MAX_SAMPLES_PER_UPDATE = 4096; public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [audio] example - raw audio streaming"); InitAudioDevice(); // Initialize audio device // Init raw audio stream (sample rate: 22050, sample size: 16bit-short, channels: 1-mono) AudioStream stream = InitAudioStream(22050, 16, 1); + + // Generate samples data from sine wave + short[] data = new short[MAX_SAMPLES]; //short *data = (short *)malloc(sizeof(short)*MAX_SAMPLES); // TODO: Review data generation, it seems data is discontinued for loop, // for that reason, there is a clip everytime audio stream is looped... for (int i = 0; i < MAX_SAMPLES; i++) { data[i] = (short)(Math.Sin(((2*Math.PI*(float)i)/2)*DEG2RAD)*32000); } PlayAudioStream(stream); // Start processing stream buffer (no data loaded currently) int totalSamples = MAX_SAMPLES; int samplesLeft = totalSamples; Vector2 position = new Vector2( 0, 0 ); SetTargetFPS(30); // Set our game to run at 30 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // Refill audio stream if required // NOTE: Every update we check if stream data has been already consumed and we update // buffer with new data from the generated samples, we upload data at a rate (MAX_SAMPLES_PER_UPDATE), // but notice that at some point we update < MAX_SAMPLES_PER_UPDATE data... if (IsAudioBufferProcessed(stream)) { int numSamples = 0; if (samplesLeft >= MAX_SAMPLES_PER_UPDATE) numSamples = MAX_SAMPLES_PER_UPDATE; else numSamples = samplesLeft; // UpdateAudioStream(stream, data + (totalSamples - samplesLeft), numSamples); samplesLeft -= numSamples; // Reset samples feeding (loop audio) if (samplesLeft <= 0) samplesLeft = totalSamples; } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText("SINE WAVE SHOULD BE PLAYING!", 240, 140, 20, LIGHTGRAY); // NOTE: Draw a part of the sine wave (only screen width, proportional values) for (int i = 0; i < GetScreenWidth(); i++) { position.x = i; position.y = 250 + 50*data[i]/32000; DrawPixelV(position, RED); } EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- // free(data); // Unload sine wave data CloseAudioStream(stream); // Close raw audio stream and delete buffers from RAM CloseAudioDevice(); // Close audio device (music streaming is automatically stopped) CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/audio/audio_sound_loading.cs b/Examples/audio/audio_sound_loading.cs index ea71524..dd53263 100644 --- a/Examples/audio/audio_sound_loading.cs +++ b/Examples/audio/audio_sound_loading.cs @@ -1,7 +1,7 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class audio_sound_loading { - /******************************************************************************************* * * raylib [audio] example - Sound loading and playing * * NOTE: This example requires OpenAL Soft library installed * * 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) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [audio] example - sound loading and playing"); InitAudioDevice(); // Initialize audio device Sound fxWav = LoadSound("resources/sound.wav"); // Load WAV audio file Sound fxOgg = LoadSound("resources/tanatana.ogg"); // Load OGG audio file SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (IsKeyPressed((int)Key.SPACE)) PlaySound(fxWav); // Play WAV sound if (IsKeyPressed((int)Key.ENTER)) PlaySound(fxOgg); // Play OGG sound //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText("Press SPACE to PLAY the WAV sound!", 200, 180, 20, LIGHTGRAY); DrawText("Press ENTER to PLAY the OGG sound!", 200, 220, 20, LIGHTGRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadSound(fxWav); // Unload sound data UnloadSound(fxOgg); // Unload sound data CloseAudioDevice(); // Close audio device CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [audio] example - Sound loading and playing * * NOTE: This example requires OpenAL Soft library installed * * 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) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [audio] example - sound loading and playing"); InitAudioDevice(); // Initialize audio device Sound fxWav = LoadSound("resources/sound.wav"); // Load WAV audio file Sound fxOgg = LoadSound("resources/tanatana.ogg"); // Load OGG audio file SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (IsKeyPressed(KEY_SPACE)) PlaySound(fxWav); // Play WAV sound if (IsKeyPressed(KEY_ENTER)) PlaySound(fxOgg); // Play OGG sound //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText("Press SPACE to PLAY the WAV sound!", 200, 180, 20, LIGHTGRAY); DrawText("Press ENTER to PLAY the OGG sound!", 200, 220, 20, LIGHTGRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadSound(fxWav); // Unload sound data UnloadSound(fxOgg); // Unload sound data CloseAudioDevice(); // Close audio device CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/core/core_2d_camera.cs b/Examples/core/core_2d_camera.cs index e57f2fd..3a3bc4e 100644 --- a/Examples/core/core_2d_camera.cs +++ b/Examples/core/core_2d_camera.cs @@ -1,7 +1,9 @@ using Raylib; using static Raylib.Raylib; +//using static Raylib.Key; +//using static Raylib.Mouse; -public partial class Examples +public partial class core_2d_camera { - /******************************************************************************************* * * 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) * * Copyright (c) 2016 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public const #define MAX_BUILDINGS 100 public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - 2d camera"); Rectangle player = { 400, 280, 40, 40 }; Rectangle[] buildings = new Rectangle[MAX_BUILDINGS]; Color[] buildColors = new Color[MAX_BUILDINGS]; int spacing = 0; for (int i = 0; i < MAX_BUILDINGS; i++) { buildings[i].width = GetRandomValue(50, 200); buildings[i].height = GetRandomValue(100, 800); buildings[i].y = screenHeight - 130 - buildings[i].height; buildings[i].x = -6000 + spacing; spacing += buildings[i].width; buildColors[i] = new Color( GetRandomValue(200, 240), GetRandomValue(200, 240), GetRandomValue(200, 250), 255 );; } Camera2D camera; camera.target = new Vector2( player.x + 20, player.y + 20 );; camera.offset = new Vector2( 0, 0 );; camera.rotation = 0.0f; camera.zoom = 1.0f; SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (IsKeyDown((int)Key.RIGHT)) { player.x += 2; // Player movement camera.offset.x -= 2; // Camera displacement with player movement } else if (IsKeyDown((int)Key.LEFT)) { player.x -= 2; // Player movement camera.offset.x += 2; // Camera displacement with player movement } // Camera target follows player camera.target = new Vector2( player.x + 20, player.y + 20 );; // Camera rotation controls if (IsKeyDown((int)Key.A)) camera.rotation--; else if (IsKeyDown((int)Key.S)) camera.rotation++; // Limit camera rotation to 80 degrees (-40 to 40) if (camera.rotation > 40) camera.rotation = 40; else if (camera.rotation < -40) camera.rotation = -40; // Camera zoom controls camera.zoom += ((float)GetMouseWheelMove()*0.05f); if (camera.zoom > 3.0f) camera.zoom = 3.0f; else if (camera.zoom < 0.1f) camera.zoom = 0.1f; // Camera reset (zoom and rotation) if (IsKeyPressed((int)Key.R)) { camera.zoom = 1.0f; camera.rotation = 0.0f; } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode2D(camera); DrawRectangle(-6000, 320, 13000, 8000, DARKGRAY); for (int i = 0; i < MAX_BUILDINGS; i++) DrawRectangleRec(buildings[i], buildColors[i]); DrawRectangleRec(player, RED); DrawRectangle(camera.target.x, -500, 1, screenHeight*4, GREEN); DrawRectangle(-500, camera.target.y, screenWidth*4, 1, GREEN); EndMode2D(); DrawText("SCREEN AREA", 640, 10, 20, RED); DrawRectangle(0, 0, screenWidth, 5, RED); DrawRectangle(0, 5, 5, screenHeight - 10, RED); DrawRectangle(screenWidth - 5, 5, 5, screenHeight - 10, RED); DrawRectangle(0, screenHeight - 5, screenWidth, 5, RED); DrawRectangle( 10, 10, 250, 113, Fade(SKYBLUE, 0.5f)); DrawRectangleLines( 10, 10, 250, 113, BLUE); DrawText("Free 2d camera controls:", 20, 20, 10, BLACK); DrawText("- Right/Left to move Offset", 40, 40, 10, DARKGRAY); DrawText("- Mouse Wheel to Zoom in-out", 40, 60, 10, DARKGRAY); DrawText("- A / S to Rotate", 40, 80, 10, DARKGRAY); DrawText("- R to reset Zoom and Rotation", 40, 100, 10, DARKGRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * 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) * * Copyright (c) 2016 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public const int MAX_BUILDINGS = 100; public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - 2d camera"); Rectangle player = new Rectangle( 400, 280, 40, 40 ); Rectangle[] buildings = new Rectangle[MAX_BUILDINGS]; Color[] buildColors = new Color[MAX_BUILDINGS]; int spacing = 0; for (int i = 0; i < MAX_BUILDINGS; i++) { buildings[i].width = GetRandomValue(50, 200); buildings[i].height = GetRandomValue(100, 800); buildings[i].y = screenHeight - 130 - buildings[i].height; buildings[i].x = -6000 + spacing; spacing += (int)buildings[i].width; buildColors[i] = new Color( GetRandomValue(200, 240), GetRandomValue(200, 240), GetRandomValue(200, 250), 255 ); } Camera2D camera; camera.target = new Vector2( player.x + 20, player.y + 20 ); camera.offset = new Vector2( 0, 0 ); camera.rotation = 0.0f; camera.zoom = 1.0f; SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (IsKeyDown(KEY_RIGHT)) { player.x += 2; // Player movement camera.offset.x -= 2; // Camera3D displacement with player movement } else if (IsKeyDown(KEY_LEFT)) { player.x -= 2; // Player movement camera.offset.x += 2; // Camera3D displacement with player movement } // Camera3D target follows player camera.target = new Vector2( player.x + 20, player.y + 20 ); // Camera3D rotation controls if (IsKeyDown(KEY_A)) camera.rotation--; else if (IsKeyDown(KEY_S)) camera.rotation++; // Limit camera rotation to 80 degrees (-40 to 40) if (camera.rotation > 40) camera.rotation = 40; else if (camera.rotation < -40) camera.rotation = -40; // Camera3D zoom controls camera.zoom += ((float)GetMouseWheelMove()*0.05f); if (camera.zoom > 3.0f) camera.zoom = 3.0f; else if (camera.zoom < 0.1f) camera.zoom = 0.1f; // Camera3D reset (zoom and rotation) if (IsKeyPressed((int)KEY_R)) { camera.zoom = 1.0f; camera.rotation = 0.0f; } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode2D(camera); DrawRectangle(-6000, 320, 13000, 8000, DARKGRAY); for (int i = 0; i < MAX_BUILDINGS; i++) DrawRectangleRec(buildings[i], buildColors[i]); DrawRectangleRec(player, RED); DrawRectangle((int)camera.target.x, -500, 1, screenHeight*4, GREEN); DrawRectangle(-500, (int)camera.target.y, screenWidth*4, 1, GREEN); EndMode2D(); DrawText("SCREEN AREA", 640, 10, 20, RED); DrawRectangle(0, 0, screenWidth, 5, RED); DrawRectangle(0, 5, 5, screenHeight - 10, RED); DrawRectangle(screenWidth - 5, 5, 5, screenHeight - 10, RED); DrawRectangle(0, screenHeight - 5, screenWidth, 5, RED); DrawRectangle( 10, 10, 250, 113, Fade(SKYBLUE, 0.5f)); DrawRectangleLines( 10, 10, 250, 113, BLUE); DrawText("Free 2d camera controls:", 20, 20, 10, BLACK); DrawText("- Right/Left to move Offset", 40, 40, 10, DARKGRAY); DrawText("- Mouse Wheel to Zoom in-out", 40, 60, 10, DARKGRAY); DrawText("- A / S to Rotate", 40, 80, 10, DARKGRAY); DrawText("- R to reset Zoom and Rotation", 40, 100, 10, DARKGRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/core/core_3d_camera_first_person.cs b/Examples/core/core_3d_camera_first_person.cs index 8b51ac1..0cd362a 100644 --- a/Examples/core/core_3d_camera_first_person.cs +++ b/Examples/core/core_3d_camera_first_person.cs @@ -1,7 +1,9 @@ using Raylib; using static Raylib.Raylib; +using static Raylib.CameraType; +using static Raylib.CameraMode; -public partial class Examples +public partial class core_3d_camera_first_person { - /******************************************************************************************* * * raylib [core] example - 3d camera first person * * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public const #define MAX_COLUMNS 20 public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera first person"); // Define the camera to look into our 3d world (position, target, up vector) Camera camera = { 0 }; camera.position = new Vector3( 4.0f, 2.0f, 4.0f );; camera.target = new Vector3( 0.0f, 1.8f, 0.0f );; camera.up = new Vector3( 0.0f, 1.0f, 0.0f );; camera.fovy = 60.0f; camera.type = CAMERA_PERSPECTIVE; // Generates some random columns float[] heights = new float[MAX_COLUMNS]; Vector3[] positions = new Vector3[MAX_COLUMNS]; Color[] colors = new Color[MAX_COLUMNS]; for (int i = 0; i < MAX_COLUMNS; i++) { heights[i] = (float)GetRandomValue(1, 12); positions[i] = new Vector3( GetRandomValue(-15, 15), heights[i]/2, GetRandomValue(-15, 15) );; colors[i] = new Color( GetRandomValue(20, 255), GetRandomValue(10, 55), 30, 255 );; } SetCameraMode(camera, CAMERA_FIRST_PERSON); // Set a first person camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateCamera(&camera); // Update camera //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); DrawPlane(new Vector3( 0.0f, 0.0f, 0.0f }, (Vector2){ 32.0f, 32.0f );, LIGHTGRAY); // Draw ground DrawCube(new Vector3( -16.0f, 2.5f, 0.0f );, 1.0f, 5.0f, 32.0f, BLUE); // Draw a blue wall DrawCube(new Vector3( 16.0f, 2.5f, 0.0f );, 1.0f, 5.0f, 32.0f, LIME); // Draw a green wall DrawCube(new Vector3( 0.0f, 2.5f, 16.0f );, 32.0f, 5.0f, 1.0f, GOLD); // Draw a yellow wall // Draw some cubes around for (int i = 0; i < MAX_COLUMNS; i++) { DrawCube(positions[i], 2.0f, heights[i], 2.0f, colors[i]); DrawCubeWires(positions[i], 2.0f, heights[i], 2.0f, MAROON); } EndMode3D(); DrawRectangle( 10, 10, 220, 70, Fade(SKYBLUE, 0.5f)); DrawRectangleLines( 10, 10, 220, 70, BLUE); DrawText("First person camera default controls:", 20, 20, 10, BLACK); DrawText("- Move with keys: W, A, S, D", 40, 40, 10, DARKGRAY); DrawText("- Mouse move to look around", 40, 60, 10, DARKGRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [core] example - 3d camera first person * * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public const int MAX_COLUMNS = 20; public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera first person"); // Define the camera to look into our 3d world (position, target, up vector) Camera3D camera = new Camera3D(); camera.position = new Vector3( 4.0f, 2.0f, 4.0f ); camera.target = new Vector3( 0.0f, 1.8f, 0.0f ); camera.up = new Vector3( 0.0f, 1.0f, 0.0f ); camera.fovy = 60.0f; camera.type = (int)CAMERA_PERSPECTIVE; // Generates some random columns float[] heights = new float[MAX_COLUMNS]; Vector3[] positions = new Vector3[MAX_COLUMNS]; Color[] colors = new Color[MAX_COLUMNS]; for (int i = 0; i < MAX_COLUMNS; i++) { heights[i] = (float)GetRandomValue(1, 12); positions[i] = new Vector3( GetRandomValue(-15, 15), heights[i]/2, GetRandomValue(-15, 15) ); colors[i] = new Color( GetRandomValue(20, 255), GetRandomValue(10, 55), 30, 255 ); } SetCameraMode(camera, (int)CAMERA_FIRST_PERSON); // Set a first person camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateCamera(ref camera); // Update camera //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); DrawPlane(new Vector3( 0.0f, 0.0f, 0.0f ), new Vector2( 32.0f, 32.0f ), LIGHTGRAY); // Draw ground DrawCube(new Vector3( -16.0f, 2.5f, 0.0f ), 1.0f, 5.0f, 32.0f, BLUE); // Draw a blue wall DrawCube(new Vector3( 16.0f, 2.5f, 0.0f ), 1.0f, 5.0f, 32.0f, LIME); // Draw a green wall DrawCube(new Vector3( 0.0f, 2.5f, 16.0f ), 32.0f, 5.0f, 1.0f, GOLD); // Draw a yellow wall // Draw some cubes around for (int i = 0; i < MAX_COLUMNS; i++) { DrawCube(positions[i], 2.0f, heights[i], 2.0f, colors[i]); DrawCubeWires(positions[i], 2.0f, heights[i], 2.0f, MAROON); } EndMode3D(); DrawRectangle( 10, 10, 220, 70, Fade(SKYBLUE, 0.5f)); DrawRectangleLines( 10, 10, 220, 70, BLUE); DrawText("First person camera default controls:", 20, 20, 10, BLACK); DrawText("- Move with keys: W, A, S, D", 40, 40, 10, DARKGRAY); DrawText("- Mouse move to look around", 40, 60, 10, DARKGRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/core/core_3d_camera_free.cs b/Examples/core/core_3d_camera_free.cs index 1f4f1cc..a513b2a 100644 --- a/Examples/core/core_3d_camera_free.cs +++ b/Examples/core/core_3d_camera_free.cs @@ -1,7 +1,9 @@ using Raylib; using static Raylib.Raylib; +using static Raylib.CameraType; +using static Raylib.CameraMode; -public partial class Examples +public partial class core_3d_camera_free { - /******************************************************************************************* * * raylib [core] example - Initialize 3d camera free * * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera free"); // Define the camera to look into our 3d world Camera3D camera; camera.position = new Vector3( 10.0f, 10.0f, 10.0f );; // Camera position camera.target = new Vector3( 0.0f, 0.0f, 0.0f );; // Camera looking at point camera.up = new Vector3( 0.0f, 1.0f, 0.0f );; // Camera up vector (rotation towards target) camera.fovy = 45.0f; // Camera field-of-view Y camera.type = CAMERA_PERSPECTIVE; // Camera mode type Vector3 cubePosition = { 0.0f, 0.0f, 0.0f }; SetCameraMode(camera, CAMERA_FREE); // Set a free camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateCamera(&camera); // Update camera if (IsKeyDown('Z')) camera.target = new Vector3( 0.0f, 0.0f, 0.0f );; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED); DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON); DrawGrid(10, 1.0f); EndMode3D(); DrawRectangle( 10, 10, 320, 133, Fade(SKYBLUE, 0.5f)); DrawRectangleLines( 10, 10, 320, 133, BLUE); DrawText("Free camera default controls:", 20, 20, 10, BLACK); DrawText("- Mouse Wheel to Zoom in-out", 40, 40, 10, DARKGRAY); DrawText("- Mouse Wheel Pressed to Pan", 40, 60, 10, DARKGRAY); DrawText("- Alt + Mouse Wheel Pressed to Rotate", 40, 80, 10, DARKGRAY); DrawText("- Alt + Ctrl + Mouse Wheel Pressed for Smooth Zoom", 40, 100, 10, DARKGRAY); DrawText("- Z to zoom to (0, 0, 0)", 40, 120, 10, DARKGRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [core] example - Initialize 3d camera free * * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera free"); // Define the camera to look into our 3d world Camera3D camera; camera.position = new Vector3( 10.0f, 10.0f, 10.0f ); // Camera3D position camera.target = new Vector3( 0.0f, 0.0f, 0.0f ); // Camera3D looking at point camera.up = new Vector3( 0.0f, 1.0f, 0.0f ); // Camera3D up vector (rotation towards target) camera.fovy = 45.0f; // Camera3D field-of-view Y camera.type = (int)CAMERA_PERSPECTIVE; // Camera3D mode type Vector3 cubePosition = new Vector3( 0.0f, 0.0f, 0.0f ); SetCameraMode(camera, (int)CAMERA_FREE); // Set a free camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateCamera(ref camera); // Update camera if (IsKeyDown('Z')) camera.target = new Vector3( 0.0f, 0.0f, 0.0f ); //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED); DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON); DrawGrid(10, 1.0f); EndMode3D(); DrawRectangle( 10, 10, 320, 133, Fade(SKYBLUE, 0.5f)); DrawRectangleLines( 10, 10, 320, 133, BLUE); DrawText("Free camera default controls:", 20, 20, 10, BLACK); DrawText("- Mouse Wheel to Zoom in-out", 40, 40, 10, DARKGRAY); DrawText("- Mouse Wheel Pressed to Pan", 40, 60, 10, DARKGRAY); DrawText("- Alt + Mouse Wheel Pressed to Rotate", 40, 80, 10, DARKGRAY); DrawText("- Alt + Ctrl + Mouse Wheel Pressed for Smooth Zoom", 40, 100, 10, DARKGRAY); DrawText("- Z to zoom to (0, 0, 0)", 40, 120, 10, DARKGRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/core/core_3d_mode.cs b/Examples/core/core_3d_mode.cs index 24f882c..c65ec20 100644 --- a/Examples/core/core_3d_mode.cs +++ b/Examples/core/core_3d_mode.cs @@ -1,7 +1,8 @@ using Raylib; using static Raylib.Raylib; +using static Raylib.CameraType; -public partial class Examples +public partial class core_3d_mode { - /******************************************************************************************* * * raylib [core] example - Initialize 3d mode * * 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) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d mode"); // Define the camera to look into our 3d world Camera3D camera; camera.position = new Vector3( 0.0f, 10.0f, 10.0f );; // Camera position camera.target = new Vector3( 0.0f, 0.0f, 0.0f );; // Camera looking at point camera.up = new Vector3( 0.0f, 1.0f, 0.0f );; // Camera up vector (rotation towards target) camera.fovy = 45.0f; // Camera field-of-view Y camera.type = CAMERA_PERSPECTIVE; // Camera mode type Vector3 cubePosition = { 0.0f, 0.0f, 0.0f }; SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update your variables here //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED); DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON); DrawGrid(10, 1.0f); EndMode3D(); DrawText("Welcome to the third dimension!", 10, 40, 20, DARKGRAY); DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [core] example - Initialize 3d mode * * 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) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d mode"); // Define the camera to look into our 3d world Camera3D camera; camera.position = new Vector3( 0.0f, 10.0f, 10.0f ); // Camera3D position camera.target = new Vector3( 0.0f, 0.0f, 0.0f ); // Camera3D looking at point camera.up = new Vector3( 0.0f, 1.0f, 0.0f ); // Camera3D up vector (rotation towards target) camera.fovy = 45.0f; // Camera3D field-of-view Y camera.type = CAMERA_PERSPECTIVE; // Camera3D mode type Vector3 cubePosition = new Vector3( 0.0f, 0.0f, 0.0f ); SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update your variables here //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED); DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON); DrawGrid(10, 1.0f); EndMode3D(); DrawText("Welcome to the third dimension!", 10, 40, 20, DARKGRAY); DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/core/core_3d_picking.cs b/Examples/core/core_3d_picking.cs index 0709b95..11267df 100644 --- a/Examples/core/core_3d_picking.cs +++ b/Examples/core/core_3d_picking.cs @@ -1,7 +1,9 @@ using Raylib; using static Raylib.Raylib; +using static Raylib.CameraType; +using static Raylib.CameraMode; -public partial class Examples +public partial class core_3d_picking { - /******************************************************************************************* * * raylib [core] example - Picking in 3d mode * * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d picking"); // Define the camera to look into our 3d world Camera camera; camera.position = new Vector3( 10.0f, 10.0f, 10.0f );; // Camera position camera.target = new Vector3( 0.0f, 0.0f, 0.0f );; // Camera looking at point camera.up = new Vector3( 0.0f, 1.0f, 0.0f );; // Camera up vector (rotation towards target) camera.fovy = 45.0f; // Camera field-of-view Y camera.type = CAMERA_PERSPECTIVE; // Camera mode type Vector3 cubePosition = { 0.0f, 1.0f, 0.0f }; Vector3 cubeSize = { 2.0f, 2.0f, 2.0f }; Ray ray = {0.0f, 0.0f, 0.0f}; // Picking line ray bool collision = false; SetCameraMode(camera, CAMERA_FREE); // Set a free camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateCamera(&camera); // Update camera if (IsMouseButtonPressed((int)Mouse.LEFT_BUTTON)) { ray = GetMouseRay(GetMousePosition(), camera); // Check collision between ray and box collision = CheckCollisionRayBox(ray, new BoundingBox((Vector3){ cubePosition.x - cubeSize.x/2, cubePosition.y - cubeSize.y/2, cubePosition.z - cubeSize.z/2 );, new Vector3( cubePosition.x + cubeSize.x/2, cubePosition.y + cubeSize.y/2, cubePosition.z + cubeSize.z/2 });); } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); if (collision) { DrawCube(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, RED); DrawCubeWires(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, MAROON); DrawCubeWires(cubePosition, cubeSize.x + 0.2f, cubeSize.y + 0.2f, cubeSize.z + 0.2f, GREEN); } else { DrawCube(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, GRAY); DrawCubeWires(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, DARKGRAY); } DrawRay(ray, MAROON); DrawGrid(10, 1.0f); EndMode3D(); DrawText("Try selecting the box with mouse!", 240, 10, 20, DARKGRAY); if(collision) DrawText("BOX SELECTED", (screenWidth - MeasureText("BOX SELECTED", 30)) / 2, screenHeight * 0.1f, 30, GREEN); DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [core] example - Picking in 3d mode * * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d picking"); // Define the camera to look into our 3d world Camera3D camera; camera.position = new Vector3( 10.0f, 10.0f, 10.0f ); // Camera3D position camera.target = new Vector3( 0.0f, 0.0f, 0.0f ); // Camera3D looking at point camera.up = new Vector3( 0.0f, 1.0f, 0.0f ); // Camera3D up vector (rotation towards target) camera.fovy = 45.0f; // Camera3D field-of-view Y camera.type = (int)CAMERA_PERSPECTIVE; // Camera3D mode type Vector3 cubePosition = new Vector3( 0.0f, 1.0f, 0.0f ); Vector3 cubeSize = new Vector3( 2.0f, 2.0f, 2.0f ); Ray ray = new Ray(new Vector3(0.0f, 0.0f, 0.0f), Vector3.Zero); // Picking line ray bool collision = false; SetCameraMode(camera, (int)CAMERA_FREE); // Set a free camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateCamera(ref camera); // Update camera if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { ray = GetMouseRay(GetMousePosition(), camera); // Check collision between ray and box collision = CheckCollisionRayBox(ray, new BoundingBox(new Vector3( cubePosition.x - cubeSize.x/2, cubePosition.y - cubeSize.y/2, cubePosition.z - cubeSize.z/2 ), new Vector3( cubePosition.x + cubeSize.x/2, cubePosition.y + cubeSize.y/2, cubePosition.z + cubeSize.z/2 ))); } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); if (collision) { DrawCube(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, RED); DrawCubeWires(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, MAROON); DrawCubeWires(cubePosition, cubeSize.x + 0.2f, cubeSize.y + 0.2f, cubeSize.z + 0.2f, GREEN); } else { DrawCube(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, GRAY); DrawCubeWires(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, DARKGRAY); } DrawRay(ray, MAROON); DrawGrid(10, 1.0f); EndMode3D(); DrawText("Try selecting the box with mouse!", 240, 10, 20, DARKGRAY); if(collision) DrawText("BOX SELECTED", (screenWidth - MeasureText("BOX SELECTED", 30)) / 2, (int)(screenHeight * 0.1f), 30, GREEN); DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/core/core_basic_window.cs b/Examples/core/core_basic_window.cs index f46086c..08c34f3 100644 --- a/Examples/core/core_basic_window.cs +++ b/Examples/core/core_basic_window.cs @@ -1 +1 @@ -using Raylib; using static Raylib.Raylib; public partial class Examples { /******************************************************************************************* * * raylib [core] example - Basic window * * Welcome to raylib! * * 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 * * 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) * * Copyright (c) 2013-2016 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window"); SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update your variables here //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText("Congrats! You created your first window!", 190, 200, 20, MAROON); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- } } \ No newline at end of file +using Raylib; using static Raylib.Raylib; public partial class core_basic_window { /******************************************************************************************* * * raylib [core] example - Basic window * * Welcome to raylib! * * 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 * * 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) * * Copyright (c) 2013-2016 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window"); SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update your variables here //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText("Congrats! You created your first window!", 190, 200, 20, MAROON); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } \ No newline at end of file diff --git a/Examples/core/core_color_select.cs b/Examples/core/core_color_select.cs index fc6e2ed..f926470 100644 --- a/Examples/core/core_color_select.cs +++ b/Examples/core/core_color_select.cs @@ -1,7 +1,7 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class core_color_select { - /******************************************************************************************* * * raylib [core] example - Color selection by mouse (collision detection) * * 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) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - color selection (collision detection)"); Color colors[21] = { DARKGRAY, MAROON, ORANGE, DARKGREEN, DARKBLUE, DARKPURPLE, DARKBROWN, GRAY, RED, GOLD, LIME, BLUE, VIOLET, BROWN, LIGHTGRAY, PINK, YELLOW, GREEN, SKYBLUE, PURPLE, BEIGE }; Rectangle[] colorsRecs = new Rectangle[21]; // Rectangles array // Fills colorsRecs data (for every rectangle) for (int i = 0; i < 21; i++) { colorsRecs[i].x = 20 + 100*(i%7) + 10*(i%7); colorsRecs[i].y = 60 + 100*(i/7) + 10*(i/7); colorsRecs[i].width = 100; colorsRecs[i].height = 100; } bool selected[21] = { false }; // Selected rectangles indicator Vector2 mousePoint; 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 //---------------------------------------------------------------------------------- mousePoint = GetMousePosition(); for (int i = 0; i < 21; i++) // Iterate along all the rectangles { if (CheckCollisionPointRec(mousePoint, colorsRecs[i])) { colors[i].a = 120; if (IsMouseButtonPressed((int)Mouse.LEFT_BUTTON)) selected[i] = !selected[i]; } else colors[i].a = 255; } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); for (int i = 0; i < 21; i++) // Draw all rectangles { DrawRectangleRec(colorsRecs[i], colors[i]); // Draw four rectangles around selected rectangle if (selected[i]) { DrawRectangle(colorsRecs[i].x, colorsRecs[i].y, 100, 10, RAYWHITE); // Square top rectangle DrawRectangle(colorsRecs[i].x, colorsRecs[i].y, 10, 100, RAYWHITE); // Square left rectangle DrawRectangle(colorsRecs[i].x + 90, colorsRecs[i].y, 10, 100, RAYWHITE); // Square right rectangle DrawRectangle(colorsRecs[i].x, colorsRecs[i].y + 90, 100, 10, RAYWHITE); // Square bottom rectangle } } EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [core] example - Color selection by mouse (collision detection) * * 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) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - color selection (collision detection)"); Color[] colors = new Color[21] { DARKGRAY, MAROON, ORANGE, DARKGREEN, DARKBLUE, DARKPURPLE, DARKBROWN, GRAY, RED, GOLD, LIME, BLUE, VIOLET, BROWN, LIGHTGRAY, PINK, YELLOW, GREEN, SKYBLUE, PURPLE, BEIGE }; Rectangle[] colorsRecs = new Rectangle[21]; // Rectangles array // Fills colorsRecs data (for every rectangle) for (int i = 0; i < 21; i++) { colorsRecs[i].x = 20 + 100*(i%7) + 10*(i%7); colorsRecs[i].y = 60 + 100*(i/7) + 10*(i/7); colorsRecs[i].width = 100; colorsRecs[i].height = 100; } bool[] selected = new bool[21]; // Selected rectangles indicator Vector2 mousePoint; 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 //---------------------------------------------------------------------------------- mousePoint = GetMousePosition(); for (int i = 0; i < 21; i++) // Iterate along all the rectangles { if (CheckCollisionPointRec(mousePoint, colorsRecs[i])) { colors[i].a = 120; if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) selected[i] = !selected[i]; } else colors[i].a = 255; } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); for (int i = 0; i < 21; i++) // Draw all rectangles { DrawRectangleRec(colorsRecs[i], colors[i]); // Draw four rectangles around selected rectangle if (selected[i]) { DrawRectangle((int)colorsRecs[i].x, (int)colorsRecs[i].y, 100, 10, RAYWHITE); // Square top rectangle DrawRectangle((int)colorsRecs[i].x, (int)colorsRecs[i].y, 10, 100, RAYWHITE); // Square left rectangle DrawRectangle((int)colorsRecs[i].x + 90, (int)colorsRecs[i].y, 10, 100, RAYWHITE); // Square right rectangle DrawRectangle((int)colorsRecs[i].x, (int)colorsRecs[i].y + 90, 100, 10, RAYWHITE); // Square bottom rectangle } } EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/core/core_drop_files.cs b/Examples/core/core_drop_files.cs index 1d92e10..abe12a1 100644 --- a/Examples/core/core_drop_files.cs +++ b/Examples/core/core_drop_files.cs @@ -1,7 +1,7 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class core_drop_files { - /******************************************************************************************* * * raylib [core] example - Windows drop files * * This example only works on platforms that support drag & drop (Windows, Linux, OSX, Html5?) * * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - drop files"); int count = 0; char **droppedFiles = { 0 }; SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (IsFileDropped()) { droppedFiles = GetDroppedFiles(&count); } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); if (count == 0) DrawText("Drop your files to this window!", 100, 40, 20, DARKGRAY); else { DrawText("Dropped files:", 100, 40, 20, DARKGRAY); for (int i = 0; i < count; i++) { if (i%2 == 0) DrawRectangle(0, 85 + 40*i, screenWidth, 40, Fade(LIGHTGRAY, 0.5f)); else DrawRectangle(0, 85 + 40*i, screenWidth, 40, Fade(LIGHTGRAY, 0.3f)); DrawText(droppedFiles[i], 120, 100 + 40*i, 10, GRAY); } DrawText("Drop new files...", 100, 110 + 40*count, 20, DARKGRAY); } EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- ClearDroppedFiles(); // Clear internal buffers CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [core] example - Windows drop files * * This example only works on platforms that support drag ref drop (Windows, Linux, OSX, Html5?) * * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - drop files"); int count = 0; string[] droppedFiles = { }; SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (IsFileDropped()) { droppedFiles = GetDroppedFiles(ref count); } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); if (count == 0) DrawText("Drop your files to this window!", 100, 40, 20, DARKGRAY); else { DrawText("Dropped files:", 100, 40, 20, DARKGRAY); for (int i = 0; i < count; i++) { if (i%2 == 0) DrawRectangle(0, 85 + 40*i, screenWidth, 40, Fade(LIGHTGRAY, 0.5f)); else DrawRectangle(0, 85 + 40*i, screenWidth, 40, Fade(LIGHTGRAY, 0.3f)); DrawText(droppedFiles[i], 120, 100 + 40*i, 10, GRAY); } DrawText("Drop new files...", 100, 110 + 40*count, 20, DARKGRAY); } EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- ClearDroppedFiles(); // Clear internal buffers CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/core/core_gestures_detection.cs b/Examples/core/core_gestures_detection.cs index aaff242..670ed6a 100644 --- a/Examples/core/core_gestures_detection.cs +++ b/Examples/core/core_gestures_detection.cs @@ -1,7 +1,10 @@ using Raylib; using static Raylib.Raylib; +using static Raylib.Gestures; -public partial class Examples +public partial class core_gestures_detection { - /******************************************************************************************* * * raylib [core] example - Gestures Detection * * 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) * * Copyright (c) 2016 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public const #define MAX_GESTURE_STRINGS 20 public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - gestures detection"); Vector2 touchPosition = { 0, 0 }; Rectangle touchArea = { 220, 10, screenWidth - 230, screenHeight - 20 }; int gesturesCount = 0; char[] gestureStrings = new char[MAX_GESTURE_STRINGS][32]; int currentGesture = GESTURE_NONE; int lastGesture = GESTURE_NONE; //SetGesturesEnabled(0b0000000000001001); // Enable only some gestures to be detected SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- lastGesture = currentGesture; currentGesture = GetGestureDetected(); touchPosition = GetTouchPosition(0); if (CheckCollisionPointRec(touchPosition, touchArea) && (currentGesture != GESTURE_NONE)) { if (currentGesture != lastGesture) { // Store gesture string switch (currentGesture) { case GESTURE_TAP: strcpy(gestureStrings[gesturesCount], "GESTURE TAP"); break; case GESTURE_DOUBLETAP: strcpy(gestureStrings[gesturesCount], "GESTURE DOUBLETAP"); break; case GESTURE_HOLD: strcpy(gestureStrings[gesturesCount], "GESTURE HOLD"); break; case GESTURE_DRAG: strcpy(gestureStrings[gesturesCount], "GESTURE DRAG"); break; case GESTURE_SWIPE_RIGHT: strcpy(gestureStrings[gesturesCount], "GESTURE SWIPE RIGHT"); break; case GESTURE_SWIPE_LEFT: strcpy(gestureStrings[gesturesCount], "GESTURE SWIPE LEFT"); break; case GESTURE_SWIPE_UP: strcpy(gestureStrings[gesturesCount], "GESTURE SWIPE UP"); break; case GESTURE_SWIPE_DOWN: strcpy(gestureStrings[gesturesCount], "GESTURE SWIPE DOWN"); break; case GESTURE_PINCH_IN: strcpy(gestureStrings[gesturesCount], "GESTURE PINCH IN"); break; case GESTURE_PINCH_OUT: strcpy(gestureStrings[gesturesCount], "GESTURE PINCH OUT"); break; default: break; } gesturesCount++; // Reset gestures strings if (gesturesCount >= MAX_GESTURE_STRINGS) { for (int i = 0; i < MAX_GESTURE_STRINGS; i++) strcpy(gestureStrings[i], "\0"); gesturesCount = 0; } } } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawRectangleRec(touchArea, GRAY); DrawRectangle(225, 15, screenWidth - 240, screenHeight - 30, RAYWHITE); DrawText("GESTURES TEST AREA", screenWidth - 270, screenHeight - 40, 20, Fade(GRAY, 0.5f)); for (int i = 0; i < gesturesCount; i++) { if (i%2 == 0) DrawRectangle(10, 30 + 20*i, 200, 20, Fade(LIGHTGRAY, 0.5f)); else DrawRectangle(10, 30 + 20*i, 200, 20, Fade(LIGHTGRAY, 0.3f)); if (i < gesturesCount - 1) DrawText(gestureStrings[i], 35, 36 + 20*i, 10, DARKGRAY); else DrawText(gestureStrings[i], 35, 36 + 20*i, 10, MAROON); } DrawRectangleLines(10, 29, 200, screenHeight - 50, GRAY); DrawText("DETECTED GESTURES", 50, 15, 10, GRAY); if (currentGesture != GESTURE_NONE) DrawCircleV(touchPosition, 30, MAROON); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- } + /******************************************************************************************* * * raylib [core] example - Gestures Detection * * 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) * * Copyright (c) 2016 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public const int MAX_GESTURE_STRINGS = 20; public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - gestures detection"); Vector2 touchPosition = new Vector2( 0, 0 ); Rectangle touchArea = new Rectangle( 220, 10, screenWidth - 230, screenHeight - 20 ); int gesturesCount = 0; string[] gestureStrings = new string[MAX_GESTURE_STRINGS]; int currentGesture = (int)GESTURE_NONE; int lastGesture = (int)GESTURE_NONE; //SetGesturesEnabled(0b0000000000001001); // Enable only some gestures to be detected SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- lastGesture = currentGesture; currentGesture = GetGestureDetected(); touchPosition = GetTouchPosition(0); if (CheckCollisionPointRec(touchPosition, touchArea) && (currentGesture != (int)GESTURE_NONE)) { if (currentGesture != lastGesture) { // Store gesture string switch (currentGesture) { case (int)GESTURE_TAP: gestureStrings[gesturesCount] = "GESTURE TAP"; break; case (int)GESTURE_DOUBLETAP: gestureStrings[gesturesCount] = "GESTURE DOUBLETAP"; break; case (int)GESTURE_HOLD: gestureStrings[gesturesCount] = "GESTURE HOLD"; break; case (int)GESTURE_DRAG: gestureStrings[gesturesCount] = "GESTURE DRAG"; break; case (int)GESTURE_SWIPE_RIGHT: gestureStrings[gesturesCount] = "GESTURE SWIPE RIGHT"; break; case (int)GESTURE_SWIPE_LEFT: gestureStrings[gesturesCount] = "GESTURE SWIPE LEFT"; break; case (int)GESTURE_SWIPE_UP: gestureStrings[gesturesCount] = "GESTURE SWIPE UP"; break; case (int)GESTURE_SWIPE_DOWN: gestureStrings[gesturesCount] = "GESTURE SWIPE DOWN"; break; case (int)GESTURE_PINCH_IN: gestureStrings[gesturesCount] = "GESTURE PINCH IN"; break; case (int)GESTURE_PINCH_OUT: gestureStrings[gesturesCount] = "GESTURE PINCH OUT"; break; default: break; } gesturesCount++; // Reset gestures strings if (gesturesCount >= MAX_GESTURE_STRINGS) { for (int i = 0; i < MAX_GESTURE_STRINGS; i++) gestureStrings[i] = " "; gesturesCount = 0; } } } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawRectangleRec(touchArea, GRAY); DrawRectangle(225, 15, screenWidth - 240, screenHeight - 30, RAYWHITE); DrawText("GESTURES TEST AREA", screenWidth - 270, screenHeight - 40, 20, Fade(GRAY, 0.5f)); for (int i = 0; i < gesturesCount; i++) { if (i%2 == 0) DrawRectangle(10, 30 + 20*i, 200, 20, Fade(LIGHTGRAY, 0.5f)); else DrawRectangle(10, 30 + 20*i, 200, 20, Fade(LIGHTGRAY, 0.3f)); if (i < gesturesCount - 1) DrawText(gestureStrings[i], 35, 36 + 20*i, 10, DARKGRAY); else DrawText(gestureStrings[i], 35, 36 + 20*i, 10, MAROON); } DrawRectangleLines(10, 29, 200, screenHeight - 50, GRAY); DrawText("DETECTED GESTURES", 50, 15, 10, GRAY); if (currentGesture != (int)GESTURE_NONE) DrawCircleV(touchPosition, 30, MAROON); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + return 0; } } diff --git a/Examples/core/core_input_gamepad.cs b/Examples/core/core_input_gamepad.cs index e9ddeb6..d07ade7 100644 --- a/Examples/core/core_input_gamepad.cs +++ b/Examples/core/core_input_gamepad.cs @@ -1,7 +1,172 @@ using Raylib; using static Raylib.Raylib; +// using static Raylib.Gamepad; -public partial class Examples -{ - /******************************************************************************************* * * 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) * ********************************************************************************************/ // NOTE: Gamepad name ID depends on drivers and OS #define XBOX360_NAME_ID "Microsoft X-Box 360 pad" #define PS3_NAME_ID "PLAYSTATION(R)3 Controller" #else #define XBOX360_NAME_ID "Xbox 360 Controller" #define PS3_NAME_ID "PLAYSTATION(R)3 Controller" public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; SetConfigFlags((int)Flag.MSAA_4X_HINT); // Set MSAA 4X hint before windows creation InitWindow(screenWidth, screenHeight, "raylib [core] example - gamepad input"); Texture2D texPs3Pad = LoadTexture("resources/ps3.png"); Texture2D texXboxPad = LoadTexture("resources/xbox.png"); SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // ... //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); if (IsGamepadAvailable(GAMEPAD_PLAYER1)) { DrawText(FormatText("GP1: %s", GetGamepadName(GAMEPAD_PLAYER1)), 10, 10, 10, BLACK); if (IsGamepadName(GAMEPAD_PLAYER1, XBOX360_NAME_ID)) { DrawTexture(texXboxPad, 0, 0, DARKGRAY); // Draw buttons: xbox home if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_HOME)) DrawCircle(394, 89, 19, RED); // Draw buttons: basic if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_START)) DrawCircle(436, 150, 9, RED); if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_SELECT)) DrawCircle(352, 150, 9, RED); if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_X)) DrawCircle(501, 151, 15, BLUE); if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_A)) DrawCircle(536, 187, 15, LIME); if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_B)) DrawCircle(572, 151, 15, MAROON); if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_Y)) DrawCircle(536, 115, 15, GOLD); // Draw buttons: d-pad DrawRectangle(317, 202, 19, 71, BLACK); DrawRectangle(293, 228, 69, 19, BLACK); if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_UP)) DrawRectangle(317, 202, 19, 26, RED); if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_DOWN)) DrawRectangle(317, 202 + 45, 19, 26, RED); if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_LEFT)) DrawRectangle(292, 228, 25, 19, RED); if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_RIGHT)) DrawRectangle(292 + 44, 228, 26, 19, RED); // Draw buttons: left-right back if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_LB)) DrawCircle(259, 61, 20, RED); if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_RB)) DrawCircle(536, 61, 20, RED); // Draw axis: left joystick DrawCircle(259, 152, 39, BLACK); DrawCircle(259, 152, 34, LIGHTGRAY); DrawCircle(259 + (GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_XBOX_AXIS_LEFT_X)*20), 152 - (GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_XBOX_AXIS_LEFT_Y)*20), 25, BLACK); // Draw axis: right joystick DrawCircle(461, 237, 38, BLACK); DrawCircle(461, 237, 33, LIGHTGRAY); DrawCircle(461 + (GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_XBOX_AXIS_RIGHT_X)*20), 237 - (GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_XBOX_AXIS_RIGHT_Y)*20), 25, BLACK); // Draw axis: left-right triggers DrawRectangle(170, 30, 15, 70, GRAY); DrawRectangle(604, 30, 15, 70, GRAY); DrawRectangle(170, 30, 15, (((1.0f + GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_XBOX_AXIS_LT))/2.0f)*70), RED); DrawRectangle(604, 30, 15, (((1.0f + GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_XBOX_AXIS_RT))/2.0f)*70), RED); //DrawText(FormatText("Xbox axis LT: %02.02f", GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_XBOX_AXIS_LT)), 10, 40, 10, BLACK); //DrawText(FormatText("Xbox axis RT: %02.02f", GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_XBOX_AXIS_RT)), 10, 60, 10, BLACK); } else if (IsGamepadName(GAMEPAD_PLAYER1, PS3_NAME_ID)) { DrawTexture(texPs3Pad, 0, 0, DARKGRAY); // Draw buttons: ps if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_PS)) DrawCircle(396, 222, 13, RED); // Draw buttons: basic if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_SELECT)) DrawRectangle(328, 170, 32, 13, RED); if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_START)) DrawTriangle(new Vector2( 436, 168 }, (Vector2){ 436, 185 }, (Vector2){ 464, 177 );, RED); if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_TRIANGLE)) DrawCircle(557, 144, 13, LIME); if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_CIRCLE)) DrawCircle(586, 173, 13, RED); if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_CROSS)) DrawCircle(557, 203, 13, VIOLET); if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_SQUARE)) DrawCircle(527, 173, 13, PINK); // Draw buttons: d-pad DrawRectangle(225, 132, 24, 84, BLACK); DrawRectangle(195, 161, 84, 25, BLACK); if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_UP)) DrawRectangle(225, 132, 24, 29, RED); if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_DOWN)) DrawRectangle(225, 132 + 54, 24, 30, RED); if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_LEFT)) DrawRectangle(195, 161, 30, 25, RED); if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_RIGHT)) DrawRectangle(195 + 54, 161, 30, 25, RED); // Draw buttons: left-right back buttons if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_L1)) DrawCircle(239, 82, 20, RED); if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_R1)) DrawCircle(557, 82, 20, RED); // Draw axis: left joystick DrawCircle(319, 255, 35, BLACK); DrawCircle(319, 255, 31, LIGHTGRAY); DrawCircle(319 + (GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_PS3_AXIS_LEFT_X)*20), 255 + (GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_PS3_AXIS_LEFT_Y)*20), 25, BLACK); // Draw axis: right joystick DrawCircle(475, 255, 35, BLACK); DrawCircle(475, 255, 31, LIGHTGRAY); DrawCircle(475 + (GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_PS3_AXIS_RIGHT_X)*20), 255 + (GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_PS3_AXIS_RIGHT_Y)*20), 25, BLACK); // Draw axis: left-right triggers DrawRectangle(169, 48, 15, 70, GRAY); DrawRectangle(611, 48, 15, 70, GRAY); DrawRectangle(169, 48, 15, (((1.0f - GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_PS3_AXIS_L2))/2.0f)*70), RED); DrawRectangle(611, 48, 15, (((1.0f - GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_PS3_AXIS_R2))/2.0f)*70), RED); } else { DrawText("- GENERIC GAMEPAD -", 280, 180, 20, GRAY); // TODO: Draw generic gamepad } DrawText(FormatText("DETECTED AXIS [%i]:", GetGamepadAxisCount(GAMEPAD_PLAYER1)), 10, 50, 10, MAROON); for (int i = 0; i < GetGamepadAxisCount(GAMEPAD_PLAYER1); i++) { DrawText(FormatText("AXIS %i: %.02f", i, GetGamepadAxisMovement(GAMEPAD_PLAYER1, i)), 20, 70 + 20*i, 10, DARKGRAY); } if (GetGamepadButtonPressed() != -1) DrawText(FormatText("DETECTED BUTTON: %i", GetGamepadButtonPressed()), 10, 430, 10, RED); else DrawText("DETECTED BUTTON: NONE", 10, 430, 10, GRAY); } else { DrawText("GP1: NOT DETECTED", 10, 10, 10, GRAY); DrawTexture(texXboxPad, 0, 0, LIGHTGRAY); } EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(texPs3Pad); UnloadTexture(texXboxPad); CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } +public partial class core_input_gamepad +{ + /******************************************************************************************* * * 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) * ********************************************************************************************/ + + + // NOTE: Gamepad name ID depends on drivers and OS + //public const string XBOX360_NAME_ID = "Microsoft; //public const string PS3_NAME_ID = "PLAYSTATION(R)3; public const string XBOX360_NAME_ID = "Xbox"; public const string PS3_NAME_ID = "PLAYSTATION(R)3"; + public static int Main() { + // Initialization + //-------------------------------------------------------------------------------------- + int screenWidth = 800; int screenHeight = 450; + + SetConfigFlags(FLAG_MSAA_4X_HINT); // Set MSAA 4X hint before windows creation + + InitWindow(screenWidth, screenHeight, "raylib [core] example - gamepad input"); + + Texture2D texPs3Pad = LoadTexture("resources/ps3.png"); Texture2D texXboxPad = LoadTexture("resources/xbox.png"); + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + // ... + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + if (IsGamepadAvailable(GAMEPAD_PLAYER1)) + { + DrawText(FormatText("GP1: %s", GetGamepadName(GAMEPAD_PLAYER1)), 10, 10, 10, BLACK); + + if (IsGamepadName(GAMEPAD_PLAYER1, XBOX360_NAME_ID)) + { + DrawTexture(texXboxPad, 0, 0, DARKGRAY); + + // Draw buttons: xbox home + if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_HOME)) DrawCircle(394, 89, 19, RED); + + // Draw buttons: basic + if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_START)) DrawCircle(436, 150, 9, RED); + if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_SELECT)) DrawCircle(352, 150, 9, RED); + if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_X)) DrawCircle(501, 151, 15, BLUE); + if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_A)) DrawCircle(536, 187, 15, LIME); + if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_B)) DrawCircle(572, 151, 15, MAROON); + if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_Y)) DrawCircle(536, 115, 15, GOLD); + + // Draw buttons: d-pad + DrawRectangle(317, 202, 19, 71, BLACK); + DrawRectangle(293, 228, 69, 19, BLACK); + if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_UP)) DrawRectangle(317, 202, 19, 26, RED); + if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_DOWN)) DrawRectangle(317, 202 + 45, 19, 26, RED); + if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_LEFT)) DrawRectangle(292, 228, 25, 19, RED); + if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_RIGHT)) DrawRectangle(292 + 44, 228, 26, 19, RED); + + // Draw buttons: left-right back + if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_LB)) DrawCircle(259, 61, 20, RED); + if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_XBOX_BUTTON_RB)) DrawCircle(536, 61, 20, RED); + + // Draw axis: left joystick + DrawCircle(259, 152, 39, BLACK); + DrawCircle(259, 152, 34, LIGHTGRAY); + DrawCircle(259 + (int)(GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_XBOX_AXIS_LEFT_X) * 20), + 152 - (int)(GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_XBOX_AXIS_LEFT_Y) * 20), 25, BLACK); + + // Draw axis: right joystick + DrawCircle(461, 237, 38, BLACK); + DrawCircle(461, 237, 33, LIGHTGRAY); + DrawCircle(461 + (int)(GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_XBOX_AXIS_RIGHT_X) * 20), + 237 - (int)(GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_XBOX_AXIS_RIGHT_Y) * 20), 25, BLACK); + + // Draw axis: left-right triggers + DrawRectangle(170, 30, 15, 70, GRAY); + DrawRectangle(604, 30, 15, 70, GRAY); + DrawRectangle(170, 30, 15, (int)(((1.0f + GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_XBOX_AXIS_LT)) / 2.0f) * 70), RED); + DrawRectangle(604, 30, 15, (int)(((1.0f + GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_XBOX_AXIS_RT)) / 2.0f) * 70), RED); + + //DrawText(FormatText("Xbox axis LT: %02.02f", GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_XBOX_AXIS_LT)), 10, 40, 10, BLACK); + //DrawText(FormatText("Xbox axis RT: %02.02f", GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_XBOX_AXIS_RT)), 10, 60, 10, BLACK); + } + else if (IsGamepadName(GAMEPAD_PLAYER1, PS3_NAME_ID)) + { + DrawTexture(texPs3Pad, 0, 0, DARKGRAY); + + // Draw buttons: ps + if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_PS)) DrawCircle(396, 222, 13, RED); + + // Draw buttons: basic + if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_SELECT)) DrawRectangle(328, 170, 32, 13, RED); + if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_START)) DrawTriangle(new Vector2(436, 168), new Vector2(436, 185), new Vector2( + 464, 177 ), RED); + if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_TRIANGLE)) DrawCircle(557, 144, 13, LIME); + if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_CIRCLE)) DrawCircle(586, 173, 13, RED); + if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_CROSS)) DrawCircle(557, 203, 13, VIOLET); + if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_SQUARE)) DrawCircle(527, 173, 13, PINK); + + // Draw buttons: d-pad + DrawRectangle(225, 132, 24, 84, BLACK); + DrawRectangle(195, 161, 84, 25, BLACK); + if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_UP)) DrawRectangle(225, 132, 24, 29, RED); + if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_DOWN)) DrawRectangle(225, 132 + 54, 24, 30, RED); + if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_LEFT)) DrawRectangle(195, 161, 30, 25, RED); + if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_RIGHT)) DrawRectangle(195 + 54, 161, 30, 25, RED); + + // Draw buttons: left-right back buttons + if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_L1)) DrawCircle(239, 82, 20, RED); + if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_PS3_BUTTON_R1)) DrawCircle(557, 82, 20, RED); + + // Draw axis: left joystick + DrawCircle(319, 255, 35, BLACK); + DrawCircle(319, 255, 31, LIGHTGRAY); + DrawCircle(319 + (int)(GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_PS3_AXIS_LEFT_X) * 20), + 255 + (int)(GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_PS3_AXIS_LEFT_Y) * 20), 25, BLACK); + + // Draw axis: right joystick + DrawCircle(475, 255, 35, BLACK); + DrawCircle(475, 255, 31, LIGHTGRAY); + DrawCircle(475 + (int)(GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_PS3_AXIS_RIGHT_X) * 20), + 255 + (int)(GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_PS3_AXIS_RIGHT_Y) * 20), 25, BLACK); + + // Draw axis: left-right triggers + DrawRectangle(169, 48, 15, 70, GRAY); + DrawRectangle(611, 48, 15, 70, GRAY); + DrawRectangle(169, 48, 15, (int)(((1.0f - GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_PS3_AXIS_L2)) / 2.0f) * 70), RED); + DrawRectangle(611, 48, 15, (int)(((1.0f - GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_PS3_AXIS_R2)) / 2.0f) * 70), RED); + } else { + DrawText("- GENERIC GAMEPAD -", 280, 180, 20, GRAY); + + // TODO: Draw generic gamepad + } + + DrawText(FormatText("DETECTED AXIS [%i]:", GetGamepadAxisCount(GAMEPAD_PLAYER1)), 10, 50, 10, MAROON); + + for (int i = 0; i < GetGamepadAxisCount(GAMEPAD_PLAYER1); i++) + { + DrawText(FormatText("AXIS %i: %.02f", i, GetGamepadAxisMovement(GAMEPAD_PLAYER1, i)), 20, 70 + 20 * i, 10, DARKGRAY); + } + + if (GetGamepadButtonPressed() != -1) DrawText(FormatText("DETECTED BUTTON: %i", GetGamepadButtonPressed()), 10, 430, 10, RED); + else DrawText("DETECTED BUTTON: NONE", 10, 430, 10, GRAY); + } + else + { + DrawText("GP1: NOT DETECTED", 10, 10, 10, GRAY); + + DrawTexture(texXboxPad, 0, 0, LIGHTGRAY); + } + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadTexture(texPs3Pad); UnloadTexture(texXboxPad); + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; } } diff --git a/Examples/core/core_input_keys.cs b/Examples/core/core_input_keys.cs index 77c9506..8352f36 100644 --- a/Examples/core/core_input_keys.cs +++ b/Examples/core/core_input_keys.cs @@ -1 +1,7 @@ -using Raylib; using static Raylib.Raylib; public partial class Examples { /******************************************************************************************* * * raylib [core] example - Keyboard input * * 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) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - keyboard input"); Vector2 ballPosition = new Vector2( (float)screenWidth/2, (float)screenHeight/2 ); SetTargetFPS(60); // Set target frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (IsKeyDown((int)Key.RIGHT)) ballPosition.x += 2.0f; if (IsKeyDown((int)Key.LEFT)) ballPosition.x -= 2.0f; if (IsKeyDown((int)Key.UP)) ballPosition.y -= 2.0f; if (IsKeyDown((int)Key.DOWN)) ballPosition.y += 2.0f; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText("move the ball with arrow keys", 10, 10, 20, DARKGRAY); DrawCircleV(ballPosition, 50, MAROON); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- } } \ No newline at end of file +using Raylib; +using static Raylib.Raylib; + +public partial class core_input_keys +{ + /******************************************************************************************* * * raylib [core] example - Keyboard input * * 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) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - keyboard input"); Vector2 ballPosition = new Vector2( (float)screenWidth/2, (float)screenHeight/2 ); SetTargetFPS(60); // Set target frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (IsKeyDown(KEY_RIGHT)) ballPosition.x += 2.0f; if (IsKeyDown(KEY_LEFT)) ballPosition.x -= 2.0f; if (IsKeyDown(KEY_UP)) ballPosition.y -= 2.0f; if (IsKeyDown(KEY_DOWN)) ballPosition.y += 2.0f; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText("move the ball with arrow keys", 10, 10, 20, DARKGRAY); DrawCircleV(ballPosition, 50, MAROON); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } +} diff --git a/Examples/core/core_input_mouse.cs b/Examples/core/core_input_mouse.cs index dedb8af..be8c047 100644 --- a/Examples/core/core_input_mouse.cs +++ b/Examples/core/core_input_mouse.cs @@ -1 +1,7 @@ -using Raylib; using static Raylib.Raylib; public partial class Examples { /******************************************************************************************* * * raylib [core] example - Mouse input * * 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) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - mouse input"); Vector2 ballPosition = new Vector2( -100.0f, -100.0f ); Color ballColor = DARKBLUE; SetTargetFPS(60); //--------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- ballPosition = GetMousePosition(); if (IsMouseButtonPressed((int)Mouse.LEFT_BUTTON)) ballColor = MAROON; else if (IsMouseButtonPressed((int)Mouse.MIDDLE_BUTTON)) ballColor = LIME; else if (IsMouseButtonPressed((int)Mouse.RIGHT_BUTTON)) ballColor = DARKBLUE; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawCircleV(ballPosition, 40, ballColor); DrawText("move ball with mouse and click mouse button to change color", 10, 10, 20, DARKGRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- } } \ No newline at end of file +using Raylib; +using static Raylib.Raylib; + +public partial class core_input_mouse +{ + /******************************************************************************************* * * raylib [core] example - Mouse input * * 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) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - mouse input"); Vector2 ballPosition = new Vector2( -100.0f, -100.0f ); Color ballColor = DARKBLUE; SetTargetFPS(60); //--------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- ballPosition = GetMousePosition(); if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) ballColor = MAROON; else if (IsMouseButtonPressed(MOUSE_MIDDLE_BUTTON)) ballColor = LIME; else if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)) ballColor = DARKBLUE; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawCircleV(ballPosition, 40, ballColor); DrawText("move ball with mouse and click mouse button to change color", 10, 10, 20, DARKGRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } +} diff --git a/Examples/core/core_mouse_wheel.cs b/Examples/core/core_mouse_wheel.cs index 162eaab..2a35557 100644 --- a/Examples/core/core_mouse_wheel.cs +++ b/Examples/core/core_mouse_wheel.cs @@ -1 +1,11 @@ -using Raylib; using static Raylib.Raylib; public partial class Examples { /******************************************************************************************* * * raylib [core] examples - 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) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - mouse wheel"); int boxPositionY = screenHeight/2 - 40; int scrollSpeed = 4; // Scrolling speed in pixels SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- boxPositionY -= (GetMouseWheelMove()*scrollSpeed); //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawRectangle(screenWidth/2 - 40, boxPositionY, 80, 80, MAROON); DrawText("Use mouse wheel to move the cube up and down!", 10, 10, 20, GRAY); DrawText(FormatText("Box position Y: %03i", boxPositionY), 10, 40, 20, LIGHTGRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- } } \ No newline at end of file +using Raylib; +using static Raylib.Raylib; + +public partial class core_mouse_wheel +{ + /******************************************************************************************* * * raylib [core] examples - 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) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - mouse wheel"); int boxPositionY = screenHeight/2 - 40; int scrollSpeed = 4; // Scrolling speed in pixels SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- boxPositionY -= (GetMouseWheelMove()*scrollSpeed); //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawRectangle(screenWidth/2 - 40, boxPositionY, 80, 80, MAROON); DrawText("Use mouse wheel to move the cube up and down!", 10, 10, 20, GRAY); + //DrawText(FormatText("Box position Y: %03i", boxPositionY), 10, 40, 20, LIGHTGRAY); + DrawText($"Box position Y: {boxPositionY}", 10, 40, 20, LIGHTGRAY); + + EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } +} diff --git a/Examples/core/core_random_values.cs b/Examples/core/core_random_values.cs index 57bd0d2..080a1e9 100644 --- a/Examples/core/core_random_values.cs +++ b/Examples/core/core_random_values.cs @@ -1,7 +1,8 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class core_random_values { - /******************************************************************************************* * * raylib [core] example - Generate random values * * This example has been created using raylib 1.1 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - generate random values"); int framesCounter = 0; // Variable used to count frames int randValue = GetRandomValue(-8, 5); // Get a random integer number between -8 and 5 (both included) SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- framesCounter++; // Every two seconds (120 frames) a new random value is generated if (((framesCounter/120)%2) == 1) { randValue = GetRandomValue(-8, 5); framesCounter = 0; } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText("Every 2 seconds a new random value is generated:", 130, 100, 20, MAROON); DrawText(FormatText("%i", randValue), 360, 180, 80, LIGHTGRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [core] example - Generate random values * * This example has been created using raylib 1.1 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - generate random values"); int framesCounter = 0; // Variable used to count frames int randValue = GetRandomValue(-8, 5); // Get a random integer number between -8 and 5 (both included) SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- framesCounter++; // Every two seconds (120 frames) a new random value is generated if (((framesCounter/120)%2) == 1) { randValue = GetRandomValue(-8, 5); framesCounter = 0; } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText("Every 2 seconds a new random value is generated:", 130, 100, 20, MAROON); //DrawText(FormatText("%i", randValue), 360, 180, 80, LIGHTGRAY); + DrawText($"{randValue}", 360, 180, 80, LIGHTGRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/core/core_storage_values.cs b/Examples/core/core_storage_values.cs index e4ebb80..589aa20 100644 --- a/Examples/core/core_storage_values.cs +++ b/Examples/core/core_storage_values.cs @@ -1,7 +1,17 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class core_storage_values { - /******************************************************************************************* * * raylib [core] example - Storage save/load values * * 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) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ // NOTE: Storage positions must start with 0, directly related to file memory layout typedef enum { STORAGE_SCORE = 0, STORAGE_HISCORE } StorageData; public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - storage save/load values"); int score = 0; int hiscore = 0; int framesCounter = 0; SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (IsKeyPressed((int)Key.R)) { score = GetRandomValue(1000, 2000); hiscore = GetRandomValue(2000, 4000); } if (IsKeyPressed((int)Key.ENTER)) { StorageSaveValue(STORAGE_SCORE, score); StorageSaveValue(STORAGE_HISCORE, hiscore); } else if (IsKeyPressed((int)Key.SPACE)) { // NOTE: If requested position could not be found, value 0 is returned score = StorageLoadValue(STORAGE_SCORE); hiscore = StorageLoadValue(STORAGE_HISCORE); } framesCounter++; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText(FormatText("SCORE: %i", score), 280, 130, 40, MAROON); DrawText(FormatText("HI-SCORE: %i", hiscore), 210, 200, 50, BLACK); DrawText(FormatText("frames: %i", framesCounter), 10, 10, 20, LIME); DrawText("Press R to generate random numbers", 220, 40, 20, LIGHTGRAY); DrawText("Press ENTER to SAVE values", 250, 310, 20, LIGHTGRAY); DrawText("Press SPACE to LOAD values", 252, 350, 20, LIGHTGRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [core] example - Storage save/load values * * 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) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ // NOTE: Storage positions must start with 0, directly related to file memory layout enum StorageData { STORAGE_SCORE = 0, STORAGE_HISCORE }; public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - storage save/load values"); int score = 0; int hiscore = 0; int framesCounter = 0; SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (IsKeyPressed(KEY_R)) { score = GetRandomValue(1000, 2000); hiscore = GetRandomValue(2000, 4000); } if (IsKeyPressed(KEY_ENTER)) { StorageSaveValue((int)StorageData.STORAGE_SCORE, score); StorageSaveValue((int)StorageData.STORAGE_HISCORE, hiscore); } else if (IsKeyPressed(KEY_SPACE)) { // NOTE: If requested position could not be found, value 0 is returned score = StorageLoadValue((int)StorageData.STORAGE_SCORE); hiscore = StorageLoadValue((int)StorageData.STORAGE_HISCORE); } framesCounter++; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); + + // DrawText(FormatText("SCORE: %i", score), 280, 130, 40, MAROON); + DrawText($"SCORE: {score}", 280, 130, 40, MAROON); + // DrawText(FormatText("HI-SCORE: %i", hiscore), 210, 200, 50, BLACK); + DrawText($"HI-SCORE: {hiscore}", 210, 200, 50, BLACK); + + // DrawText(FormatText("frames: %i", framesCounter), 10, 10, 20, LIME); + DrawText($"frames: {framesCounter}", 10, 10, 20, LIME); + + DrawText("Press R to generate random numbers", 220, 40, 20, LIGHTGRAY); DrawText("Press ENTER to SAVE values", 250, 310, 20, LIGHTGRAY); DrawText("Press SPACE to LOAD values", 252, 350, 20, LIGHTGRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/core/core_vr_simulator.cs b/Examples/core/core_vr_simulator.cs index 4d6947b..0c1398a 100644 --- a/Examples/core/core_vr_simulator.cs +++ b/Examples/core/core_vr_simulator.cs @@ -1,7 +1,10 @@ using Raylib; using static Raylib.Raylib; +using static Raylib.CameraType; +using static Raylib.CameraMode; +using static Raylib.VrDeviceType; -public partial class Examples +public partial class core_vr_simulator { - /******************************************************************************************* * * raylib [core] example - VR Simulator (Oculus Rift CV1 parameters) * * This example has been created using raylib 1.7 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2017 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 1080; int screenHeight = 600; // NOTE: screenWidth/screenHeight should match VR device aspect ratio InitWindow(screenWidth, screenHeight, "raylib [core] example - vr simulator"); // Init VR simulator (Oculus Rift CV1 parameters) InitVrSimulator(GetVrDeviceInfo(HMD_OCULUS_RIFT_CV1)); // Define the camera to look into our 3d world Camera camera; camera.position = new Vector3( 5.0f, 2.0f, 5.0f );; // Camera position camera.target = new Vector3( 0.0f, 2.0f, 0.0f );; // Camera looking at point camera.up = new Vector3( 0.0f, 1.0f, 0.0f );; // Camera up vector (rotation towards target) camera.fovy = 60.0f; // Camera field-of-view Y camera.type = CAMERA_PERSPECTIVE; // Camera type Vector3 cubePosition = { 0.0f, 0.0f, 0.0f }; SetCameraMode(camera, CAMERA_FIRST_PERSON); // Set first person camera mode SetTargetFPS(90); // Set our game to run at 90 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateCamera(&camera); // Update camera (simulator mode) if (IsKeyPressed((int)Key.SPACE)) ToggleVrMode(); // Toggle VR mode //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginVrDrawing(); BeginMode3D(camera); DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED); DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON); DrawGrid(40, 1.0f); EndMode3D(); EndVrDrawing(); DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseVrSimulator(); // Close VR simulator CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [core] example - VR Simulator (Oculus Rift CV1 parameters) * * This example has been created using raylib 1.7 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2017 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 1080; int screenHeight = 600; // NOTE: screenWidth/screenHeight should match VR device aspect ratio InitWindow(screenWidth, screenHeight, "raylib [core] example - vr simulator"); // Init VR simulator (Oculus Rift CV1 parameters) // fails? InitVrSimulator(GetVrDeviceInfo((int)HMD_OCULUS_RIFT_CV1)); // Define the camera to look into our 3d world Camera3D camera; camera.position = new Vector3( 5.0f, 2.0f, 5.0f ); // Camera3D position camera.target = new Vector3( 0.0f, 2.0f, 0.0f ); // Camera3D looking at point camera.up = new Vector3( 0.0f, 1.0f, 0.0f ); // Camera3D up vector (rotation towards target) camera.fovy = 60.0f; // Camera3D field-of-view Y camera.type = (int)CAMERA_PERSPECTIVE; // Camera3D type Vector3 cubePosition = new Vector3( 0.0f, 0.0f, 0.0f ); SetCameraMode(camera, (int)CAMERA_FIRST_PERSON); // Set first person camera mode SetTargetFPS(90); // Set our game to run at 90 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateCamera(ref camera); // Update camera (simulator mode) if (IsKeyPressed(KEY_SPACE)) ToggleVrMode(); // Toggle VR mode //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginVrDrawing(); BeginMode3D(camera); DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED); DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON); DrawGrid(40, 1.0f); EndMode3D(); EndVrDrawing(); DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseVrSimulator(); // Close VR simulator CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/core/core_world_screen.cs b/Examples/core/core_world_screen.cs index 9ad38a7..b4b583a 100644 --- a/Examples/core/core_world_screen.cs +++ b/Examples/core/core_world_screen.cs @@ -1,7 +1,9 @@ using Raylib; using static Raylib.Raylib; +using static Raylib.CameraType; +using static Raylib.CameraMode; -public partial class Examples +public partial class core_world_screen { - /******************************************************************************************* * * raylib [core] example - World to screen * * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera free"); // Define the camera to look into our 3d world Camera camera = { 0 }; camera.position = new Vector3( 10.0f, 10.0f, 10.0f );; camera.target = new Vector3( 0.0f, 0.0f, 0.0f );; camera.up = new Vector3( 0.0f, 1.0f, 0.0f );; camera.fovy = 45.0f; camera.type = CAMERA_PERSPECTIVE; Vector3 cubePosition = { 0.0f, 0.0f, 0.0f }; Vector2 cubeScreenPosition; SetCameraMode(camera, CAMERA_FREE); // Set a free camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateCamera(&camera); // Update camera // Calculate cube screen space position (with a little offset to be in top) cubeScreenPosition = GetWorldToScreen(new Vector3(cubePosition.x, cubePosition.y + 2.5f, cubePosition.z);, camera); //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED); DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON); DrawGrid(10, 1.0f); EndMode3D(); DrawText("Enemy: 100 / 100", cubeScreenPosition.x - MeasureText("Enemy: 100 / 100", 20) / 2, cubeScreenPosition.y, 20, BLACK); DrawText("Text is always on top of the cube", (screenWidth - MeasureText("Text is always on top of the cube", 20)) / 2, 25, 20, GRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [core] example - World to screen * * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera free"); // Define the camera to look into our 3d world Camera3D camera = new Camera3D(); camera.position = new Vector3( 10.0f, 10.0f, 10.0f ); camera.target = new Vector3( 0.0f, 0.0f, 0.0f ); camera.up = new Vector3( 0.0f, 1.0f, 0.0f ); camera.fovy = 45.0f; camera.type = (int)CAMERA_PERSPECTIVE; Vector3 cubePosition = new Vector3( 0.0f, 0.0f, 0.0f ); Vector2 cubeScreenPosition; SetCameraMode(camera, (int)CAMERA_FREE); // Set a free camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateCamera(ref camera); // Update camera // Calculate cube screen space position (with a little offset to be in top) cubeScreenPosition = GetWorldToScreen(new Vector3(cubePosition.x, cubePosition.y + 2.5f, cubePosition.z), camera); //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED); DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON); DrawGrid(10, 1.0f); EndMode3D(); DrawText("Enemy: 100 / 100", (int)cubeScreenPosition.x - MeasureText("Enemy: 100 / 100", 20) / 2, (int)cubeScreenPosition.y, 20, BLACK); DrawText("Text is always on top of the cube", (screenWidth - MeasureText("Text is always on top of the cube", 20)) / 2, 25, 20, GRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/iqm_loader/models_iqm_animation.cs b/Examples/iqm_loader/models_iqm_animation.cs deleted file mode 100644 index 2b46a3c..0000000 --- a/Examples/iqm_loader/models_iqm_animation.cs +++ /dev/null @@ -1,7 +0,0 @@ -using Raylib; -using static Raylib.Raylib; - -public partial class Examples -{ - /******************************************************************************************* * * raylib [models] example - Load IQM 3d model with animations and play them * * This example has been created using raylib 2.0 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2018 @culacant and @raysan5 * ********************************************************************************************/ public const #define RIQM_IMPLEMENTATION public static int models_iqm_animation() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - iqm animation"); // Define the camera to look into our 3d world Camera camera = { 0 }; camera.position = (Vector3){ 10.0f, 10.0f, 10.0f }; // Camera position camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) camera.fovy = 45.0f; // Camera field-of-view Y camera.type = CAMERA_PERSPECTIVE; // Camera mode type // Load the animated model mesh and basic data AnimatedModel model = LoadAnimatedModel("resources/guy.iqm"); // Load model texture and set material // NOTE: There is only 1 mesh and 1 material (both at index 0), thats what the 2 0's are model = AnimatedModelAddTexture(model, "resources/guytex.png"); // REPLACE! model = SetMeshMaterial(model, 0, 0); // REPLACE! // Load animation data Animation anim = LoadAnimationFromIQM("resources/guyanim.iqm"); int animFrameCounter = 0; SetCameraMode(camera, CAMERA_FREE); // Set free camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateCamera(&camera); // Play animation when spacebar is held down if (IsKeyDown(KEY_SPACE)) { animFrameCounter++; AnimateModel(model, anim, animFrameCounter); // Animate the model with animation data and frame } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); DrawAnimatedModel(model, Vector3Zero(), 1.0f, WHITE); // Draw animated model DrawGrid(10, 1.0f); // Draw a grid EndMode3D(); DrawText("PRESS SPACE to PLAY IQM MODEL ANIMATION", 10, 10, 20, MAROON); DrawText("(c) Guy IQM 3D model by @culacant", screenWidth - 200, screenHeight - 20, 10, GRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadAnimation(anim); // Unload animation data UnloadAnimatedModel(model); // Unload animated model CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } -} diff --git a/Examples/models/models_billboard.cs b/Examples/models/models_billboard.cs index b38c9f5..44cab88 100644 --- a/Examples/models/models_billboard.cs +++ b/Examples/models/models_billboard.cs @@ -1,7 +1,9 @@ using Raylib; using static Raylib.Raylib; +using static Raylib.CameraType; +using static Raylib.CameraMode; -public partial class Examples +public partial class models_billboard { - /******************************************************************************************* * * raylib [models] example - Drawing billboards * * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - drawing billboards"); // Define the camera to look into our 3d world Camera camera = { 0 }; camera.position = new Vector3( 5.0f, 4.0f, 5.0f );; camera.target = new Vector3( 0.0f, 2.0f, 0.0f );; camera.up = new Vector3( 0.0f, 1.0f, 0.0f );; camera.fovy = 45.0f; camera.type = CAMERA_PERSPECTIVE; Texture2D bill = LoadTexture("resources/billboard.png"); // Our texture billboard Vector3 billPosition = { 0.0f, 2.0f, 0.0f }; // Position where draw billboard SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateCamera(&camera); // Update camera //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); DrawBillboard(camera, bill, billPosition, 2.0f, WHITE); DrawGrid(10, 1.0f); // Draw a grid EndMode3D(); DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(bill); // Unload texture CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [models] example - Drawing billboards * * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - drawing billboards"); // Define the camera to look into our 3d world Camera3D camera = new Camera3D(); camera.position = new Vector3( 5.0f, 4.0f, 5.0f ); camera.target = new Vector3( 0.0f, 2.0f, 0.0f ); camera.up = new Vector3( 0.0f, 1.0f, 0.0f ); camera.fovy = 45.0f; camera.type = CAMERA_PERSPECTIVE; Texture2D bill = LoadTexture("resources/billboard.png"); // Our texture billboard Vector3 billPosition = new Vector3( 0.0f, 2.0f, 0.0f ); // Position where draw billboard SetCameraMode(camera, (int)CAMERA_ORBITAL); // Set an orbital camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateCamera(ref camera); // Update camera //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); DrawBillboard(camera, bill, billPosition, 2.0f, WHITE); DrawGrid(10, 1.0f); // Draw a grid EndMode3D(); DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(bill); // Unload texture CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/models/models_box_collisions.cs b/Examples/models/models_box_collisions.cs index 16f99be..8ae2674 100644 --- a/Examples/models/models_box_collisions.cs +++ b/Examples/models/models_box_collisions.cs @@ -1,7 +1,7 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class models_box_collisions { - /******************************************************************************************* * * raylib [models] example - Detect basic 3d collisions (box vs sphere vs box) * * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - box collisions"); // Define the camera to look into our 3d world Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 }; Vector3 playerPosition = { 0.0f, 1.0f, 2.0f }; Vector3 playerSize = { 1.0f, 2.0f, 1.0f }; Color playerColor = GREEN; Vector3 enemyBoxPos = { -4.0f, 1.0f, 0.0f }; Vector3 enemyBoxSize = { 2.0f, 2.0f, 2.0f }; Vector3 enemySpherePos = { 4.0f, 0.0f, 0.0f }; float enemySphereSize = 1.5f; bool collision = false; SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // Move player if (IsKeyDown((int)Key.RIGHT)) playerPosition.x += 0.2f; else if (IsKeyDown((int)Key.LEFT)) playerPosition.x -= 0.2f; else if (IsKeyDown((int)Key.DOWN)) playerPosition.z += 0.2f; else if (IsKeyDown((int)Key.UP)) playerPosition.z -= 0.2f; collision = false; // Check collisions player vs enemy-box if (CheckCollisionBoxes( (BoundingBox){(Vector3){ playerPosition.x - playerSize.x/2, playerPosition.y - playerSize.y/2, playerPosition.z - playerSize.z/2 }, (Vector3){ playerPosition.x + playerSize.x/2, playerPosition.y + playerSize.y/2, playerPosition.z + playerSize.z/2 }}, (BoundingBox){(Vector3){ enemyBoxPos.x - enemyBoxSize.x/2, enemyBoxPos.y - enemyBoxSize.y/2, enemyBoxPos.z - enemyBoxSize.z/2 }, (Vector3){ enemyBoxPos.x + enemyBoxSize.x/2, enemyBoxPos.y + enemyBoxSize.y/2, enemyBoxPos.z + enemyBoxSize.z/2 }})) collision = true; // Check collisions player vs enemy-sphere if (CheckCollisionBoxSphere( (BoundingBox){(Vector3){ playerPosition.x - playerSize.x/2, playerPosition.y - playerSize.y/2, playerPosition.z - playerSize.z/2 }, (Vector3){ playerPosition.x + playerSize.x/2, playerPosition.y + playerSize.y/2, playerPosition.z + playerSize.z/2 }}, enemySpherePos, enemySphereSize)) collision = true; if (collision) playerColor = RED; else playerColor = GREEN; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); // Draw enemy-box DrawCube(enemyBoxPos, enemyBoxSize.x, enemyBoxSize.y, enemyBoxSize.z, GRAY); DrawCubeWires(enemyBoxPos, enemyBoxSize.x, enemyBoxSize.y, enemyBoxSize.z, DARKGRAY); // Draw enemy-sphere DrawSphere(enemySpherePos, enemySphereSize, GRAY); DrawSphereWires(enemySpherePos, enemySphereSize, 16, 16, DARKGRAY); // Draw player DrawCubeV(playerPosition, playerSize, playerColor); DrawGrid(10, 1.0f); // Draw a grid EndMode3D(); DrawText("Move player with cursors to collide", 220, 40, 20, GRAY); DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [models] example - Detect basic 3d collisions (box vs sphere vs box) * * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - box collisions"); // Define the camera to look into our 3d world Camera3D camera = new Camera3D(new Vector3( 0.0f, 10.0f, 10.0f ), new Vector3( 0.0f, 0.0f, 0.0f ), new Vector3( 0.0f, 1.0f, 0.0f ), 45.0f, 0 ); Vector3 playerPosition = new Vector3( 0.0f, 1.0f, 2.0f ); Vector3 playerSize = new Vector3( 1.0f, 2.0f, 1.0f ); Color playerColor = GREEN; Vector3 enemyBoxPos = new Vector3( -4.0f, 1.0f, 0.0f ); Vector3 enemyBoxSize = new Vector3( 2.0f, 2.0f, 2.0f ); Vector3 enemySpherePos = new Vector3( 4.0f, 0.0f, 0.0f ); float enemySphereSize = 1.5f; bool collision = false; SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // Move player if (IsKeyDown(KEY_RIGHT)) playerPosition.x += 0.2f; else if (IsKeyDown(KEY_LEFT)) playerPosition.x -= 0.2f; else if (IsKeyDown(KEY_DOWN)) playerPosition.z += 0.2f; else if (IsKeyDown(KEY_UP)) playerPosition.z -= 0.2f; collision = false; // Check collisions player vs enemy-box if (CheckCollisionBoxes( new BoundingBox(new Vector3( playerPosition.x - playerSize.x/2, playerPosition.y - playerSize.y/2, playerPosition.z - playerSize.z/2 ), new Vector3( playerPosition.x + playerSize.x/2, playerPosition.y + playerSize.y/2, playerPosition.z + playerSize.z/2 )), new BoundingBox(new Vector3( enemyBoxPos.x - enemyBoxSize.x/2, enemyBoxPos.y - enemyBoxSize.y/2, enemyBoxPos.z - enemyBoxSize.z/2 ), new Vector3( enemyBoxPos.x + enemyBoxSize.x/2, enemyBoxPos.y + enemyBoxSize.y/2, enemyBoxPos.z + enemyBoxSize.z/2 )))) collision = true; // Check collisions player vs enemy-sphere if (CheckCollisionBoxSphere( new BoundingBox(new Vector3( playerPosition.x - playerSize.x/2, playerPosition.y - playerSize.y/2, playerPosition.z - playerSize.z/2 ), new Vector3( playerPosition.x + playerSize.x/2, playerPosition.y + playerSize.y/2, playerPosition.z + playerSize.z/2 )), enemySpherePos, enemySphereSize)) collision = true; if (collision) playerColor = RED; else playerColor = GREEN; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); // Draw enemy-box DrawCube(enemyBoxPos, enemyBoxSize.x, enemyBoxSize.y, enemyBoxSize.z, GRAY); DrawCubeWires(enemyBoxPos, enemyBoxSize.x, enemyBoxSize.y, enemyBoxSize.z, DARKGRAY); // Draw enemy-sphere DrawSphere(enemySpherePos, enemySphereSize, GRAY); DrawSphereWires(enemySpherePos, enemySphereSize, 16, 16, DARKGRAY); // Draw player DrawCubeV(playerPosition, playerSize, playerColor); DrawGrid(10, 1.0f); // Draw a grid EndMode3D(); DrawText("Move player with cursors to collide", 220, 40, 20, GRAY); DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/models/models_cubicmap.cs b/Examples/models/models_cubicmap.cs index 29b5b5a..6c4110d 100644 --- a/Examples/models/models_cubicmap.cs +++ b/Examples/models/models_cubicmap.cs @@ -1,7 +1,9 @@ using Raylib; using static Raylib.Raylib; +using static Raylib.CameraMode; +using static Raylib.TexmapIndex; -public partial class Examples +public partial class models_cubicmap { - /******************************************************************************************* * * raylib [models] example - Cubicmap loading and drawing * * This example has been created using raylib 1.8 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - cubesmap loading and drawing"); // Define the camera to look into our 3d world Camera camera = {{ 16.0f, 14.0f, 16.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 }; Image image = LoadImage("resources/cubicmap.png"); // Load cubicmap image (RAM) Texture2D cubicmap = LoadTextureFromImage(image); // Convert image to texture to display (VRAM) Mesh mesh = GenMeshCubicmap(image, new Vector3( 1.0f, 1.0f, 1.0f );); Model model = LoadModelFromMesh(mesh); // NOTE: By default each cube is mapped to one part of texture atlas Texture2D texture = LoadTexture("resources/cubicmap_atlas.png"); // Load map texture model.material.maps[MAP_DIFFUSE].texture = texture; // Set map diffuse texture Vector3 mapPosition = { -16.0f, 0.0f, -8.0f }; // Set model position UnloadImage(image); // Unload cubesmap image from RAM, already uploaded to VRAM SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateCamera(&camera); // Update camera //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); DrawModel(model, mapPosition, 1.0f, WHITE); EndMode3D(); DrawTextureEx(cubicmap, new Vector2( screenWidth - cubicmap.width*4 - 20, 20 );, 0.0f, 4.0f, WHITE); DrawRectangleLines(screenWidth - cubicmap.width*4 - 20, 20, cubicmap.width*4, cubicmap.height*4, GREEN); DrawText("cubicmap image used to", 658, 90, 10, GRAY); DrawText("generate map 3d model", 658, 104, 10, GRAY); DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(cubicmap); // Unload cubicmap texture UnloadTexture(texture); // Unload map texture UnloadModel(model); // Unload map model CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [models] example - Cubicmap loading and drawing * * This example has been created using raylib 1.8 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - cubesmap loading and drawing"); // Define the camera to look into our 3d world Camera3D camera = new Camera3D(new Vector3( 16.0f, 14.0f, 16.0f ), new Vector3( 0.0f, 0.0f, 0.0f ), new Vector3( 0.0f, 1.0f, 0.0f ), 45.0f, 0 ); Image image = LoadImage("resources/cubicmap.png"); // Load cubicmap image (RAM) Texture2D cubicmap = LoadTextureFromImage(image); // Convert image to texture to display (VRAM) Mesh mesh = GenMeshCubicmap(image, new Vector3( 1.0f, 1.0f, 1.0f )); Model model = LoadModelFromMesh(mesh); // NOTE: By default each cube is mapped to one part of texture atlas Texture2D texture = LoadTexture("resources/cubicmap_atlas.png"); // Load map texture model.material.maps[(int)MAP_ALBEDO].texture = texture; // Set map diffuse texture Vector3 mapPosition = new Vector3( -16.0f, 0.0f, -8.0f ); // Set model position UnloadImage(image); // Unload cubesmap image from RAM, already uploaded to VRAM SetCameraMode(camera, (int)CAMERA_ORBITAL); // Set an orbital camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateCamera(ref camera); // Update camera //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); DrawModel(model, mapPosition, 1.0f, WHITE); EndMode3D(); DrawTextureEx(cubicmap, new Vector2( screenWidth - cubicmap.width*4 - 20, 20 ), 0.0f, 4.0f, WHITE); DrawRectangleLines(screenWidth - cubicmap.width*4 - 20, 20, cubicmap.width*4, cubicmap.height*4, GREEN); DrawText("cubicmap image used to", 658, 90, 10, GRAY); DrawText("generate map 3d model", 658, 104, 10, GRAY); DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(cubicmap); // Unload cubicmap texture UnloadTexture(texture); // Unload map texture UnloadModel(model); // Unload map model CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/models/models_geometric_shapes.cs b/Examples/models/models_geometric_shapes.cs index b25fa4c..6c57bf3 100644 --- a/Examples/models/models_geometric_shapes.cs +++ b/Examples/models/models_geometric_shapes.cs @@ -1,7 +1,8 @@ using Raylib; using static Raylib.Raylib; +using static Raylib.CameraType; -public partial class Examples +public partial class models_geometric_shapes { - /******************************************************************************************* * * raylib [models] example - Draw some basic geometric shapes (cube, sphere, cylinder...) * * 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) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - geometric shapes"); // Define the camera to look into our 3d world Camera camera = { 0 }; camera.position = new Vector3( 0.0f, 10.0f, 10.0f );; camera.target = new Vector3( 0.0f, 0.0f, 0.0f );; camera.up = new Vector3( 0.0f, 1.0f, 0.0f );; camera.fovy = 45.0f; camera.type = CAMERA_PERSPECTIVE; SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update your variables here //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); DrawCube(new Vector3(-4.0f, 0.0f, 2.0f);, 2.0f, 5.0f, 2.0f, RED); DrawCubeWires(new Vector3(-4.0f, 0.0f, 2.0f);, 2.0f, 5.0f, 2.0f, GOLD); DrawCubeWires(new Vector3(-4.0f, 0.0f, -2.0f);, 3.0f, 6.0f, 2.0f, MAROON); DrawSphere(new Vector3(-1.0f, 0.0f, -2.0f);, 1.0f, GREEN); DrawSphereWires(new Vector3(1.0f, 0.0f, 2.0f);, 2.0f, 16, 16, LIME); DrawCylinder(new Vector3(4.0f, 0.0f, -2.0f);, 1.0f, 2.0f, 3.0f, 4, SKYBLUE); DrawCylinderWires(new Vector3(4.0f, 0.0f, -2.0f);, 1.0f, 2.0f, 3.0f, 4, DARKBLUE); DrawCylinderWires(new Vector3(4.5f, -1.0f, 2.0f);, 1.0f, 1.0f, 2.0f, 6, BROWN); DrawCylinder(new Vector3(1.0f, 0.0f, -4.0f);, 0.0f, 1.5f, 3.0f, 8, GOLD); DrawCylinderWires(new Vector3(1.0f, 0.0f, -4.0f);, 0.0f, 1.5f, 3.0f, 8, PINK); DrawGrid(10, 1.0f); // Draw a grid EndMode3D(); DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [models] example - Draw some basic geometric shapes (cube, sphere, cylinder...) * * 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) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - geometric shapes"); // Define the camera to look into our 3d world Camera3D camera = new Camera3D(); camera.position = new Vector3( 0.0f, 10.0f, 10.0f ); camera.target = new Vector3( 0.0f, 0.0f, 0.0f ); camera.up = new Vector3( 0.0f, 1.0f, 0.0f ); camera.fovy = 45.0f; camera.type = CAMERA_PERSPECTIVE; SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update your variables here //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); DrawCube(new Vector3(-4.0f, 0.0f, 2.0f), 2.0f, 5.0f, 2.0f, RED); DrawCubeWires(new Vector3(-4.0f, 0.0f, 2.0f), 2.0f, 5.0f, 2.0f, GOLD); DrawCubeWires(new Vector3(-4.0f, 0.0f, -2.0f), 3.0f, 6.0f, 2.0f, MAROON); DrawSphere(new Vector3(-1.0f, 0.0f, -2.0f), 1.0f, GREEN); DrawSphereWires(new Vector3(1.0f, 0.0f, 2.0f), 2.0f, 16, 16, LIME); DrawCylinder(new Vector3(4.0f, 0.0f, -2.0f), 1.0f, 2.0f, 3.0f, 4, SKYBLUE); DrawCylinderWires(new Vector3(4.0f, 0.0f, -2.0f), 1.0f, 2.0f, 3.0f, 4, DARKBLUE); DrawCylinderWires(new Vector3(4.5f, -1.0f, 2.0f), 1.0f, 1.0f, 2.0f, 6, BROWN); DrawCylinder(new Vector3(1.0f, 0.0f, -4.0f), 0.0f, 1.5f, 3.0f, 8, GOLD); DrawCylinderWires(new Vector3(1.0f, 0.0f, -4.0f), 0.0f, 1.5f, 3.0f, 8, PINK); DrawGrid(10, 1.0f); // Draw a grid EndMode3D(); DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/models/models_heightmap.cs b/Examples/models/models_heightmap.cs index 7bae543..c208dfd 100644 --- a/Examples/models/models_heightmap.cs +++ b/Examples/models/models_heightmap.cs @@ -1,7 +1,9 @@ using Raylib; using static Raylib.Raylib; +using static Raylib.CameraMode; +using static Raylib.TexmapIndex; -public partial class Examples +public partial class models_heightmap { - /******************************************************************************************* * * raylib [models] example - Heightmap loading and drawing * * This example has been created using raylib 1.8 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - heightmap loading and drawing"); // Define our custom camera to look into our 3d world Camera camera = {{ 18.0f, 16.0f, 18.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 }; Image image = LoadImage("resources/heightmap.png"); // Load heightmap image (RAM) Texture2D texture = LoadTextureFromImage(image); // Convert image to texture (VRAM) Mesh mesh = GenMeshHeightmap(image, new Vector3( 16, 8, 16 );); // Generate heightmap mesh (RAM and VRAM) Model model = LoadModelFromMesh(mesh); // Load model from generated mesh model.material.maps[MAP_DIFFUSE].texture = texture; // Set map diffuse texture Vector3 mapPosition = { -8.0f, 0.0f, -8.0f }; // Define model position UnloadImage(image); // Unload heightmap image from RAM, already uploaded to VRAM SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateCamera(&camera); // Update camera //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); DrawModel(model, mapPosition, 1.0f, RED); DrawGrid(20, 1.0f); EndMode3D(); DrawTexture(texture, screenWidth - texture.width - 20, 20, WHITE); DrawRectangleLines(screenWidth - texture.width - 20, 20, texture.width, texture.height, GREEN); DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(texture); // Unload texture UnloadModel(model); // Unload model CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [models] example - Heightmap loading and drawing * * This example has been created using raylib 1.8 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - heightmap loading and drawing"); // Define our custom camera to look into our 3d world Camera3D camera = new Camera3D(new Vector3( 18.0f, 16.0f, 18.0f ), new Vector3( 0.0f, 0.0f, 0.0f ), new Vector3( 0.0f, 1.0f, 0.0f ), 45.0f, 0 ); Image image = LoadImage("resources/heightmap.png"); // Load heightmap image (RAM) Texture2D texture = LoadTextureFromImage(image); // Convert image to texture (VRAM) Mesh mesh = GenMeshHeightmap(image, new Vector3( 16, 8, 16 )); // Generate heightmap mesh (RAM and VRAM) Model model = LoadModelFromMesh(mesh); // Load model from generated mesh model.material.maps[(int)MAP_ALBEDO].texture = texture; // Set map diffuse texture Vector3 mapPosition = new Vector3( -8.0f, 0.0f, -8.0f ); // Define model position UnloadImage(image); // Unload heightmap image from RAM, already uploaded to VRAM SetCameraMode(camera, (int)CAMERA_ORBITAL); // Set an orbital camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateCamera(ref camera); // Update camera //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); DrawModel(model, mapPosition, 1.0f, RED); DrawGrid(20, 1.0f); EndMode3D(); DrawTexture(texture, screenWidth - texture.width - 20, 20, WHITE); DrawRectangleLines(screenWidth - texture.width - 20, 20, texture.width, texture.height, GREEN); DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(texture); // Unload texture UnloadModel(model); // Unload model CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/models/models_material_pbr.cs b/Examples/models/models_material_pbr.cs index 0689316..db6bf2e 100644 --- a/Examples/models/models_material_pbr.cs +++ b/Examples/models/models_material_pbr.cs @@ -1,7 +1,7 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class models_material_pbr { - /******************************************************************************************* * * raylib [models] example - PBR material * * This example has been created using raylib 1.8 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2017 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public const #define RLIGHTS_IMPLEMENTATION public const #define CUBEMAP_SIZE 512 // Cubemap texture size public const #define IRRADIANCE_SIZE 32 // Irradiance texture size public const #define PREFILTERED_SIZE 256 // Prefiltered HDR environment texture size public const #define BRDF_SIZE 512 // BRDF LUT texture size // PBR material loading static Material LoadMaterialPBR(Color albedo, float metalness, float roughness); public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; SetConfigFlags((int)Flag.MSAA_4X_HINT); // Enable Multi Sampling Anti Aliasing 4x (if available) InitWindow(screenWidth, screenHeight, "raylib [models] example - pbr material"); // Define the camera to look into our 3d world Camera camera = {{ 4.0f, 4.0f, 4.0f }, { 0.0f, 0.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 }; // Load model and PBR material Model model = LoadModel("resources/pbr/trooper.obj"); MeshTangents(&model.mesh); model.material = LoadMaterialPBR(new Color( 255, 255, 255, 255 );, 1.0f, 1.0f); // Define lights attributes // NOTE: Shader is passed to every light on creation to define shader bindings internally Light lights[MAX_LIGHTS] = { CreateLight(LIGHT_POINT, new Vector3( LIGHT_DISTANCE, LIGHT_HEIGHT, 0.0f }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 255, 0, 0, 255 );, model.material.shader), CreateLight(LIGHT_POINT, new Vector3( 0.0f, LIGHT_HEIGHT, LIGHT_DISTANCE }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 0, 255, 0, 255 );, model.material.shader), CreateLight(LIGHT_POINT, new Vector3( -LIGHT_DISTANCE, LIGHT_HEIGHT, 0.0f }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 0, 0, 255, 255 );, model.material.shader), CreateLight(LIGHT_DIRECTIONAL, new Vector3( 0.0f, LIGHT_HEIGHT*2.0f, -LIGHT_DISTANCE }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 255, 0, 255, 255 );, model.material.shader) }; SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateCamera(&camera); // Update camera // Send to material PBR shader camera view position float cameraPos[3] = { camera.position.x, camera.position.y, camera.position.z }; SetShaderValue(model.material.shader, model.material.shader.locs[LOC_VECTOR_VIEW], cameraPos, 3); //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); DrawModel(model, Vector3Zero(), 1.0f, WHITE); DrawGrid(10, 1.0f); EndMode3D(); DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadModel(model); // Unload skybox model CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } // Load PBR material (Supports: ALBEDO, NORMAL, METALNESS, ROUGHNESS, AO, EMMISIVE, HEIGHT maps) // NOTE: PBR shader is loaded inside this function static Material LoadMaterialPBR(Color albedo, float metalness, float roughness) { Material mat = { 0 }; // NOTE: All maps textures are set to { 0 } #define PATH_PBR_VS "resources/shaders/pbr.vs" // Path to physically based rendering vertex shader #define PATH_PBR_FS "resources/shaders/pbr.fs" // Path to physically based rendering fragment shader mat.shader = LoadShader(PATH_PBR_VS, PATH_PBR_FS); // Get required locations points for PBR material // NOTE: Those location names must be available and used in the shader code mat.shader.locs[LOC_MAP_ALBEDO] = GetShaderLocation(mat.shader, "albedo.sampler"); mat.shader.locs[LOC_MAP_METALNESS] = GetShaderLocation(mat.shader, "metalness.sampler"); mat.shader.locs[LOC_MAP_NORMAL] = GetShaderLocation(mat.shader, "normals.sampler"); mat.shader.locs[LOC_MAP_ROUGHNESS] = GetShaderLocation(mat.shader, "roughness.sampler"); mat.shader.locs[LOC_MAP_OCCLUSION] = GetShaderLocation(mat.shader, "occlusion.sampler"); //mat.shader.locs[LOC_MAP_EMISSION] = GetShaderLocation(mat.shader, "emission.sampler"); //mat.shader.locs[LOC_MAP_HEIGHT] = GetShaderLocation(mat.shader, "height.sampler"); mat.shader.locs[LOC_MAP_IRRADIANCE] = GetShaderLocation(mat.shader, "irradianceMap"); mat.shader.locs[LOC_MAP_PREFILTER] = GetShaderLocation(mat.shader, "prefilterMap"); mat.shader.locs[LOC_MAP_BRDF] = GetShaderLocation(mat.shader, "brdfLUT"); // Set view matrix location mat.shader.locs[LOC_MATRIX_MODEL] = GetShaderLocation(mat.shader, "matModel"); mat.shader.locs[LOC_MATRIX_VIEW] = GetShaderLocation(mat.shader, "view"); mat.shader.locs[LOC_VECTOR_VIEW] = GetShaderLocation(mat.shader, "viewPos"); // Set PBR standard maps mat.maps[MAP_ALBEDO].texture = LoadTexture("resources/pbr/trooper_albedo.png"); mat.maps[MAP_NORMAL].texture = LoadTexture("resources/pbr/trooper_normals.png"); mat.maps[MAP_METALNESS].texture = LoadTexture("resources/pbr/trooper_metalness.png"); mat.maps[MAP_ROUGHNESS].texture = LoadTexture("resources/pbr/trooper_roughness.png"); mat.maps[MAP_OCCLUSION].texture = LoadTexture("resources/pbr/trooper_ao.png"); // Set environment maps #define PATH_CUBEMAP_VS "resources/shaders/cubemap.vs" // Path to equirectangular to cubemap vertex shader #define PATH_CUBEMAP_FS "resources/shaders/cubemap.fs" // Path to equirectangular to cubemap fragment shader #define PATH_SKYBOX_VS "resources/shaders/skybox.vs" // Path to skybox vertex shader #define PATH_IRRADIANCE_FS "resources/shaders/irradiance.fs" // Path to irradiance (GI) calculation fragment shader #define PATH_PREFILTER_FS "resources/shaders/prefilter.fs" // Path to reflection prefilter calculation fragment shader #define PATH_BRDF_VS "resources/shaders/brdf.vs" // Path to bidirectional reflectance distribution function vertex shader #define PATH_BRDF_FS "resources/shaders/brdf.fs" // Path to bidirectional reflectance distribution function fragment shader Shader shdrCubemap = LoadShader(PATH_CUBEMAP_VS, PATH_CUBEMAP_FS); Shader shdrIrradiance = LoadShader(PATH_SKYBOX_VS, PATH_IRRADIANCE_FS); Shader shdrPrefilter = LoadShader(PATH_SKYBOX_VS, PATH_PREFILTER_FS); Shader shdrBRDF = LoadShader(PATH_BRDF_VS, PATH_BRDF_FS); // Setup required shader locations SetShaderValuei(shdrCubemap, GetShaderLocation(shdrCubemap, "equirectangularMap"), (int[1]){ 0 }, 1); SetShaderValuei(shdrIrradiance, GetShaderLocation(shdrIrradiance, "environmentMap"), (int[1]){ 0 }, 1); SetShaderValuei(shdrPrefilter, GetShaderLocation(shdrPrefilter, "environmentMap"), (int[1]){ 0 }, 1); Texture2D texHDR = LoadTexture("resources/dresden_square.hdr"); Texture2D cubemap = GenTextureCubemap(shdrCubemap, texHDR, CUBEMAP_SIZE); mat.maps[MAP_IRRADIANCE].texture = GenTextureIrradiance(shdrIrradiance, cubemap, IRRADIANCE_SIZE); mat.maps[MAP_PREFILTER].texture = GenTexturePrefilter(shdrPrefilter, cubemap, PREFILTERED_SIZE); mat.maps[MAP_BRDF].texture = GenTextureBRDF(shdrBRDF, cubemap, BRDF_SIZE); UnloadTexture(cubemap); UnloadTexture(texHDR); // Unload already used shaders (to create specific textures) UnloadShader(shdrCubemap); UnloadShader(shdrIrradiance); UnloadShader(shdrPrefilter); UnloadShader(shdrBRDF); // Set textures filtering for better quality SetTextureFilter(mat.maps[MAP_ALBEDO].texture, FILTER_BILINEAR); SetTextureFilter(mat.maps[MAP_NORMAL].texture, FILTER_BILINEAR); SetTextureFilter(mat.maps[MAP_METALNESS].texture, FILTER_BILINEAR); SetTextureFilter(mat.maps[MAP_ROUGHNESS].texture, FILTER_BILINEAR); SetTextureFilter(mat.maps[MAP_OCCLUSION].texture, FILTER_BILINEAR); // Enable sample usage in shader for assigned textures SetShaderValuei(mat.shader, GetShaderLocation(mat.shader, "albedo.useSampler"), (int[1]){ 1 }, 1); SetShaderValuei(mat.shader, GetShaderLocation(mat.shader, "normals.useSampler"), (int[1]){ 1 }, 1); SetShaderValuei(mat.shader, GetShaderLocation(mat.shader, "metalness.useSampler"), (int[1]){ 1 }, 1); SetShaderValuei(mat.shader, GetShaderLocation(mat.shader, "roughness.useSampler"), (int[1]){ 1 }, 1); SetShaderValuei(mat.shader, GetShaderLocation(mat.shader, "occlusion.useSampler"), (int[1]){ 1 }, 1); int renderModeLoc = GetShaderLocation(mat.shader, "renderMode"); SetShaderValuei(mat.shader, renderModeLoc, (int[1]){ 0 }, 1); // Set up material properties color mat.maps[MAP_ALBEDO].color = albedo; mat.maps[MAP_NORMAL].color = new Color( 128, 128, 255, 255 );; mat.maps[MAP_METALNESS].value = metalness; mat.maps[MAP_ROUGHNESS].value = roughness; mat.maps[MAP_OCCLUSION].value = 1.0f; mat.maps[MAP_EMISSION].value = 0.5f; mat.maps[MAP_HEIGHT].value = 0.5f; return mat; } + /******************************************************************************************* * * raylib [models] example - PBR material * * This example has been created using raylib 1.8 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2017 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public const int CUBEMAP_SIZE = 512; public const int IRRADIANCE_SIZE = 32; public const int PREFILTERED_SIZE = 256; public const int BRDF_SIZE = 512; // PBR material loading /*static Material LoadMaterialPBR(Color albedo, float metalness, float roughness); public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; SetConfigFlags(FLAG_MSAA_4X_HINT); // Enable Multi Sampling Anti Aliasing 4x (if available) InitWindow(screenWidth, screenHeight, "raylib [models] example - pbr material"); // Define the camera to look into our 3d world Camera3D camera = new Camera3D(new Vector3( 4.0f, 4.0f, 4.0f ), new Vector3( 0.0f, 0.5f, 0.0f ), new Vector3( 0.0f, 1.0f, 0.0f ), 45.0f, 0 ); // Load model and PBR material Model model = LoadModel("resources/pbr/trooper.obj"); MeshTangents(ref model.mesh); model.material = LoadMaterialPBR(new Color( 255, 255, 255, 255 ), 1.0f, 1.0f); // Define lights attributes // NOTE: Shader is passed to every light on creation to define shader bindings internally Light lights[MAX_LIGHTS] = { CreateLight(LIGHT_POINT, new Vector3( LIGHT_DISTANCE, LIGHT_HEIGHT, 0.0f }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 255, 0, 0, 255 ), model.material.shader), CreateLight(LIGHT_POINT, new Vector3( 0.0f, LIGHT_HEIGHT, LIGHT_DISTANCE }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 0, 255, 0, 255 ), model.material.shader), CreateLight(LIGHT_POINT, new Vector3( -LIGHT_DISTANCE, LIGHT_HEIGHT, 0.0f }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 0, 0, 255, 255 ), model.material.shader), CreateLight(LIGHT_DIRECTIONAL, new Vector3( 0.0f, LIGHT_HEIGHT*2.0f, -LIGHT_DISTANCE }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 255, 0, 255, 255 ), model.material.shader) }; SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateCamera(ref amera); // Update camera // Send to material PBR shader camera view position float cameraPos[3] = { camera.position.x, camera.position.y, camera.position.z }; SetShaderValue(model.material.shader, model.material.shader.locs[LOC_VECTOR_VIEW], cameraPos, 3); //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); DrawModel(model, Vector3Zero(), 1.0f, WHITE); DrawGrid(10, 1.0f); EndMode3D(); DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadModel(model); // Unload skybox model CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } // Load PBR material (Supports: ALBEDO, NORMAL, METALNESS, ROUGHNESS, AO, EMMISIVE, HEIGHT maps) // NOTE: PBR shader is loaded inside this function static Material LoadMaterialPBR(Color albedo, float metalness, float roughness) { Material mat = new Material( 0 }; // NOTE: All maps textures are set to { 0 ) public const string PATH_PBR_VS = "resources/shaders/pbr.vs"; public const string PATH_PBR_FS = "resources/shaders/pbr.fs"; mat.shader = LoadShader(PATH_PBR_VS, PATH_PBR_FS); // Get required locations points for PBR material // NOTE: Those location names must be available and used in the shader code mat.shader.locs[LOC_MAP_ALBEDO] = GetShaderLocation(mat.shader, "albedo.sampler"); mat.shader.locs[LOC_MAP_METALNESS] = GetShaderLocation(mat.shader, "metalness.sampler"); mat.shader.locs[LOC_MAP_NORMAL] = GetShaderLocation(mat.shader, "normals.sampler"); mat.shader.locs[LOC_MAP_ROUGHNESS] = GetShaderLocation(mat.shader, "roughness.sampler"); mat.shader.locs[LOC_MAP_OCCLUSION] = GetShaderLocation(mat.shader, "occlusion.sampler"); //mat.shader.locs[LOC_MAP_EMISSION] = GetShaderLocation(mat.shader, "emission.sampler"); //mat.shader.locs[LOC_MAP_HEIGHT] = GetShaderLocation(mat.shader, "height.sampler"); mat.shader.locs[LOC_MAP_IRRADIANCE] = GetShaderLocation(mat.shader, "irradianceMap"); mat.shader.locs[LOC_MAP_PREFILTER] = GetShaderLocation(mat.shader, "prefilterMap"); mat.shader.locs[LOC_MAP_BRDF] = GetShaderLocation(mat.shader, "brdfLUT"); // Set view matrix location mat.shader.locs[LOC_MATRIX_MODEL] = GetShaderLocation(mat.shader, "matModel"); mat.shader.locs[LOC_MATRIX_VIEW] = GetShaderLocation(mat.shader, "view"); mat.shader.locs[LOC_VECTOR_VIEW] = GetShaderLocation(mat.shader, "viewPos"); // Set PBR standard maps mat.maps[MAP_ALBEDO].texture = LoadTexture("resources/pbr/trooper_albedo.png"); mat.maps[MAP_NORMAL].texture = LoadTexture("resources/pbr/trooper_normals.png"); mat.maps[MAP_METALNESS].texture = LoadTexture("resources/pbr/trooper_metalness.png"); mat.maps[MAP_ROUGHNESS].texture = LoadTexture("resources/pbr/trooper_roughness.png"); mat.maps[MAP_OCCLUSION].texture = LoadTexture("resources/pbr/trooper_ao.png"); // Set environment maps public const string PATH_CUBEMAP_VS = "resources/shaders/cubemap.vs"; public const string PATH_CUBEMAP_FS = "resources/shaders/cubemap.fs"; public const string PATH_SKYBOX_VS = "resources/shaders/skybox.vs"; public const string PATH_IRRADIANCE_FS = "resources/shaders/irradiance.fs"; public const string PATH_PREFILTER_FS = "resources/shaders/prefilter.fs"; public const string PATH_BRDF_VS = "resources/shaders/brdf.vs"; public const string PATH_BRDF_FS = "resources/shaders/brdf.fs"; Shader shdrCubemap = LoadShader(PATH_CUBEMAP_VS, PATH_CUBEMAP_FS); Shader shdrIrradiance = LoadShader(PATH_SKYBOX_VS, PATH_IRRADIANCE_FS); Shader shdrPrefilter = LoadShader(PATH_SKYBOX_VS, PATH_PREFILTER_FS); Shader shdrBRDF = LoadShader(PATH_BRDF_VS, PATH_BRDF_FS); // Setup required shader locations SetShaderValuei(shdrCubemap, GetShaderLocation(shdrCubemap, "equirectangularMap"), (int[1]){ 0 }, 1); SetShaderValuei(shdrIrradiance, GetShaderLocation(shdrIrradiance, "environmentMap"), (int[1]){ 0 }, 1); SetShaderValuei(shdrPrefilter, GetShaderLocation(shdrPrefilter, "environmentMap"), (int[1]){ 0 }, 1); Texture2D texHDR = LoadTexture("resources/dresden_square.hdr"); Texture2D cubemap = GenTextureCubemap(shdrCubemap, texHDR, CUBEMAP_SIZE); mat.maps[MAP_IRRADIANCE].texture = GenTextureIrradiance(shdrIrradiance, cubemap, IRRADIANCE_SIZE); mat.maps[MAP_PREFILTER].texture = GenTexturePrefilter(shdrPrefilter, cubemap, PREFILTERED_SIZE); mat.maps[MAP_BRDF].texture = GenTextureBRDF(shdrBRDF, cubemap, BRDF_SIZE); UnloadTexture(cubemap); UnloadTexture(texHDR); // Unload already used shaders (to create specific textures) UnloadShader(shdrCubemap); UnloadShader(shdrIrradiance); UnloadShader(shdrPrefilter); UnloadShader(shdrBRDF); // Set textures filtering for better quality SetTextureFilter(mat.maps[MAP_ALBEDO].texture, FILTER_BILINEAR); SetTextureFilter(mat.maps[MAP_NORMAL].texture, FILTER_BILINEAR); SetTextureFilter(mat.maps[MAP_METALNESS].texture, FILTER_BILINEAR); SetTextureFilter(mat.maps[MAP_ROUGHNESS].texture, FILTER_BILINEAR); SetTextureFilter(mat.maps[MAP_OCCLUSION].texture, FILTER_BILINEAR); // Enable sample usage in shader for assigned textures SetShaderValuei(mat.shader, GetShaderLocation(mat.shader, "albedo.useSampler"), (int[1]){ 1 }, 1); SetShaderValuei(mat.shader, GetShaderLocation(mat.shader, "normals.useSampler"), (int[1]){ 1 }, 1); SetShaderValuei(mat.shader, GetShaderLocation(mat.shader, "metalness.useSampler"), (int[1]){ 1 }, 1); SetShaderValuei(mat.shader, GetShaderLocation(mat.shader, "roughness.useSampler"), (int[1]){ 1 }, 1); SetShaderValuei(mat.shader, GetShaderLocation(mat.shader, "occlusion.useSampler"), (int[1]){ 1 }, 1); int renderModeLoc = GetShaderLocation(mat.shader, "renderMode"); SetShaderValuei(mat.shader, renderModeLoc, (int[1]){ 0 }, 1); // Set up material properties color mat.maps[MAP_ALBEDO].color = albedo; mat.maps[MAP_NORMAL].color = new Color( 128, 128, 255, 255 ); mat.maps[MAP_METALNESS].value = metalness; mat.maps[MAP_ROUGHNESS].value = roughness; mat.maps[MAP_OCCLUSION].value = 1.0f; mat.maps[MAP_EMISSION].value = 0.5f; mat.maps[MAP_HEIGHT].value = 0.5f; return mat; }*/ } diff --git a/Examples/models/models_mesh_generation.cs b/Examples/models/models_mesh_generation.cs index 3f07304..4a4dc63 100644 --- a/Examples/models/models_mesh_generation.cs +++ b/Examples/models/models_mesh_generation.cs @@ -1,7 +1,9 @@ using Raylib; using static Raylib.Raylib; +using static Raylib.CameraMode; +using static Raylib.TexmapIndex; -public partial class Examples +public partial class models_mesh_generation { - /******************************************************************************************* * * raylib example - procedural mesh generation * * This example has been created using raylib 1.8 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2017 Ramon Santamaria (Ray San) * ********************************************************************************************/ public const #define NUM_MODELS 7 // We generate 7 parametric 3d shapes public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - mesh generation"); // We generate a checked image for texturing Image checked = GenImageChecked(2, 2, 1, 1, RED, GREEN); Texture2D texture = LoadTextureFromImage(checked); UnloadImage(checked); Model[] models = new Model[NUM_MODELS]; models[0] = LoadModelFromMesh(GenMeshPlane(2, 2, 5, 5)); models[1] = LoadModelFromMesh(GenMeshCube(2.0f, 1.0f, 2.0f)); models[2] = LoadModelFromMesh(GenMeshSphere(2, 32, 32)); models[3] = LoadModelFromMesh(GenMeshHemiSphere(2, 16, 16)); models[4] = LoadModelFromMesh(GenMeshCylinder(1, 2, 16)); models[5] = LoadModelFromMesh(GenMeshTorus(0.25f, 4.0f, 16, 32)); models[6] = LoadModelFromMesh(GenMeshKnot(1.0f, 2.0f, 16, 128)); // Set checked texture as default diffuse component for all models material for (int i = 0; i < NUM_MODELS; i++) models[i].material.maps[MAP_DIFFUSE].texture = texture; // Define the camera to look into our 3d world Camera camera = {{ 5.0f, 5.0f, 5.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 }; // Model drawing position Vector3 position = { 0.0f, 0.0f, 0.0f }; int currentModel = 0; SetCameraMode(camera, CAMERA_ORBITAL); // Set a orbital camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateCamera(&camera); // Update internal camera and our camera if (IsMouseButtonPressed((int)Mouse.LEFT_BUTTON)) { currentModel = (currentModel + 1)%NUM_MODELS; // Cycle between the textures } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); DrawModel(models[currentModel], position, 1.0f, WHITE); DrawGrid(10, 1.0); EndMode3D(); DrawRectangle(30, 400, 310, 30, Fade(SKYBLUE, 0.5f)); DrawRectangleLines(30, 400, 310, 30, Fade(DARKBLUE, 0.5f)); DrawText("MOUSE LEFT BUTTON to CYCLE PROCEDURAL MODELS", 40, 410, 10, BLUE); switch(currentModel) { case 0: DrawText("PLANE", 680, 10, 20, DARKBLUE); break; case 1: DrawText("CUBE", 680, 10, 20, DARKBLUE); break; case 2: DrawText("SPHERE", 680, 10, 20, DARKBLUE); break; case 3: DrawText("HEMISPHERE", 640, 10, 20, DARKBLUE); break; case 4: DrawText("CYLINDER", 680, 10, 20, DARKBLUE); break; case 5: DrawText("TORUS", 680, 10, 20, DARKBLUE); break; case 6: DrawText("KNOT", 680, 10, 20, DARKBLUE); break; default: break; } EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- // Unload models data (GPU VRAM) for (int i = 0; i < NUM_MODELS; i++) UnloadModel(models[i]); CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib example - procedural mesh generation * * This example has been created using raylib 1.8 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2017 Ramon Santamaria (Ray San) * ********************************************************************************************/ public const int NUM_MODELS = 7; public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - mesh generation"); // We generate a isChecked image for texturing Image isChecked = GenImageChecked(2, 2, 1, 1, RED, GREEN); Texture2D texture = LoadTextureFromImage(isChecked); UnloadImage(isChecked); Model[] models = new Model[NUM_MODELS]; models[0] = LoadModelFromMesh(GenMeshPlane(2, 2, 5, 5)); models[1] = LoadModelFromMesh(GenMeshCube(2.0f, 1.0f, 2.0f)); models[2] = LoadModelFromMesh(GenMeshSphere(2, 32, 32)); models[3] = LoadModelFromMesh(GenMeshHemiSphere(2, 16, 16)); models[4] = LoadModelFromMesh(GenMeshCylinder(1, 2, 16)); models[5] = LoadModelFromMesh(GenMeshTorus(0.25f, 4.0f, 16, 32)); models[6] = LoadModelFromMesh(GenMeshKnot(1.0f, 2.0f, 16, 128)); // Set isChecked texture as default diffuse component for all models material for (int i = 0; i < NUM_MODELS; i++) models[i].material.maps[(int)MAP_ALBEDO].texture = texture; // Define the camera to look into our 3d world Camera3D camera = new Camera3D(new Vector3( 5.0f, 5.0f, 5.0f ), new Vector3( 0.0f, 0.0f, 0.0f ), new Vector3( 0.0f, 1.0f, 0.0f ), 45.0f, 0 ); // Model drawing position Vector3 position = new Vector3( 0.0f, 0.0f, 0.0f ); int currentModel = 0; SetCameraMode(camera, (int)CAMERA_ORBITAL); // Set a orbital camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateCamera(ref camera); // Update internal camera and our camera if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { currentModel = (currentModel + 1)%NUM_MODELS; // Cycle between the textures } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); DrawModel(models[currentModel], position, 1.0f, WHITE); DrawGrid(10, 1.0f); EndMode3D(); DrawRectangle(30, 400, 310, 30, Fade(SKYBLUE, 0.5f)); DrawRectangleLines(30, 400, 310, 30, Fade(DARKBLUE, 0.5f)); DrawText("MOUSE LEFT BUTTON to CYCLE PROCEDURAL MODELS", 40, 410, 10, BLUE); switch(currentModel) { case 0: DrawText("PLANE", 680, 10, 20, DARKBLUE); break; case 1: DrawText("CUBE", 680, 10, 20, DARKBLUE); break; case 2: DrawText("SPHERE", 680, 10, 20, DARKBLUE); break; case 3: DrawText("HEMISPHERE", 640, 10, 20, DARKBLUE); break; case 4: DrawText("CYLINDER", 680, 10, 20, DARKBLUE); break; case 5: DrawText("TORUS", 680, 10, 20, DARKBLUE); break; case 6: DrawText("KNOT", 680, 10, 20, DARKBLUE); break; default: break; } EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- // Unload models data (GPU VRAM) for (int i = 0; i < NUM_MODELS; i++) UnloadModel(models[i]); CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/models/models_mesh_picking.cs b/Examples/models/models_mesh_picking.cs index 1c0def2..bdd58a4 100644 --- a/Examples/models/models_mesh_picking.cs +++ b/Examples/models/models_mesh_picking.cs @@ -1,7 +1,10 @@ using Raylib; using static Raylib.Raylib; +using static Raylib.CameraType; +using static Raylib.CameraMode; +using static Raylib.TexmapIndex; -public partial class Examples +public partial class models_mesh_picking { - /******************************************************************************************* * * raylib [models] example - Mesh picking in 3d mode, ground plane, triangle, mesh * * This example has been created using raylib 1.7 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * Example contributed by Joel Davis (@joeld42) * ********************************************************************************************/ public const #define FLT_MAX 3.40282347E+38F // Maximum value of a float, defined in public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - mesh picking"); // Define the camera to look into our 3d world Camera camera; camera.position = new Vector3( 20.0f, 20.0f, 20.0f );; // Camera position camera.target = new Vector3( 0.0f, 8.0f, 0.0f );; // Camera looking at point camera.up = new Vector3( 0.0f, 1.6f, 0.0f );; // Camera up vector (rotation towards target) camera.fovy = 45.0f; // Camera field-of-view Y camera.type = CAMERA_PERSPECTIVE; // Camera mode type Ray ray; // Picking ray Model tower = LoadModel("resources/models/turret.obj"); // Load OBJ model Texture2D texture = LoadTexture("resources/models/turret_diffuse.png"); // Load model texture tower.material.maps[MAP_DIFFUSE].texture = texture; // Set model diffuse texture Vector3 towerPos = { 0.0f, 0.0f, 0.0f }; // Set model position BoundingBox towerBBox = MeshBoundingBox(tower.mesh); // Get mesh bounding box bool hitMeshBBox = false; bool hitTriangle = false; // Test triangle Vector3 ta = new Vector3( -25.0, 0.5, 0.0 );; Vector3 tb = new Vector3( -4.0, 2.5, 1.0 );; Vector3 tc = new Vector3( -8.0, 6.5, 0.0 );; Vector3 bary = { 0.0f, 0.0f, 0.0f }; SetCameraMode(camera, CAMERA_FREE); // Set a free camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateCamera(&camera); // Update camera // Display information about closest hit RayHitInfo nearestHit; char *hitObjectName = "None"; nearestHit.distance = FLT_MAX; nearestHit.hit = false; Color cursorColor = WHITE; // Get ray and test against ground, triangle, and mesh ray = GetMouseRay(GetMousePosition(), camera); // Check ray collision aginst ground plane RayHitInfo groundHitInfo = GetCollisionRayGround(ray, 0.0f); if ((groundHitInfo.hit) && (groundHitInfo.distance < nearestHit.distance)) { nearestHit = groundHitInfo; cursorColor = GREEN; hitObjectName = "Ground"; } // Check ray collision against test triangle RayHitInfo triHitInfo = GetCollisionRayTriangle(ray, ta, tb, tc); if ((triHitInfo.hit) && (triHitInfo.distance < nearestHit.distance)) { nearestHit = triHitInfo; cursorColor = PURPLE; hitObjectName = "Triangle"; bary = Vector3Barycenter(nearestHit.position, ta, tb, tc); hitTriangle = true; } else hitTriangle = false; RayHitInfo meshHitInfo; // Check ray collision against bounding box first, before trying the full ray-mesh test if (CheckCollisionRayBox(ray, towerBBox)) { hitMeshBBox = true; // Check ray collision against model // NOTE: It considers model.transform matrix! meshHitInfo = GetCollisionRayModel(ray, &tower); if ((meshHitInfo.hit) && (meshHitInfo.distance < nearestHit.distance)) { nearestHit = meshHitInfo; cursorColor = ORANGE; hitObjectName = "Mesh"; } } hitMeshBBox = false; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); // Draw the tower // WARNING: If scale is different than 1.0f, // not considered by GetCollisionRayModel() DrawModel(tower, towerPos, 1.0f, WHITE); // Draw the test triangle DrawLine3D(ta, tb, PURPLE); DrawLine3D(tb, tc, PURPLE); DrawLine3D(tc, ta, PURPLE); // Draw the mesh bbox if we hit it if (hitMeshBBox) DrawBoundingBox(towerBBox, LIME); // If we hit something, draw the cursor at the hit point if (nearestHit.hit) { DrawCube(nearestHit.position, 0.3, 0.3, 0.3, cursorColor); DrawCubeWires(nearestHit.position, 0.3, 0.3, 0.3, RED); Vector3 normalEnd; normalEnd.x = nearestHit.position.x + nearestHit.normal.x; normalEnd.y = nearestHit.position.y + nearestHit.normal.y; normalEnd.z = nearestHit.position.z + nearestHit.normal.z; DrawLine3D(nearestHit.position, normalEnd, RED); } DrawRay(ray, MAROON); DrawGrid(10, 10.0f); EndMode3D(); // Draw some debug GUI text DrawText(FormatText("Hit Object: %s", hitObjectName), 10, 50, 10, BLACK); if (nearestHit.hit) { int ypos = 70; DrawText(FormatText("Distance: %3.2f", nearestHit.distance), 10, ypos, 10, BLACK); DrawText(FormatText("Hit Pos: %3.2f %3.2f %3.2f", nearestHit.position.x, nearestHit.position.y, nearestHit.position.z), 10, ypos + 15, 10, BLACK); DrawText(FormatText("Hit Norm: %3.2f %3.2f %3.2f", nearestHit.normal.x, nearestHit.normal.y, nearestHit.normal.z), 10, ypos + 30, 10, BLACK); if (hitTriangle) DrawText(FormatText("Barycenter: %3.2f %3.2f %3.2f", bary.x, bary.y, bary.z), 10, ypos + 45, 10, BLACK); } DrawText("Use Mouse to Move Camera", 10, 430, 10, GRAY); DrawText("(c) Turret 3D model by Alberto Cano", screenWidth - 200, screenHeight - 20, 10, GRAY); DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadModel(tower); // Unload model UnloadTexture(texture); // Unload texture CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [models] example - Mesh picking in 3d mode, ground plane, triangle, mesh * * This example has been created using raylib 1.7 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * Example contributed by Joel Davis (@joeld42) * ********************************************************************************************/ public const float FLT_MAX = 3.40282347E+38F; public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - mesh picking"); // Define the camera to look into our 3d world Camera3D camera; camera.position = new Vector3( 20.0f, 20.0f, 20.0f ); // Camera3D position camera.target = new Vector3( 0.0f, 8.0f, 0.0f ); // Camera3D looking at point camera.up = new Vector3( 0.0f, 1.6f, 0.0f ); // Camera3D up vector (rotation towards target) camera.fovy = 45.0f; // Camera3D field-of-view Y camera.type = CAMERA_PERSPECTIVE; // Camera3D mode type Ray ray; // Picking ray Model tower = LoadModel("resources/models/turret.obj"); // Load OBJ model Texture2D texture = LoadTexture("resources/models/turret_diffuse.png"); // Load model texture tower.material.maps[(int)MAP_ALBEDO].texture = texture; // Set model diffuse texture Vector3 towerPos = new Vector3( 0.0f, 0.0f, 0.0f ); // Set model position BoundingBox towerBBox = MeshBoundingBox(tower.mesh); // Get mesh bounding box bool hitMeshBBox = false; bool hitTriangle = false; // Test triangle Vector3 ta = new Vector3( -25.0f, 0.5f, 0.0f ); Vector3 tb = new Vector3( -4.0f, 2.5f, 1.0f ); Vector3 tc = new Vector3( -8.0f, 6.5f, 0.0f ); Vector3 bary = new Vector3( 0.0f, 0.0f, 0.0f ); SetCameraMode(camera, (int)CAMERA_FREE); // Set a free camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateCamera(ref camera); // Update camera // Display information about closest hit RayHitInfo nearestHit = new RayHitInfo(); string hitObjectName = "None"; nearestHit.distance = FLT_MAX; nearestHit.hit = false; Color cursorColor = WHITE; // Get ray and test against ground, triangle, and mesh ray = GetMouseRay(GetMousePosition(), camera); // Check ray collision aginst ground plane RayHitInfo groundHitInfo = GetCollisionRayGround(ray, 0.0f); if ((groundHitInfo.hit) && (groundHitInfo.distance < nearestHit.distance)) { nearestHit = groundHitInfo; cursorColor = GREEN; hitObjectName = "Ground"; } // Check ray collision against test triangle RayHitInfo triHitInfo = GetCollisionRayTriangle(ray, ta, tb, tc); if ((triHitInfo.hit) && (triHitInfo.distance < nearestHit.distance)) { nearestHit = triHitInfo; cursorColor = PURPLE; hitObjectName = "Triangle"; bary = Vector3Barycenter(nearestHit.position, ta, tb, tc); hitTriangle = true; } else hitTriangle = false; RayHitInfo meshHitInfo; // Check ray collision against bounding box first, before trying the full ray-mesh test if (CheckCollisionRayBox(ray, towerBBox)) { hitMeshBBox = true; // Check ray collision against model // NOTE: It considers model.transform matrix! meshHitInfo = GetCollisionRayModel(ray, ref tower); if ((meshHitInfo.hit) && (meshHitInfo.distance < nearestHit.distance)) { nearestHit = meshHitInfo; cursorColor = ORANGE; hitObjectName = "Mesh"; } } hitMeshBBox = false; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); // Draw the tower // WARNING: If scale is different than 1.0f, // not considered by GetCollisionRayModel() DrawModel(tower, towerPos, 1.0f, WHITE); // Draw the test triangle DrawLine3D(ta, tb, PURPLE); DrawLine3D(tb, tc, PURPLE); DrawLine3D(tc, ta, PURPLE); // Draw the mesh bbox if we hit it if (hitMeshBBox) DrawBoundingBox(towerBBox, LIME); // If we hit something, draw the cursor at the hit point if (nearestHit.hit) { DrawCube(nearestHit.position, 0.3f, 0.3f, 0.3f, cursorColor); DrawCubeWires(nearestHit.position, 0.3f, 0.3f, 0.3f, RED); Vector3 normalEnd; normalEnd.x = nearestHit.position.x + nearestHit.normal.x; normalEnd.y = nearestHit.position.y + nearestHit.normal.y; normalEnd.z = nearestHit.position.z + nearestHit.normal.z; DrawLine3D(nearestHit.position, normalEnd, RED); } DrawRay(ray, MAROON); DrawGrid(10, 10.0f); EndMode3D(); // Draw some debug GUI text DrawText(FormatText("Hit Object: %s", hitObjectName), 10, 50, 10, BLACK); if (nearestHit.hit) { int ypos = 70; DrawText(FormatText("Distance: %3.2f", nearestHit.distance), 10, ypos, 10, BLACK); DrawText(FormatText("Hit Pos: %3.2f %3.2f %3.2f", nearestHit.position.x, nearestHit.position.y, nearestHit.position.z), 10, ypos + 15, 10, BLACK); DrawText(FormatText("Hit Norm: %3.2f %3.2f %3.2f", nearestHit.normal.x, nearestHit.normal.y, nearestHit.normal.z), 10, ypos + 30, 10, BLACK); if (hitTriangle) DrawText(FormatText("Barycenter: %3.2f %3.2f %3.2f", bary.x, bary.y, bary.z), 10, ypos + 45, 10, BLACK); } DrawText("Use Mouse to Move Camera", 10, 430, 10, GRAY); DrawText("(c) Turret 3D model by Alberto Cano", screenWidth - 200, screenHeight - 20, 10, GRAY); DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadModel(tower); // Unload model UnloadTexture(texture); // Unload texture CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/models/models_obj_loading.cs b/Examples/models/models_obj_loading.cs index a5aac57..bc5c85a 100644 --- a/Examples/models/models_obj_loading.cs +++ b/Examples/models/models_obj_loading.cs @@ -1,7 +1,9 @@ using Raylib; using static Raylib.Raylib; +using static Raylib.CameraType; +using static Raylib.TexmapIndex; -public partial class Examples +public partial class models_obj_loading { - /******************************************************************************************* * * raylib [models] example - Load and draw a 3d model (OBJ) * * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - obj model loading"); // Define the camera to look into our 3d world Camera camera = { 0 }; camera.position = new Vector3( 8.0f, 8.0f, 8.0f );; // Camera position camera.target = new Vector3( 0.0f, 2.5f, 0.0f );; // Camera looking at point camera.up = new Vector3( 0.0f, 1.0f, 0.0f );; // Camera up vector (rotation towards target) camera.fovy = 45.0f; // Camera field-of-view Y camera.type = CAMERA_PERSPECTIVE; // Camera mode type Model model = LoadModel("resources/models/castle.obj"); // Load OBJ model Texture2D texture = LoadTexture("resources/models/castle_diffuse.png"); // Load model texture model.material.maps[MAP_DIFFUSE].texture = texture; // Set map diffuse texture Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position 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 //---------------------------------------------------------------------------------- //... //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); DrawModel(model, position, 0.2f, WHITE); // Draw 3d model with texture DrawGrid(10, 1.0f); // Draw a grid DrawGizmo(position); // Draw gizmo EndMode3D(); DrawText("(c) Castle 3D model by Alberto Cano", screenWidth - 200, screenHeight - 20, 10, GRAY); DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(texture); // Unload texture UnloadModel(model); // Unload model CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [models] example - Load and draw a 3d model (OBJ) * * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - obj model loading"); // Define the camera to look into our 3d world Camera3D camera = new Camera3D(); camera.position = new Vector3( 8.0f, 8.0f, 8.0f ); // Camera3D position camera.target = new Vector3( 0.0f, 2.5f, 0.0f ); // Camera3D looking at point camera.up = new Vector3( 0.0f, 1.0f, 0.0f ); // Camera3D up vector (rotation towards target) camera.fovy = 45.0f; // Camera3D field-of-view Y camera.type = CAMERA_PERSPECTIVE; // Camera3D mode type Model model = LoadModel("resources/models/castle.obj"); // Load OBJ model Texture2D texture = LoadTexture("resources/models/castle_diffuse.png"); // Load model texture model.material.maps[(int)MAP_ALBEDO].texture = texture; // Set map diffuse texture Vector3 position = new Vector3( 0.0f, 0.0f, 0.0f ); // Set model position 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 //---------------------------------------------------------------------------------- //... //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); DrawModel(model, position, 0.2f, WHITE); // Draw 3d model with texture DrawGrid(10, 1.0f); // Draw a grid DrawGizmo(position); // Draw gizmo EndMode3D(); DrawText("(c) Castle 3D model by Alberto Cano", screenWidth - 200, screenHeight - 20, 10, GRAY); DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(texture); // Unload texture UnloadModel(model); // Unload model CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/models/models_orthographic_projection.cs b/Examples/models/models_orthographic_projection.cs index 74ee184..84eeee0 100644 --- a/Examples/models/models_orthographic_projection.cs +++ b/Examples/models/models_orthographic_projection.cs @@ -1,7 +1,9 @@ using Raylib; using static Raylib.Raylib; +using static Raylib.CameraType; +using static Raylib.CameraMode; -public partial class Examples +public partial class models_orthographic_projection { - /******************************************************************************************* * * raylib [models] example - Show the difference between perspective and orthographic projection * * This program is heavily based on the geometric objects example * * This example has been created using raylib 1.9.7 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2018 Max Danielsson & Ramon Santamaria (@raysan5) * ********************************************************************************************/ public const #define FOVY_PERSPECTIVE 45.0f public const #define WIDTH_ORTHOGRAPHIC 10.0f public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - geometric shapes"); // Define the camera to look into our 3d world Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, FOVY_PERSPECTIVE, CAMERA_PERSPECTIVE }; SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (IsKeyPressed((int)Key.SPACE)) { if (camera.type == CAMERA_PERSPECTIVE) { camera.fovy = WIDTH_ORTHOGRAPHIC; camera.type = CAMERA_ORTHOGRAPHIC; } else { camera.fovy = FOVY_PERSPECTIVE; camera.type = CAMERA_PERSPECTIVE; } } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); DrawCube(new Vector3(-4.0f, 0.0f, 2.0f);, 2.0f, 5.0f, 2.0f, RED); DrawCubeWires(new Vector3(-4.0f, 0.0f, 2.0f);, 2.0f, 5.0f, 2.0f, GOLD); DrawCubeWires(new Vector3(-4.0f, 0.0f, -2.0f);, 3.0f, 6.0f, 2.0f, MAROON); DrawSphere(new Vector3(-1.0f, 0.0f, -2.0f);, 1.0f, GREEN); DrawSphereWires(new Vector3(1.0f, 0.0f, 2.0f);, 2.0f, 16, 16, LIME); DrawCylinder(new Vector3(4.0f, 0.0f, -2.0f);, 1.0f, 2.0f, 3.0f, 4, SKYBLUE); DrawCylinderWires(new Vector3(4.0f, 0.0f, -2.0f);, 1.0f, 2.0f, 3.0f, 4, DARKBLUE); DrawCylinderWires(new Vector3(4.5f, -1.0f, 2.0f);, 1.0f, 1.0f, 2.0f, 6, BROWN); DrawCylinder(new Vector3(1.0f, 0.0f, -4.0f);, 0.0f, 1.5f, 3.0f, 8, GOLD); DrawCylinderWires(new Vector3(1.0f, 0.0f, -4.0f);, 0.0f, 1.5f, 3.0f, 8, PINK); DrawGrid(10, 1.0f); // Draw a grid EndMode3D(); DrawText("Press Spacebar to switch camera type", 10, GetScreenHeight() - 30, 20, DARKGRAY); if (camera.type == CAMERA_ORTHOGRAPHIC) DrawText("ORTHOGRAPHIC", 10, 40, 20, BLACK); else if (camera.type == CAMERA_PERSPECTIVE) DrawText("PERSPECTIVE", 10, 40, 20, BLACK); DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [models] example - Show the difference between perspective and orthographic projection * * This program is heavily based on the geometric objects example * * This example has been created using raylib 1.9.7 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2018 Max Danielsson ref Ramon Santamaria (@raysan5) * ********************************************************************************************/ public const float FOVY_PERSPECTIVE = 45.0f; public const float WIDTH_ORTHOGRAPHIC = 10.0f; public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - geometric shapes"); // Define the camera to look into our 3d world Camera3D camera = new Camera3D(new Vector3( 0.0f, 10.0f, 10.0f ), new Vector3( 0.0f, 0.0f, 0.0f ), new Vector3( 0.0f, 1.0f, 0.0f ), FOVY_PERSPECTIVE, CAMERA_PERSPECTIVE ); SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (IsKeyPressed(KEY_SPACE)) { if (camera.type == CAMERA_PERSPECTIVE) { camera.fovy = WIDTH_ORTHOGRAPHIC; camera.type = CAMERA_ORTHOGRAPHIC; } else { camera.fovy = FOVY_PERSPECTIVE; camera.type = CAMERA_PERSPECTIVE; } } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); DrawCube(new Vector3(-4.0f, 0.0f, 2.0f), 2.0f, 5.0f, 2.0f, RED); DrawCubeWires(new Vector3(-4.0f, 0.0f, 2.0f), 2.0f, 5.0f, 2.0f, GOLD); DrawCubeWires(new Vector3(-4.0f, 0.0f, -2.0f), 3.0f, 6.0f, 2.0f, MAROON); DrawSphere(new Vector3(-1.0f, 0.0f, -2.0f), 1.0f, GREEN); DrawSphereWires(new Vector3(1.0f, 0.0f, 2.0f), 2.0f, 16, 16, LIME); DrawCylinder(new Vector3(4.0f, 0.0f, -2.0f), 1.0f, 2.0f, 3.0f, 4, SKYBLUE); DrawCylinderWires(new Vector3(4.0f, 0.0f, -2.0f), 1.0f, 2.0f, 3.0f, 4, DARKBLUE); DrawCylinderWires(new Vector3(4.5f, -1.0f, 2.0f), 1.0f, 1.0f, 2.0f, 6, BROWN); DrawCylinder(new Vector3(1.0f, 0.0f, -4.0f), 0.0f, 1.5f, 3.0f, 8, GOLD); DrawCylinderWires(new Vector3(1.0f, 0.0f, -4.0f), 0.0f, 1.5f, 3.0f, 8, PINK); DrawGrid(10, 1.0f); // Draw a grid EndMode3D(); DrawText("Press Spacebar to switch camera type", 10, GetScreenHeight() - 30, 20, DARKGRAY); if (camera.type == CAMERA_ORTHOGRAPHIC) DrawText("ORTHOGRAPHIC", 10, 40, 20, BLACK); else if (camera.type == CAMERA_PERSPECTIVE) DrawText("PERSPECTIVE", 10, 40, 20, BLACK); DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/models/models_skybox.cs b/Examples/models/models_skybox.cs index 09d7ab8..8c677aa 100644 --- a/Examples/models/models_skybox.cs +++ b/Examples/models/models_skybox.cs @@ -1,7 +1,9 @@ using Raylib; using static Raylib.Raylib; +using static Raylib.CameraMode; +using static Raylib.TexmapIndex; -public partial class Examples +public partial class models_skybox { - /******************************************************************************************* * * raylib [models] example - Skybox loading and drawing * * This example has been created using raylib 1.8 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2017 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - skybox loading and drawing"); // Define the camera to look into our 3d world Camera camera = {{ 1.0f, 1.0f, 1.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 }; // Load skybox model Mesh cube = GenMeshCube(1.0f, 1.0f, 1.0f); Model skybox = LoadModelFromMesh(cube); // Load skybox shader and set required locations // NOTE: Some locations are automatically set at shader loading skybox.material.shader = LoadShader("resources/shaders/skybox.vs", "resources/shaders/skybox.fs"); SetShaderValuei(skybox.material.shader, GetShaderLocation(skybox.material.shader, "environmentMap"), (int[1]){ MAP_CUBEMAP }, 1); // Load cubemap shader and setup required shader locations Shader shdrCubemap = LoadShader("resources/shaders/cubemap.vs", "resources/shaders/cubemap.fs"); SetShaderValuei(shdrCubemap, GetShaderLocation(shdrCubemap, "equirectangularMap"), (int[1]){ 0 }, 1); // Load HDR panorama (sphere) texture Texture2D texHDR = LoadTexture("resources/dresden_square.hdr"); // Generate cubemap (texture with 6 quads-cube-mapping) from panorama HDR texture // NOTE: New texture is generated rendering to texture, shader computes the sphre->cube coordinates mapping skybox.material.maps[MAP_CUBEMAP].texture = GenTextureCubemap(shdrCubemap, texHDR, 512); UnloadTexture(texHDR); // Texture not required anymore, cubemap already generated UnloadShader(shdrCubemap); // Unload cubemap generation shader, not required anymore SetCameraMode(camera, CAMERA_FIRST_PERSON); // Set a first person camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateCamera(&camera); // Update camera //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); DrawModel(skybox, new Vector3(0, 0, 0);, 1.0f, WHITE); DrawGrid(10, 1.0f); EndMode3D(); DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadModel(skybox); // Unload skybox model (and textures) CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [models] example - Skybox loading and drawing * * This example has been created using raylib 1.8 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2017 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - skybox loading and drawing"); // Define the camera to look into our 3d world Camera3D camera = new Camera3D(new Vector3( 1.0f, 1.0f, 1.0f ), new Vector3( 0.0f, 0.0f, 0.0f ), new Vector3( 0.0f, 1.0f, 0.0f ), 45.0f, 0 ); // Load skybox model Mesh cube = GenMeshCube(1.0f, 1.0f, 1.0f); Model skybox = LoadModelFromMesh(cube); // Load skybox shader and set required locations // NOTE: Some locations are automatically set at shader loading skybox.material.shader = LoadShader("resources/shaders/skybox.vs", "resources/shaders/skybox.fs"); SetShaderValuei(skybox.material.shader, GetShaderLocation(skybox.material.shader, "environmentMap"), new int[]{ (int)MAP_CUBEMAP }, 1); // Load cubemap shader and setup required shader locations Shader shdrCubemap = LoadShader("resources/shaders/cubemap.vs", "resources/shaders/cubemap.fs"); SetShaderValuei(shdrCubemap, GetShaderLocation(shdrCubemap, "equirectangularMap"), new int[]{ 0 }, 1); // Load HDR panorama (sphere) texture Texture2D texHDR = LoadTexture("resources/dresden_square.hdr"); // Generate cubemap (texture with 6 quads-cube-mapping) from panorama HDR texture // NOTE: New texture is generated rendering to texture, shader computes the sphre->cube coordinates mapping skybox.material.maps[(int)MAP_CUBEMAP].texture = GenTextureCubemap(shdrCubemap, texHDR, 512); UnloadTexture(texHDR); // Texture not required anymore, cubemap already generated UnloadShader(shdrCubemap); // Unload cubemap generation shader, not required anymore SetCameraMode(camera, (int)CAMERA_FIRST_PERSON); // Set a first person camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateCamera(ref camera); // Update camera //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); DrawModel(skybox, new Vector3(0, 0, 0), 1.0f, WHITE); DrawGrid(10, 1.0f); EndMode3D(); DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadModel(skybox); // Unload skybox model (and textures) CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/models/models_yaw_pitch_roll.cs b/Examples/models/models_yaw_pitch_roll.cs index 49758a3..531fdfe 100644 --- a/Examples/models/models_yaw_pitch_roll.cs +++ b/Examples/models/models_yaw_pitch_roll.cs @@ -1,7 +1,10 @@ using Raylib; using static Raylib.Raylib; +using static Raylib.CameraType; +using static Raylib.TexmapIndex; +using static Raylib.BlendMode; -public partial class Examples +public partial class models_yaw_pitch_roll { - /******************************************************************************************* * * raylib [models] example - Plane rotations (yaw, pitch, roll) * * This example has been created using raylib 1.8 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Example based on Berni work on Raspberry Pi: * http://forum.raylib.com/index.php?p=/discussion/124/line-versus-triangle-drawing-order * * Copyright (c) 2017 Ramon Santamaria (@raysan5) * ********************************************************************************************/ // Draw angle gauge controls void DrawAngleGauge(Texture2D angleGauge, int x, int y, float angle, char title[], Color color); //---------------------------------------------------------------------------------- // Main entry point //---------------------------------------------------------------------------------- public static void Main() { // Initialization //-------------------------------------------------------------------------------------- const int screenWidth = 800; const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - plane rotations (yaw, pitch, roll)"); Texture2D texAngleGauge = LoadTexture("resources/angle_gauge.png"); Texture2D texBackground = LoadTexture("resources/background.png"); Texture2D texPitch = LoadTexture("resources/pitch.png"); Texture2D texPlane = LoadTexture("resources/plane.png"); RenderTexture2D framebuffer = LoadRenderTexture(192, 192); // Model loading Model model = LoadModel("resources/plane.obj"); // Load OBJ model model.material.maps[MAP_DIFFUSE].texture = LoadTexture("resources/plane_diffuse.png"); // Set map diffuse texture GenTextureMipmaps(&model.material.maps[MAP_DIFFUSE].texture); Camera camera = { 0 }; camera.position = new Vector3( 0.0f, 60.0f, -120.0f );;// Camera position perspective camera.target = new Vector3( 0.0f, 12.0f, 0.0f );; // Camera looking at point camera.up = new Vector3( 0.0f, 1.0f, 0.0f );; // Camera up vector (rotation towards target) camera.fovy = 30.0f; // Camera field-of-view Y camera.type = CAMERA_PERSPECTIVE; // Camera type float pitch = 0.0f; float roll = 0.0f; float yaw = 0.0f; SetTargetFPS(60); //-------------------------------------------------------------------------------------- while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // Plane roll (x-axis) controls if (IsKeyDown((int)Key.LEFT)) roll += 1.0f; else if (IsKeyDown((int)Key.RIGHT)) roll -= 1.0f; else { if (roll > 0.0f) roll -= 0.5f; else if (roll < 0.0f) roll += 0.5f; } // Plane yaw (y-axis) controls if (IsKeyDown((int)Key.S)) yaw += 1.0f; else if (IsKeyDown((int)Key.A)) yaw -= 1.0f; else { if (yaw > 0.0f) yaw -= 0.5f; else if (yaw < 0.0f) yaw += 0.5f; } // Plane pitch (z-axis) controls if (IsKeyDown((int)Key.DOWN)) pitch += 0.6f; else if (IsKeyDown((int)Key.UP)) pitch -= 0.6f; else { if (pitch > 0.3f) pitch -= 0.3f; else if (pitch < -0.3f) pitch += 0.3f; } // Wraps the phase of an angle to fit between -180 and +180 degrees int pitchOffset = pitch; while (pitchOffset > 180) pitchOffset -= 360; while (pitchOffset < -180) pitchOffset += 360; pitchOffset *= 10; Matrix transform = MatrixIdentity(); transform = MatrixMultiply(transform, MatrixRotateZ(DEG2RAD*roll)); transform = MatrixMultiply(transform, MatrixRotateX(DEG2RAD*pitch)); transform = MatrixMultiply(transform, MatrixRotateY(DEG2RAD*yaw)); model.transform = transform; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); // Draw framebuffer texture (Ahrs Display) int centerX = framebuffer.texture.width/2; int centerY = framebuffer.texture.height/2; float scaleFactor = 0.5f; BeginTextureMode(framebuffer); BeginBlendMode(BLEND_ALPHA); DrawTexturePro(texBackground, new Rectangle( 0, 0, texBackground.width, texBackground.height );, new Rectangle( centerX, centerY, texBackground.width*scaleFactor, texBackground.height*scaleFactor);, new Vector2( texBackground.width/2*scaleFactor, texBackground.height/2*scaleFactor + pitchOffset*scaleFactor );, roll, WHITE); DrawTexturePro(texPitch, new Rectangle( 0, 0, texPitch.width, texPitch.height );, new Rectangle( centerX, centerY, texPitch.width*scaleFactor, texPitch.height*scaleFactor );, new Vector2( texPitch.width/2*scaleFactor, texPitch.height/2*scaleFactor + pitchOffset*scaleFactor );, roll, WHITE); DrawTexturePro(texPlane, new Rectangle( 0, 0, texPlane.width, texPlane.height );, new Rectangle( centerX, centerY, texPlane.width*scaleFactor, texPlane.height*scaleFactor );, new Vector2( texPlane.width/2*scaleFactor, texPlane.height/2*scaleFactor );, 0, WHITE); EndBlendMode(); EndTextureMode(); // Draw 3D model (recomended to draw 3D always before 2D) BeginMode3D(camera); DrawModel(model, new Vector3( 0, 6.0f, 0 );, 1.0f, WHITE); // Draw 3d model with texture DrawGrid(10, 10.0f); EndMode3D(); // Draw 2D GUI stuff DrawAngleGauge(texAngleGauge, 80, 70, roll, "roll", RED); DrawAngleGauge(texAngleGauge, 190, 70, pitch, "pitch", GREEN); DrawAngleGauge(texAngleGauge, 300, 70, yaw, "yaw", SKYBLUE); DrawRectangle(30, 360, 260, 70, Fade(SKYBLUE, 0.5f)); DrawRectangleLines(30, 360, 260, 70, Fade(DARKBLUE, 0.5f)); DrawText("Pitch controlled with: (int)Key.UP / (int)Key.DOWN", 40, 370, 10, DARKGRAY); DrawText("Roll controlled with: (int)Key.LEFT / (int)Key.RIGHT", 40, 390, 10, DARKGRAY); DrawText("Yaw controlled with: (int)Key.A / (int)Key.S", 40, 410, 10, DARKGRAY); // Draw framebuffer texture DrawTextureRec(framebuffer.texture, new Rectangle( 0, 0, framebuffer.texture.width, -framebuffer.texture.height );, new Vector2( screenWidth - framebuffer.texture.width - 20, 20 );, Fade(WHITE, 0.8f)); DrawRectangleLines(screenWidth - framebuffer.texture.width - 20, 20, framebuffer.texture.width, framebuffer.texture.height, DARKGRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- // Unload all loaded data UnloadModel(model); UnloadRenderTexture(framebuffer); UnloadTexture(texAngleGauge); UnloadTexture(texBackground); UnloadTexture(texPitch); UnloadTexture(texPlane); CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } // Draw angle gauge controls void DrawAngleGauge(Texture2D angleGauge, int x, int y, float angle, char title[], Color color) { Rectangle srcRec = { 0, 0, angleGauge.width, angleGauge.height }; Rectangle dstRec = { x, y, angleGauge.width, angleGauge.height }; Vector2 origin = { angleGauge.width/2, angleGauge.height/2}; int textSize = 20; DrawTexturePro(angleGauge, srcRec, dstRec, origin, angle, color); DrawText(FormatText("%5.1f", angle), x - MeasureText(FormatText("%5.1f", angle), textSize) / 2, y + 10, textSize, DARKGRAY); DrawText(title, x - MeasureText(title, textSize) / 2, y + 60, textSize, DARKGRAY); } + /******************************************************************************************* * * raylib [models] example - Plane rotations (yaw, pitch, roll) * * This example has been created using raylib 1.8 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Example based on Berni work on Raspberry Pi: * http://forum.raylib.com/index.php?p=/discussion/124/line-versus-triangle-drawing-order * * Copyright (c) 2017 Ramon Santamaria (@raysan5) * ********************************************************************************************/ // Draw angle gauge controls //void DrawAngleGauge(Texture2D angleGauge, int x, int y, float angle, char title[], Color color); //---------------------------------------------------------------------------------- // Main entry point //---------------------------------------------------------------------------------- public static int Main() { // Initialization //-------------------------------------------------------------------------------------- const int screenWidth = 800; const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - plane rotations (yaw, pitch, roll)"); Texture2D texAngleGauge = LoadTexture("resources/angle_gauge.png"); Texture2D texBackground = LoadTexture("resources/background.png"); Texture2D texPitch = LoadTexture("resources/pitch.png"); Texture2D texPlane = LoadTexture("resources/plane.png"); RenderTexture2D framebuffer = LoadRenderTexture(192, 192); // Model loading Model model = LoadModel("resources/plane.obj"); // Load OBJ model model.material.maps[(int)MAP_ALBEDO].texture = LoadTexture("resources/plane_diffuse.png"); // Set map diffuse texture GenTextureMipmaps(ref model.material.maps[(int)MAP_ALBEDO].texture); Camera3D camera = new Camera3D(); camera.position = new Vector3( 0.0f, 60.0f, -120.0f );// Camera3D position perspective camera.target = new Vector3( 0.0f, 12.0f, 0.0f ); // Camera3D looking at point camera.up = new Vector3( 0.0f, 1.0f, 0.0f ); // Camera3D up vector (rotation towards target) camera.fovy = 30.0f; // Camera3D field-of-view Y camera.type = CAMERA_PERSPECTIVE; // Camera3D type float pitch = 0.0f; float roll = 0.0f; float yaw = 0.0f; SetTargetFPS(60); //-------------------------------------------------------------------------------------- while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // Plane roll (x-axis) controls if (IsKeyDown(KEY_LEFT)) roll += 1.0f; else if (IsKeyDown(KEY_RIGHT)) roll -= 1.0f; else { if (roll > 0.0f) roll -= 0.5f; else if (roll < 0.0f) roll += 0.5f; } // Plane yaw (y-axis) controls if (IsKeyDown(KEY_S)) yaw += 1.0f; else if (IsKeyDown(KEY_A)) yaw -= 1.0f; else { if (yaw > 0.0f) yaw -= 0.5f; else if (yaw < 0.0f) yaw += 0.5f; } // Plane pitch (z-axis) controls if (IsKeyDown(KEY_DOWN)) pitch += 0.6f; else if (IsKeyDown(KEY_UP)) pitch -= 0.6f; else { if (pitch > 0.3f) pitch -= 0.3f; else if (pitch < -0.3f) pitch += 0.3f; } // Wraps the phase of an angle to fit between -180 and +180 degrees int pitchOffset = (int)pitch; while (pitchOffset > 180) pitchOffset -= 360; while (pitchOffset < -180) pitchOffset += 360; pitchOffset *= 10; Matrix transform = MatrixIdentity(); transform = MatrixMultiply(transform, MatrixRotateZ(DEG2RAD*roll)); transform = MatrixMultiply(transform, MatrixRotateX(DEG2RAD*pitch)); transform = MatrixMultiply(transform, MatrixRotateY(DEG2RAD*yaw)); model.transform = transform; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); // Draw framebuffer texture (Ahrs Display) int centerX = framebuffer.texture.width/2; int centerY = framebuffer.texture.height/2; float scaleFactor = 0.5f; BeginTextureMode(framebuffer); BeginBlendMode((int)BLEND_ALPHA); DrawTexturePro(texBackground, new Rectangle( 0, 0, texBackground.width, texBackground.height ), new Rectangle( centerX, centerY, texBackground.width*scaleFactor, texBackground.height*scaleFactor), new Vector2( texBackground.width/2*scaleFactor, texBackground.height/2*scaleFactor + pitchOffset*scaleFactor ), roll, WHITE); DrawTexturePro(texPitch, new Rectangle( 0, 0, texPitch.width, texPitch.height ), new Rectangle( centerX, centerY, texPitch.width*scaleFactor, texPitch.height*scaleFactor ), new Vector2( texPitch.width/2*scaleFactor, texPitch.height/2*scaleFactor + pitchOffset*scaleFactor ), roll, WHITE); DrawTexturePro(texPlane, new Rectangle( 0, 0, texPlane.width, texPlane.height ), new Rectangle( centerX, centerY, texPlane.width*scaleFactor, texPlane.height*scaleFactor ), new Vector2( texPlane.width/2*scaleFactor, texPlane.height/2*scaleFactor ), 0, WHITE); EndBlendMode(); EndTextureMode(); // Draw 3D model (recomended to draw 3D always before 2D) BeginMode3D(camera); DrawModel(model, new Vector3( 0, 6.0f, 0 ), 1.0f, WHITE); // Draw 3d model with texture DrawGrid(10, 10.0f); EndMode3D(); // Draw 2D GUI stuff DrawAngleGauge(texAngleGauge, 80, 70, roll, "roll", RED); DrawAngleGauge(texAngleGauge, 190, 70, pitch, "pitch", GREEN); DrawAngleGauge(texAngleGauge, 300, 70, yaw, "yaw", SKYBLUE); DrawRectangle(30, 360, 260, 70, Fade(SKYBLUE, 0.5f)); DrawRectangleLines(30, 360, 260, 70, Fade(DARKBLUE, 0.5f)); DrawText("Pitch controlled with: KEY_UP / KEY_DOWN", 40, 370, 10, DARKGRAY); DrawText("Roll controlled with: KEY_LEFT / KEY_RIGHT", 40, 390, 10, DARKGRAY); DrawText("Yaw controlled with: KEY_A / KEY_S", 40, 410, 10, DARKGRAY); // Draw framebuffer texture DrawTextureRec(framebuffer.texture, new Rectangle( 0, 0, framebuffer.texture.width, -framebuffer.texture.height ), new Vector2( screenWidth - framebuffer.texture.width - 20, 20 ), Fade(WHITE, 0.8f)); DrawRectangleLines(screenWidth - framebuffer.texture.width - 20, 20, framebuffer.texture.width, framebuffer.texture.height, DARKGRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- // Unload all loaded data UnloadModel(model); UnloadRenderTexture(framebuffer); UnloadTexture(texAngleGauge); UnloadTexture(texBackground); UnloadTexture(texPitch); UnloadTexture(texPlane); CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } // Draw angle gauge controls static void DrawAngleGauge(Texture2D angleGauge, int x, int y, float angle, string title, Color color) { Rectangle srcRec = new Rectangle( 0, 0, angleGauge.width, angleGauge.height ); Rectangle dstRec = new Rectangle( x, y, angleGauge.width, angleGauge.height ); Vector2 origin = new Vector2( angleGauge.width/2, angleGauge.height/2); int textSize = 20; DrawTexturePro(angleGauge, srcRec, dstRec, origin, angle, color); DrawText(FormatText("%5.1f", angle), x - MeasureText(FormatText("%5.1f", angle), textSize) / 2, y + 10, textSize, DARKGRAY); DrawText(title, x - MeasureText(title, textSize) / 2, y + 60, textSize, DARKGRAY); } } diff --git a/Examples/others/audio_standalone.cs b/Examples/others/audio_standalone.cs deleted file mode 100644 index 664a8d9..0000000 --- a/Examples/others/audio_standalone.cs +++ /dev/null @@ -1,7 +0,0 @@ -using Raylib; -using static Raylib.Raylib; - -public partial class Examples -{ - /******************************************************************************************* * * raylib [audio] example - Using audio module as standalone module * * NOTE: This example does not require any graphic device, it can run directly on console. * * DEPENDENCIES: * mini_al.h - Audio device management lib (http://kcat.strangesoft.net/openal.html) * stb_vorbis.c - Ogg audio files loading (http://www.nothings.org/stb_vorbis/) * jar_xm.h - XM module file loading * jar_mod.h - MOD audio file loading * dr_flac.h - FLAC audio file loading * * COMPILATION: * gcc -c ..\..\src\external\mini_al.c -Wall -I. * gcc -o audio_standalone.exe audio_standalone.c ..\..\src\audio.c ..\..\src\external\stb_vorbis.c mini_al.o / * -I..\..\src -I..\..\src\external -L. -Wall -std=c99 / * -DAUDIO_STANDALONE -DSUPPORT_FILEFORMAT_WAV -DSUPPORT_FILEFORMAT_OGG * * LICENSE: zlib/libpng * * This example is 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-2018 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, including commercial * applications, and to alter it and redistribute it freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not claim that you * wrote the original software. If you use this software in a product, an acknowledgment * in the product documentation would be appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not be misrepresented * as being the original software. * * 3. This notice may not be removed or altered from any source distribution. * ********************************************************************************************/ #include // Windows only, no stardard library #else // Provide kbhit() function in non-Windows platforms // Check if a key has been pressed static int kbhit(void) { struct termios oldt, newt; int ch; int oldf; tcgetattr(STDIN_FILENO, &oldt); newt = oldt; newt.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &newt); oldf = fcntl(STDIN_FILENO, F_GETFL, 0); fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK); ch = getchar(); tcsetattr(STDIN_FILENO, TCSANOW, &oldt); fcntl(STDIN_FILENO, F_SETFL, oldf); if (ch != EOF) { ungetc(ch, stdin); return 1; } return 0; } // Get pressed character static char getch() { return getchar(); } public const #define (int)Key.ESCAPE 27 public static void Main() { // Initialization //-------------------------------------------------------------------------------------- static unsigned char key; InitAudioDevice(); Sound fxWav = LoadSound("resources/audio/weird.wav"); // Load WAV audio file Sound fxOgg = LoadSound("resources/audio/tanatana.ogg"); // Load OGG audio file IntPtr music = LoadMusicStream("resources/audio/guitar_noodling.ogg"); PlayMusicStream(music); printf("\nPress s or d to play sounds...\n"); //-------------------------------------------------------------------------------------- // Main loop while (key != (int)Key.ESCAPE) { if (kbhit()) key = getch(); if (key == 's') { PlaySound(fxWav); key = 0; } if (key == 'd') { PlaySound(fxOgg); key = 0; } UpdateMusicStream(music); } // De-Initialization //-------------------------------------------------------------------------------------- UnloadSound(fxWav); // Unload sound data UnloadSound(fxOgg); // Unload sound data UnloadMusicStream(music); // Unload music stream data CloseAudioDevice(); //-------------------------------------------------------------------------------------- return 0; } -} diff --git a/Examples/others/bunnymark.cs b/Examples/others/bunnymark.cs index 4fa6cce..7152bf6 100644 --- a/Examples/others/bunnymark.cs +++ b/Examples/others/bunnymark.cs @@ -1,7 +1,14 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class bunnymark { - /******************************************************************************************* * * raylib example - Bunnymark * * 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) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public const #define MAX_BUNNIES 100000 // 100K bunnies struct Bunny { public Vector2 position; public Vector2 speed; public Color color; public } Bunny; public static int bunnymark() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 1280; int screenHeight = 960; InitWindow(screenWidth, screenHeight, "raylib example - Bunnymark"); Texture2D texBunny = LoadTexture("resources/wabbit_alpha.png"); Bunny *bunnies = (Bunny *)malloc(MAX_BUNNIES*sizeof(Bunny)); // Bunnies array int bunniesCount = 0; // Bunnies counter SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) { // Create more bunnies for (int i = 0; i < 100; i++) { bunnies[bunniesCount].position = GetMousePosition(); bunnies[bunniesCount].speed.x = (float)GetRandomValue(250, 500)/60.0f; bunnies[bunniesCount].speed.y = (float)(GetRandomValue(250, 500) - 500)/60.0f; bunniesCount++; } } // Update bunnies for (int i = 0; i < bunniesCount; i++) { bunnies[i].position.x += bunnies[i].speed.x; bunnies[i].position.y += bunnies[i].speed.y; if ((bunnies[i].position.x > GetScreenWidth()) || (bunnies[i].position.x < 0)) bunnies[i].speed.x *= -1; if ((bunnies[i].position.y > GetScreenHeight()) || (bunnies[i].position.y < 0)) bunnies[i].speed.y *= -1; } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); for (int i = 0; i < bunniesCount; i++) { // NOTE: When internal QUADS batch limit is reached, a draw call is launched and // batching buffer starts being filled again; before launching the draw call, // updated vertex data from internal buffer is send to GPU... it seems it generates // a stall and consequently a frame drop, limiting number of bunnies drawn at 60 fps DrawTexture(texBunny, bunnies[i].position.x, bunnies[i].position.y, RAYWHITE); } DrawRectangle(0, 0, screenWidth, 40, LIGHTGRAY); DrawText("raylib bunnymark", 10, 10, 20, DARKGRAY); DrawText(FormatText("bunnies: %i", bunniesCount), 400, 10, 20, RED); DrawFPS(260, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- free(bunnies); CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib example - Bunnymark * * 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) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public const int MAX_BUNNIES = 100000; + + struct Bunny { + public Vector2 position; public Vector2 speed; public Color color; } public static int Main() { + // Initialization + //-------------------------------------------------------------------------------------- + int screenWidth = 1280; int screenHeight = 960; InitWindow(screenWidth, screenHeight, "raylib example - Bunnymark"); Texture2D texBunny = LoadTexture("resources/wabbit_alpha.png"); Bunny[] bunnies = new Bunny[MAX_BUNNIES]; // Bunnies array int bunniesCount = 0; // Bunnies counter SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) { // Create more bunnies for (int i = 0; i < 100; i++) { bunnies[bunniesCount].position = GetMousePosition(); bunnies[bunniesCount].speed.x = (float)GetRandomValue(250, 500)/60.0f; bunnies[bunniesCount].speed.y = (float)(GetRandomValue(250, 500) - 500)/60.0f; bunniesCount++; } } // Update bunnies for (int i = 0; i < bunniesCount; i++) { bunnies[i].position.x += bunnies[i].speed.x; bunnies[i].position.y += bunnies[i].speed.y; if ((bunnies[i].position.x > GetScreenWidth()) || (bunnies[i].position.x < 0)) bunnies[i].speed.x *= -1; if ((bunnies[i].position.y > GetScreenHeight()) || (bunnies[i].position.y < 0)) bunnies[i].speed.y *= -1; } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); for (int i = 0; i < bunniesCount; i++) { // NOTE: When internal QUADS batch limit is reached, a draw call is launched and // batching buffer starts being filled again; before launching the draw call, // updated vertex data from internal buffer is send to GPU... it seems it generates // a stall and consequently a frame drop, limiting number of bunnies drawn at 60 fps DrawTexture(texBunny, (int)bunnies[i].position.x, (int)bunnies[i].position.y, RAYWHITE); } DrawRectangle(0, 0, screenWidth, 40, LIGHTGRAY); DrawText("raylib bunnymark", 10, 10, 20, DARKGRAY); // DrawText(FormatText("bunnies: %i", bunniesCount), 400, 10, 20, RED); + DrawText($"bunnies: {bunniesCount}", 400, 10, 20, RED); DrawFPS(260, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/others/resources/wabbit_alpha.png b/Examples/others/resources/wabbit_alpha.png new file mode 100644 index 0000000000000000000000000000000000000000..79c31675083b7ffc272a6370bc189360bde484d0 GIT binary patch literal 449 zcmeAS@N?(olHy`uVBq!ia0y~yV31;9U{K{?V_;y2N&C5tfq_A?#5JNMI6tkVJh3R1 z!7(L2DOJHUH!(dmC^a#qvhZZ84FdyXvZsqe1NMU zf!pr@=MFfy&0{anLP4>r9R+pSN*u}1}x^V55-3)98*YHU^xz^8E z{zuQa>cFxR*JXb50$9_krz@2PJ_tGT@|otPPX9J(#jVv02Yb)2dc~k}lOwtI%A1lm z@5C4n#_mwM%C*8qK_m9+8Mdm)2ao=cbu@@KbeVQft*a-d%z=?N scale -> translate) rlTranslatef(position.x, position.y, position.z); //rlScalef(2.0f, 2.0f, 2.0f); //rlRotatef(45, 0, 1, 0); rlBegin(RL_TRIANGLES); rlColor4ub(color.r, color.g, color.b, color.a); // Front Face ----------------------------------------------------- rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Right rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right // Back Face ------------------------------------------------------ rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Left rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left // Top Face ------------------------------------------------------- rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left rlVertex3f(x-width/2, y+height/2, z+length/2); // Bottom Left rlVertex3f(x+width/2, y+height/2, z+length/2); // Bottom Right rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left rlVertex3f(x+width/2, y+height/2, z+length/2); // Bottom Right // Bottom Face ---------------------------------------------------- rlVertex3f(x-width/2, y-height/2, z-length/2); // Top Left rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left rlVertex3f(x+width/2, y-height/2, z-length/2); // Top Right rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right rlVertex3f(x-width/2, y-height/2, z-length/2); // Top Left // Right face ----------------------------------------------------- rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Left rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Left rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Left // Left Face ------------------------------------------------------ rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Right rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Right rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Right rlEnd(); rlPopMatrix(); } // Draw cube wires void DrawCubeWires(Vector3 position, float width, float height, float length, Color color) { float x = 0.0f; float y = 0.0f; float z = 0.0f; rlPushMatrix(); rlTranslatef(position.x, position.y, position.z); //rlRotatef(45, 0, 1, 0); rlBegin(RL_LINES); rlColor4ub(color.r, color.g, color.b, color.a); // Front Face ----------------------------------------------------- // Bottom Line rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right // Left Line rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Right // Top Line rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Right rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left // Right Line rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left // Back Face ------------------------------------------------------ // Bottom Line rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Left rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right // Left Line rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right // Top Line rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left // Right Line rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Left // Top Face ------------------------------------------------------- // Left Line rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left Front rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left Back // Right Line rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Right Front rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right Back // Bottom Face --------------------------------------------------- // Left Line rlVertex3f(x-width/2, y-height/2, z+length/2); // Top Left Front rlVertex3f(x-width/2, y-height/2, z-length/2); // Top Left Back // Right Line rlVertex3f(x+width/2, y-height/2, z+length/2); // Top Right Front rlVertex3f(x+width/2, y-height/2, z-length/2); // Top Right Back rlEnd(); rlPopMatrix(); } -} diff --git a/Examples/others/standard_lighting.cs b/Examples/others/standard_lighting.cs deleted file mode 100644 index 40a2d94..0000000 --- a/Examples/others/standard_lighting.cs +++ /dev/null @@ -1,7 +0,0 @@ -using Raylib; -using static Raylib.Raylib; - -public partial class Examples -{ - /******************************************************************************************* * * raylib [shaders] example - Standard lighting (materials and lights) * * NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, * OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. * * NOTE: Shaders used in this example are #version 330 (OpenGL 3.3), to test this example * on OpenGL ES 2.0 platforms (Android, Raspberry Pi, HTML5), use #version 100 shaders * raylib comes with shaders ready for both versions, check raylib/shaders install folder * * This example has been created using raylib 1.7 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2016-2017 Ramon Santamaria (@raysan5) * ********************************************************************************************/ //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- public const #define MAX_LIGHTS 8 // Max lights supported by standard shader //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- // Light type struct LightData,*Light { public unsigned int id; // Light unique id public bool enabled; // Light enabled public int type; // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT public public Vector3 position; // Light position public Vector3 target; // Light direction: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target) public float radius; // Light attenuation radius light intensity reduced with distance (world distance) public public Color diffuse; // Light diffuse color public float intensity; // Light intensity level public public float coneAngle; // Light cone max angle: LIGHT_SPOT public } LightData, *Light; // Light types typedef enum { LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT } LightType; //---------------------------------------------------------------------------------- // Global Variables Definition //---------------------------------------------------------------------------------- static Light[] lights = new Light[MAX_LIGHTS]; // Lights pool static int lightsCount = 0; // Enabled lights counter static int[] lightsLocs = new int[MAX_LIGHTS][8]; // Lights location points in shader: 8 possible points per light: // enabled, type, position, target, radius, diffuse, intensity, coneAngle //---------------------------------------------------------------------------------- // Module Functions Declaration //---------------------------------------------------------------------------------- static Light CreateLight(int type, Vector3 position, Color diffuse); // Create a new light, initialize it and add to pool static void DestroyLight(Light light); // Destroy a light and take it out of the list static void DrawLight(Light light); // Draw light in 3D world static void GetShaderLightsLocations(Shader shader); // Get shader locations for lights (up to MAX_LIGHTS) static void SetShaderLightsValues(Shader shader); // Set shader uniform values for lights // Vector3 math functions static float VectorLength(const Vector3 v); // Calculate vector length static void VectorNormalize(Vector3 *v); // Normalize provided vector static Vector3 VectorSubtract(Vector3 v1, Vector3 v2); // Substract two vectors //https://www.gamedev.net/topic/655969-speed-gluniform-vs-uniform-buffer-objects/ //https://www.reddit.com/r/opengl/comments/4ri20g/is_gluniform_more_expensive_than_glprogramuniform/ //http://cg.alexandra.dk/?p=3778 - AZDO //https://developer.apple.com/library/content/documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/BestPracticesforShaders/BestPracticesforShaders.html //------------------------------------------------------------------------------------ // Program main entry point //------------------------------------------------------------------------------------ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; SetConfigFlags((int)Flag.MSAA_4X_HINT); // Enable Multi Sampling Anti Aliasing 4x (if available) InitWindow(screenWidth, screenHeight, "raylib [shaders] example - model shader"); // Define the camera to look into our 3d world Camera camera = {{ 4.0f, 4.0f, 4.0f }, { 0.0f, 1.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f }; Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position Model dwarf = LoadModel("resources/model/dwarf.obj"); // Load OBJ model Material material;// = LoadStandardMaterial(); material.shader = LoadShader("resources/shaders/glsl330/standard.vs", "resources/shaders/glsl330/standard.fs"); // Try to get lights location points (if available) GetShaderLightsLocations(material.shader); material.maps[MAP_DIFFUSE].texture = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model diffuse texture material.maps[MAP_NORMAL].texture = LoadTexture("resources/model/dwarf_normal.png"); // Load model normal texture material.maps[MAP_SPECULAR].texture = LoadTexture("resources/model/dwarf_specular.png"); // Load model specular texture material.maps[MAP_DIFFUSE].color = WHITE; material.maps[MAP_SPECULAR].color = WHITE; dwarf.material = material; // Apply material to model Light spotLight = CreateLight(LIGHT_SPOT, new Vector3(3.0f, 5.0f, 2.0f}, (Color){255, 255, 255, 255);); spotLight->target = new Vector3(0.0f, 0.0f, 0.0f);; spotLight->intensity = 2.0f; spotLight->diffuse = new Color(255, 100, 100, 255);; spotLight->coneAngle = 60.0f; Light dirLight = CreateLight(LIGHT_DIRECTIONAL, new Vector3(0.0f, -3.0f, -3.0f}, (Color){255, 255, 255, 255);); dirLight->target = new Vector3(1.0f, -2.0f, -2.0f);; dirLight->intensity = 2.0f; dirLight->diffuse = new Color(100, 255, 100, 255);; Light pointLight = CreateLight(LIGHT_POINT, new Vector3(0.0f, 4.0f, 5.0f}, (Color){255, 255, 255, 255);); pointLight->intensity = 2.0f; pointLight->diffuse = new Color(100, 100, 255, 255);; pointLight->radius = 3.0f; // Set shader lights values for enabled lights // NOTE: If values are not changed in real time, they can be set at initialization!!! SetShaderLightsValues(material.shader); //SetShaderActive(0); // Setup orbital camera SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateCamera(&camera); // Update camera //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode3D(camera); DrawModel(dwarf, position, 2.0f, WHITE); // Draw 3d model with texture DrawLight(spotLight); // Draw spot light DrawLight(dirLight); // Draw directional light DrawLight(pointLight); // Draw point light DrawGrid(10, 1.0f); // Draw a grid EndMode3D(); DrawText("(c) Dwarf 3D model by David Moreno", screenWidth - 200, screenHeight - 20, 10, GRAY); DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadMaterial(material); // Unload material and assigned textures UnloadModel(dwarf); // Unload model // Destroy all created lights DestroyLight(pointLight); DestroyLight(dirLight); DestroyLight(spotLight); // Unload lights if (lightsCount > 0) { for (int i = 0; i < lightsCount; i++) free(lights[i]); lightsCount = 0; } CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } //-------------------------------------------------------------------------------------------- // Module Functions Definitions //-------------------------------------------------------------------------------------------- // Create a new light, initialize it and add to pool Light CreateLight(int type, Vector3 position, Color diffuse) { Light light = NULL; if (lightsCount < MAX_LIGHTS) { // Allocate dynamic memory light = (Light)malloc(sizeof(LightData)); // Initialize light values with generic values light->id = lightsCount; light->type = type; light->enabled = true; light->position = position; light->target = new Vector3( 0.0f, 0.0f, 0.0f );; light->intensity = 1.0f; light->diffuse = diffuse; // Add new light to the array lights[lightsCount] = light; // Increase enabled lights count lightsCount++; } else { // NOTE: Returning latest created light to avoid crashes light = lights[lightsCount]; } return light; } // Destroy a light and take it out of the list void DestroyLight(Light light) { if (light != NULL) { int lightId = light->id; // Free dynamic memory allocation free(lights[lightId]); // Remove *obj from the pointers array for (int i = lightId; i < lightsCount; i++) { // Resort all the following pointers of the array if ((i + 1) < lightsCount) { lights[i] = lights[i + 1]; lights[i]->id = lights[i + 1]->id; } } // Decrease enabled physic objects count lightsCount--; } } // Draw light in 3D world void DrawLight(Light light) { switch (light->type) { case LIGHT_POINT: { DrawSphereWires(light->position, 0.3f*light->intensity, 8, 8, (light->enabled ? light->diffuse : GRAY)); DrawCircle3D(light->position, light->radius, new Vector3( 0, 0, 0 );, 0.0f, (light->enabled ? light->diffuse : GRAY)); DrawCircle3D(light->position, light->radius, new Vector3( 1, 0, 0 );, 90.0f, (light->enabled ? light->diffuse : GRAY)); DrawCircle3D(light->position, light->radius, new Vector3( 0, 1, 0 );,90.0f, (light->enabled ? light->diffuse : GRAY)); } break; case LIGHT_DIRECTIONAL: { DrawLine3D(light->position, light->target, (light->enabled ? light->diffuse : GRAY)); DrawSphereWires(light->position, 0.3f*light->intensity, 8, 8, (light->enabled ? light->diffuse : GRAY)); DrawCubeWires(light->target, 0.3f, 0.3f, 0.3f, (light->enabled ? light->diffuse : GRAY)); } break; case LIGHT_SPOT: { DrawLine3D(light->position, light->target, (light->enabled ? light->diffuse : GRAY)); Vector3 dir = VectorSubtract(light->target, light->position); VectorNormalize(&dir); DrawCircle3D(light->position, 0.5f, dir, 0.0f, (light->enabled ? light->diffuse : GRAY)); //DrawCylinderWires(light->position, 0.0f, 0.3f*light->coneAngle/50, 0.6f, 5, (light->enabled ? light->diffuse : GRAY)); DrawCubeWires(light->target, 0.3f, 0.3f, 0.3f, (light->enabled ? light->diffuse : GRAY)); } break; default: break; } } // Get shader locations for lights (up to MAX_LIGHTS) static void GetShaderLightsLocations(Shader shader) { char locName[32] = "lights[x].\0"; char[] locNameUpdated = new char[64]; for (int i = 0; i < MAX_LIGHTS; i++) { locName[7] = '0' + i; strcpy(locNameUpdated, locName); strcat(locNameUpdated, "enabled\0"); lightsLocs[i][0] = GetShaderLocation(shader, locNameUpdated); locNameUpdated[0] = '\0'; strcpy(locNameUpdated, locName); strcat(locNameUpdated, "type\0"); lightsLocs[i][1] = GetShaderLocation(shader, locNameUpdated); locNameUpdated[0] = '\0'; strcpy(locNameUpdated, locName); strcat(locNameUpdated, "position\0"); lightsLocs[i][2] = GetShaderLocation(shader, locNameUpdated); locNameUpdated[0] = '\0'; strcpy(locNameUpdated, locName); strcat(locNameUpdated, "direction\0"); lightsLocs[i][3] = GetShaderLocation(shader, locNameUpdated); locNameUpdated[0] = '\0'; strcpy(locNameUpdated, locName); strcat(locNameUpdated, "radius\0"); lightsLocs[i][4] = GetShaderLocation(shader, locNameUpdated); locNameUpdated[0] = '\0'; strcpy(locNameUpdated, locName); strcat(locNameUpdated, "diffuse\0"); lightsLocs[i][5] = GetShaderLocation(shader, locNameUpdated); locNameUpdated[0] = '\0'; strcpy(locNameUpdated, locName); strcat(locNameUpdated, "intensity\0"); lightsLocs[i][6] = GetShaderLocation(shader, locNameUpdated); locNameUpdated[0] = '\0'; strcpy(locNameUpdated, locName); strcat(locNameUpdated, "coneAngle\0"); lightsLocs[i][7] = GetShaderLocation(shader, locNameUpdated); } } // Set shader uniform values for lights // NOTE: It would be far easier with shader UBOs but are not supported on OpenGL ES 2.0 // TODO: Replace glUniform1i(), glUniform1f(), glUniform3f(), glUniform4f(): //SetShaderValue(Shader shader, int uniformLoc, float *value, int size) //SetShaderValuei(Shader shader, int uniformLoc, int *value, int size) static void SetShaderLightsValues(Shader shader) { int tempInt[8] = { 0 }; float tempFloat[8] = { 0.0f }; for (int i = 0; i < MAX_LIGHTS; i++) { if (i < lightsCount) { tempInt[0] = lights[i]->enabled; SetShaderValuei(shader, lightsLocs[i][0], tempInt, 1); //glUniform1i(lightsLocs[i][0], lights[i]->enabled); tempInt[0] = lights[i]->type; SetShaderValuei(shader, lightsLocs[i][1], tempInt, 1); //glUniform1i(lightsLocs[i][1], lights[i]->type); tempFloat[0] = (float)lights[i]->diffuse.r/255.0f; tempFloat[1] = (float)lights[i]->diffuse.g/255.0f; tempFloat[2] = (float)lights[i]->diffuse.b/255.0f; tempFloat[3] = (float)lights[i]->diffuse.a/255.0f; SetShaderValue(shader, lightsLocs[i][5], tempFloat, 4); //glUniform4f(lightsLocs[i][5], (float)lights[i]->diffuse.r/255, (float)lights[i]->diffuse.g/255, (float)lights[i]->diffuse.b/255, (float)lights[i]->diffuse.a/255); tempFloat[0] = lights[i]->intensity; SetShaderValue(shader, lightsLocs[i][6], tempFloat, 1); switch (lights[i]->type) { case LIGHT_POINT: { tempFloat[0] = lights[i]->position.x; tempFloat[1] = lights[i]->position.y; tempFloat[2] = lights[i]->position.z; SetShaderValue(shader, lightsLocs[i][2], tempFloat, 3); tempFloat[0] = lights[i]->radius; SetShaderValue(shader, lightsLocs[i][4], tempFloat, 1); //glUniform3f(lightsLocs[i][2], lights[i]->position.x, lights[i]->position.y, lights[i]->position.z); //glUniform1f(lightsLocs[i][4], lights[i]->radius); } break; case LIGHT_DIRECTIONAL: { Vector3 direction = VectorSubtract(lights[i]->target, lights[i]->position); VectorNormalize(&direction); tempFloat[0] = direction.x; tempFloat[1] = direction.y; tempFloat[2] = direction.z; SetShaderValue(shader, lightsLocs[i][3], tempFloat, 3); //glUniform3f(lightsLocs[i][3], direction.x, direction.y, direction.z); } break; case LIGHT_SPOT: { tempFloat[0] = lights[i]->position.x; tempFloat[1] = lights[i]->position.y; tempFloat[2] = lights[i]->position.z; SetShaderValue(shader, lightsLocs[i][2], tempFloat, 3); //glUniform3f(lightsLocs[i][2], lights[i]->position.x, lights[i]->position.y, lights[i]->position.z); Vector3 direction = VectorSubtract(lights[i]->target, lights[i]->position); VectorNormalize(&direction); tempFloat[0] = direction.x; tempFloat[1] = direction.y; tempFloat[2] = direction.z; SetShaderValue(shader, lightsLocs[i][3], tempFloat, 3); //glUniform3f(lightsLocs[i][3], direction.x, direction.y, direction.z); tempFloat[0] = lights[i]->coneAngle; SetShaderValue(shader, lightsLocs[i][7], tempFloat, 1); //glUniform1f(lightsLocs[i][7], lights[i]->coneAngle); } break; default: break; } } else { tempInt[0] = 0; SetShaderValuei(shader, lightsLocs[i][0], tempInt, 1); //glUniform1i(lightsLocs[i][0], 0); // Light disabled } } } // Calculate vector length float VectorLength(const Vector3 v) { float length; length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z); return length; } // Normalize provided vector void VectorNormalize(Vector3 *v) { float length, ilength; length = VectorLength(*v); if (length == 0.0f) length = 1.0f; ilength = 1.0f/length; v->x *= ilength; v->y *= ilength; v->z *= ilength; } // Substract two vectors Vector3 VectorSubtract(Vector3 v1, Vector3 v2) { Vector3 result; result.x = v1.x - v2.x; result.y = v1.y - v2.y; result.z = v1.z - v2.z; return result; } -} diff --git a/Examples/physac/physics_demo.cs b/Examples/physac/physics_demo.cs index 1b7c5bb..6d56111 100644 --- a/Examples/physac/physics_demo.cs +++ b/Examples/physac/physics_demo.cs @@ -1,7 +1,7 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class physics_demo { - /******************************************************************************************* * * Physac - Physics demo * * NOTE 1: Physac requires multi-threading, when InitPhysics() a second thread is created to manage physics calculations. * NOTE 2: Physac requires static C library linkage to avoid dependency on MinGW DLL (-static -lpthread) * * Use the following line to compile: * * gcc -o $(NAME_PART).exe $(FILE_NAME) -s $(RAYLIB_DIR)\raylib\raylib.rc.o -static -lraylib -lpthread * -lglfw3 -lopengl32 -lgdi32 -lopenal32 -lwinmm -std=c99 -Wl,--subsystem,windows -Wl,-allow-multiple-definition * * Copyright (c) 2016-2018 Victor Fisac * ********************************************************************************************/ public const #define PHYSAC_IMPLEMENTATION public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; SetConfigFlags((int)Flag.MSAA_4X_HINT); InitWindow(screenWidth, screenHeight, "Physac [raylib] - Physics demo"); // Physac logo drawing position int logoX = screenWidth - MeasureText("Physac", 30) - 10; int logoY = 15; bool needsReset = false; // Initialize physics and default physics bodies InitPhysics(); // Create floor rectangle physics body PhysicsBody floor = CreatePhysicsBodyRectangle(new Vector2( screenWidth/2, screenHeight );, 500, 100, 10); floor->enabled = false; // Disable body state to convert it to static (no dynamics, but collisions) // Create obstacle circle physics body PhysicsBody circle = CreatePhysicsBodyCircle(new Vector2( screenWidth/2, screenHeight/2 );, 45, 10); circle->enabled = false; // Disable body state to convert it to static (no dynamics, but collisions) SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // Delay initialization of variables due to physics reset async if (needsReset) { floor = CreatePhysicsBodyRectangle(new Vector2( screenWidth/2, screenHeight );, 500, 100, 10); floor->enabled = false; circle = CreatePhysicsBodyCircle(new Vector2( screenWidth/2, screenHeight/2 );, 45, 10); circle->enabled = false; } // Reset physics input if (IsKeyPressed('R')) { ResetPhysics(); needsReset = true; } // Physics body creation inputs if (IsMouseButtonPressed((int)Mouse.LEFT_BUTTON)) CreatePhysicsBodyPolygon(GetMousePosition(), GetRandomValue(20, 80), GetRandomValue(3, 8), 10); else if (IsMouseButtonPressed((int)Mouse.RIGHT_BUTTON)) CreatePhysicsBodyCircle(GetMousePosition(), GetRandomValue(10, 45), 10); // Destroy falling physics bodies int bodiesCount = GetPhysicsBodiesCount(); for (int i = bodiesCount - 1; i >= 0; i--) { PhysicsBody body = GetPhysicsBody(i); if (body != NULL && (body->position.y > screenHeight*2)) DestroyPhysicsBody(body); } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(BLACK); DrawFPS(screenWidth - 90, screenHeight - 30); // Draw created physics bodies bodiesCount = GetPhysicsBodiesCount(); for (int i = 0; i < bodiesCount; i++) { PhysicsBody body = GetPhysicsBody(i); if (body != NULL) { int vertexCount = GetPhysicsShapeVerticesCount(i); for (int j = 0; j < vertexCount; j++) { // Get physics bodies shape vertices to draw lines // Note: GetPhysicsShapeVertex() already calculates rotation transformations Vector2 vertexA = GetPhysicsShapeVertex(body, j); int jj = (((j + 1) < vertexCount) ? (j + 1) : 0); // Get next vertex or first to close the shape Vector2 vertexB = GetPhysicsShapeVertex(body, jj); DrawLineV(vertexA, vertexB, GREEN); // Draw a line between two vertex positions } } } DrawText("Left mouse button to create a polygon", 10, 10, 10, WHITE); DrawText("Right mouse button to create a circle", 10, 25, 10, WHITE); DrawText("Press 'R' to reset example", 10, 40, 10, WHITE); DrawText("Physac", logoX, logoY, 30, WHITE); DrawText("Powered by", logoX + 50, logoY - 7, 10, WHITE); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- ClosePhysics(); // Unitialize physics CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * Physac - Physics demo * * NOTE 1: Physac requires multi-threading, when InitPhysics() a second thread is created to manage physics calculations. * NOTE 2: Physac requires static C library linkage to avoid dependency on MinGW DLL (-static -lpthread) * * Use the following line to compile: * * gcc -o $(NAME_PART).exe $(FILE_NAME) -s $(RAYLIB_DIR)\raylib\raylib.rc.o -static -lraylib -lpthread * -lglfw3 -lopengl32 -lgdi32 -lopenal32 -lwinmm -std=c99 -Wl,--subsystem,windows -Wl,-allow-multiple-definition * * Copyright (c) 2016-2018 Victor Fisac * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; SetConfigFlags(FLAG_MSAA_4X_HINT); InitWindow(screenWidth, screenHeight, "Physac [raylib] - Physics demo"); // Physac logo drawing position int logoX = screenWidth - MeasureText("Physac", 30) - 10; int logoY = 15; bool needsReset = false; // Initialize physics and default physics bodies InitPhysics(); // Create floor rectangle physics body var floor = CreatePhysicsBodyRectangle(new Vector2( screenWidth/2, screenHeight ), 500, 100, 10); floor.enabled = false; // Disable body state to convert it to static (no dynamics, but collisions) // Create obstacle circle physics body var circle = CreatePhysicsBodyCircle(new Vector2( screenWidth/2, screenHeight/2 ), 45, 10); circle.enabled = false; // Disable body state to convert it to static (no dynamics, but collisions) SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // Delay initialization of variables due to physics reset async if (needsReset) { floor = CreatePhysicsBodyRectangle(new Vector2( screenWidth/2, screenHeight ), 500, 100, 10); floor.enabled = false; circle = CreatePhysicsBodyCircle(new Vector2( screenWidth/2, screenHeight/2 ), 45, 10); circle.enabled = false; } // Reset physics input if (IsKeyPressed('R')) { ResetPhysics(); needsReset = true; } // Physics body creation inputs if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) CreatePhysicsBodyPolygon(GetMousePosition(), GetRandomValue(20, 80), GetRandomValue(3, 8), 10); else if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)) CreatePhysicsBodyCircle(GetMousePosition(), GetRandomValue(10, 45), 10); // Destroy falling physics bodies int bodiesCount = GetPhysicsBodiesCount(); for (int i = bodiesCount - 1; i >= 0; i--) { var body = GetPhysicsBody(i); if (body.id != 0 && (body.position.y > screenHeight*2)) DestroyPhysicsBody(body); } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(BLACK); DrawFPS(screenWidth - 90, screenHeight - 30); // Draw created physics bodies bodiesCount = GetPhysicsBodiesCount(); for (int i = 0; i < bodiesCount; i++) { var body = GetPhysicsBody(i); if (body.id != 0) // can't check struct for null { int vertexCount = GetPhysicsShapeVerticesCount(i); for (int j = 0; j < vertexCount; j++) { // Get physics bodies shape vertices to draw lines // Note: GetPhysicsShapeVertex() already calculates rotation transformations Vector2 vertexA = GetPhysicsShapeVertex(body, j); int jj = (((j + 1) < vertexCount) ? (j + 1) : 0); // Get next vertex or first to close the shape Vector2 vertexB = GetPhysicsShapeVertex(body, jj); DrawLineV(vertexA, vertexB, GREEN); // Draw a line between two vertex positions } } } DrawText("Left mouse button to create a polygon", 10, 10, 10, WHITE); DrawText("Right mouse button to create a circle", 10, 25, 10, WHITE); DrawText("Press 'R' to reset example", 10, 40, 10, WHITE); DrawText("Physac", logoX, logoY, 30, WHITE); DrawText("Powered by", logoX + 50, logoY - 7, 10, WHITE); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- ClosePhysics(); // Unitialize physics CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/physac/physics_friction.cs b/Examples/physac/physics_friction.cs index a761d66..0ee20c4 100644 --- a/Examples/physac/physics_friction.cs +++ b/Examples/physac/physics_friction.cs @@ -1,7 +1,7 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class physics_friction { - /******************************************************************************************* * * Physac - Physics friction * * NOTE 1: Physac requires multi-threading, when InitPhysics() a second thread is created to manage physics calculations. * NOTE 2: Physac requires static C library linkage to avoid dependency on MinGW DLL (-static -lpthread) * * Use the following line to compile: * * gcc -o $(NAME_PART).exe $(FILE_NAME) -s $(RAYLIB_DIR)\raylib\raylib.rc.o -static -lraylib -lpthread * -lglfw3 -lopengl32 -lgdi32 -lopenal32 -lwinmm -std=c99 -Wl,--subsystem,windows -Wl,-allow-multiple-definition * * Copyright (c) 2016-2018 Victor Fisac * ********************************************************************************************/ public const #define PHYSAC_IMPLEMENTATION public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; SetConfigFlags((int)Flag.MSAA_4X_HINT); InitWindow(screenWidth, screenHeight, "Physac [raylib] - Physics friction"); // Physac logo drawing position int logoX = screenWidth - MeasureText("Physac", 30) - 10; int logoY = 15; // Initialize physics and default physics bodies InitPhysics(); // Create floor rectangle physics body PhysicsBody floor = CreatePhysicsBodyRectangle(new Vector2( screenWidth/2, screenHeight );, screenWidth, 100, 10); floor->enabled = false; // Disable body state to convert it to static (no dynamics, but collisions) PhysicsBody wall = CreatePhysicsBodyRectangle(new Vector2( screenWidth/2, screenHeight*0.8f );, 10, 80, 10); wall->enabled = false; // Disable body state to convert it to static (no dynamics, but collisions) // Create left ramp physics body PhysicsBody rectLeft = CreatePhysicsBodyRectangle(new Vector2( 25, screenHeight - 5 );, 250, 250, 10); rectLeft->enabled = false; // Disable body state to convert it to static (no dynamics, but collisions) SetPhysicsBodyRotation(rectLeft, 30*DEG2RAD); // Create right ramp physics body PhysicsBody rectRight = CreatePhysicsBodyRectangle(new Vector2( screenWidth - 25, screenHeight - 5 );, 250, 250, 10); rectRight->enabled = false; // Disable body state to convert it to static (no dynamics, but collisions) SetPhysicsBodyRotation(rectRight, 330*DEG2RAD); // Create dynamic physics bodies PhysicsBody bodyA = CreatePhysicsBodyRectangle(new Vector2( 35, screenHeight*0.6f );, 40, 40, 10); bodyA->staticFriction = 0.1f; bodyA->dynamicFriction = 0.1f; SetPhysicsBodyRotation(bodyA, 30*DEG2RAD); PhysicsBody bodyB = CreatePhysicsBodyRectangle(new Vector2( screenWidth - 35, screenHeight*0.6f );, 40, 40, 10); bodyB->staticFriction = 1; bodyB->dynamicFriction = 1; SetPhysicsBodyRotation(bodyB, 330*DEG2RAD); SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (IsKeyPressed('R')) // Reset physics input { // Reset dynamic physics bodies position, velocity and rotation bodyA->position = new Vector2( 35, screenHeight*0.6f );; bodyA->velocity = new Vector2( 0, 0 );; bodyA->angularVelocity = 0; SetPhysicsBodyRotation(bodyA, 30*DEG2RAD); bodyB->position = new Vector2( screenWidth - 35, screenHeight*0.6f );; bodyB->velocity = new Vector2( 0, 0 );; bodyB->angularVelocity = 0; SetPhysicsBodyRotation(bodyB, 330*DEG2RAD); } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(BLACK); DrawFPS(screenWidth - 90, screenHeight - 30); // Draw created physics bodies int bodiesCount = GetPhysicsBodiesCount(); for (int i = 0; i < bodiesCount; i++) { PhysicsBody body = GetPhysicsBody(i); if (body != NULL) { int vertexCount = GetPhysicsShapeVerticesCount(i); for (int j = 0; j < vertexCount; j++) { // Get physics bodies shape vertices to draw lines // Note: GetPhysicsShapeVertex() already calculates rotation transformations Vector2 vertexA = GetPhysicsShapeVertex(body, j); int jj = (((j + 1) < vertexCount) ? (j + 1) : 0); // Get next vertex or first to close the shape Vector2 vertexB = GetPhysicsShapeVertex(body, jj); DrawLineV(vertexA, vertexB, GREEN); // Draw a line between two vertex positions } } } DrawRectangle(0, screenHeight - 49, screenWidth, 49, BLACK); DrawText("Friction amount", (screenWidth - MeasureText("Friction amount", 30))/2, 75, 30, WHITE); DrawText("0.1", bodyA->position.x - MeasureText("0.1", 20)/2, bodyA->position.y - 7, 20, WHITE); DrawText("1", bodyB->position.x - MeasureText("1", 20)/2, bodyB->position.y - 7, 20, WHITE); DrawText("Press 'R' to reset example", 10, 10, 10, WHITE); DrawText("Physac", logoX, logoY, 30, WHITE); DrawText("Powered by", logoX + 50, logoY - 7, 10, WHITE); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- ClosePhysics(); // Unitialize physics CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * Physac - Physics friction * * NOTE 1: Physac requires multi-threading, when InitPhysics() a second thread is created to manage physics calculations. * NOTE 2: Physac requires static C library linkage to avoid dependency on MinGW DLL (-static -lpthread) * * Use the following line to compile: * * gcc -o $(NAME_PART).exe $(FILE_NAME) -s $(RAYLIB_DIR)\raylib\raylib.rc.o -static -lraylib -lpthread * -lglfw3 -lopengl32 -lgdi32 -lopenal32 -lwinmm -std=c99 -Wl,--subsystem,windows -Wl,-allow-multiple-definition * * Copyright (c) 2016-2018 Victor Fisac * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; SetConfigFlags(FLAG_MSAA_4X_HINT); InitWindow(screenWidth, screenHeight, "Physac [raylib] - Physics friction"); // Physac logo drawing position int logoX = screenWidth - MeasureText("Physac", 30) - 10; int logoY = 15; // Initialize physics and default physics bodies InitPhysics(); // Create floor rectangle physics body PhysicsBodyData floor = CreatePhysicsBodyRectangle(new Vector2( screenWidth/2, screenHeight ), screenWidth, 100, 10); floor.enabled = false; // Disable body state to convert it to static (no dynamics, but collisions) PhysicsBodyData wall = CreatePhysicsBodyRectangle(new Vector2( screenWidth/2, screenHeight*0.8f ), 10, 80, 10); wall.enabled = false; // Disable body state to convert it to static (no dynamics, but collisions) // Create left ramp physics body PhysicsBodyData rectLeft = CreatePhysicsBodyRectangle(new Vector2( 25, screenHeight - 5 ), 250, 250, 10); rectLeft.enabled = false; // Disable body state to convert it to static (no dynamics, but collisions) SetPhysicsBodyRotation(rectLeft, 30*DEG2RAD); // Create right ramp physics body PhysicsBodyData rectRight = CreatePhysicsBodyRectangle(new Vector2( screenWidth - 25, screenHeight - 5 ), 250, 250, 10); rectRight.enabled = false; // Disable body state to convert it to static (no dynamics, but collisions) SetPhysicsBodyRotation(rectRight, 330*DEG2RAD); // Create dynamic physics bodies PhysicsBodyData bodyA = CreatePhysicsBodyRectangle(new Vector2( 35, screenHeight*0.6f ), 40, 40, 10); bodyA.staticFriction = 0.1f; bodyA.dynamicFriction = 0.1f; SetPhysicsBodyRotation(bodyA, 30*DEG2RAD); PhysicsBodyData bodyB = CreatePhysicsBodyRectangle(new Vector2( screenWidth - 35, screenHeight*0.6f ), 40, 40, 10); bodyB.staticFriction = 1; bodyB.dynamicFriction = 1; SetPhysicsBodyRotation(bodyB, 330*DEG2RAD); SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (IsKeyPressed('R')) // Reset physics input { // Reset dynamic physics bodies position, velocity and rotation bodyA.position = new Vector2( 35, screenHeight*0.6f ); bodyA.velocity = new Vector2( 0, 0 ); bodyA.angularVelocity = 0; SetPhysicsBodyRotation(bodyA, 30*DEG2RAD); bodyB.position = new Vector2( screenWidth - 35, screenHeight*0.6f ); bodyB.velocity = new Vector2( 0, 0 ); bodyB.angularVelocity = 0; SetPhysicsBodyRotation(bodyB, 330*DEG2RAD); } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(BLACK); DrawFPS(screenWidth - 90, screenHeight - 30); // Draw created physics bodies int bodiesCount = GetPhysicsBodiesCount(); for (int i = 0; i < bodiesCount; i++) { PhysicsBodyData body = GetPhysicsBody(i); if (body.id != 0) // check for null? { int vertexCount = GetPhysicsShapeVerticesCount(i); for (int j = 0; j < vertexCount; j++) { // Get physics bodies shape vertices to draw lines // Note: GetPhysicsShapeVertex() already calculates rotation transformations Vector2 vertexA = GetPhysicsShapeVertex(body, j); int jj = (((j + 1) < vertexCount) ? (j + 1) : 0); // Get next vertex or first to close the shape Vector2 vertexB = GetPhysicsShapeVertex(body, jj); DrawLineV(vertexA, vertexB, GREEN); // Draw a line between two vertex positions } } } DrawRectangle(0, screenHeight - 49, screenWidth, 49, BLACK); DrawText("Friction amount", (screenWidth - MeasureText("Friction amount", 30))/2, 75, 30, WHITE); DrawText("0.1", (int)bodyA.position.x - MeasureText("0.1", 20)/2, (int)bodyA.position.y - 7, 20, WHITE); DrawText("1", (int)bodyB.position.x - MeasureText("1", 20)/2, (int)bodyB.position.y - 7, 20, WHITE); DrawText("Press 'R' to reset example", 10, 10, 10, WHITE); DrawText("Physac", logoX, logoY, 30, WHITE); DrawText("Powered by", logoX + 50, logoY - 7, 10, WHITE); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- ClosePhysics(); // Unitialize physics CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/physac/physics_movement.cs b/Examples/physac/physics_movement.cs index a158757..2a855b7 100644 --- a/Examples/physac/physics_movement.cs +++ b/Examples/physac/physics_movement.cs @@ -1,7 +1,10 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class physics_movement { - /******************************************************************************************* * * Physac - Physics movement * * NOTE 1: Physac requires multi-threading, when InitPhysics() a second thread is created to manage physics calculations. * NOTE 2: Physac requires static C library linkage to avoid dependency on MinGW DLL (-static -lpthread) * * Use the following line to compile: * * gcc -o $(NAME_PART).exe $(FILE_NAME) -s $(RAYLIB_DIR)\raylib\raylib.rc.o -static -lraylib -lpthread * -lglfw3 -lopengl32 -lgdi32 -lopenal32 -lwinmm -std=c99 -Wl,--subsystem,windows -Wl,-allow-multiple-definition * * Copyright (c) 2016-2018 Victor Fisac * ********************************************************************************************/ public const #define PHYSAC_IMPLEMENTATION public const #define VELOCITY 0.5f public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; SetConfigFlags((int)Flag.MSAA_4X_HINT); InitWindow(screenWidth, screenHeight, "Physac [raylib] - Physics movement"); // Physac logo drawing position int logoX = screenWidth - MeasureText("Physac", 30) - 10; int logoY = 15; // Initialize physics and default physics bodies InitPhysics(); // Create floor and walls rectangle physics body PhysicsBody floor = CreatePhysicsBodyRectangle(new Vector2( screenWidth/2, screenHeight );, screenWidth, 100, 10); PhysicsBody platformLeft = CreatePhysicsBodyRectangle(new Vector2( screenWidth*0.25f, screenHeight*0.6f );, screenWidth*0.25f, 10, 10); PhysicsBody platformRight = CreatePhysicsBodyRectangle(new Vector2( screenWidth*0.75f, screenHeight*0.6f );, screenWidth*0.25f, 10, 10); PhysicsBody wallLeft = CreatePhysicsBodyRectangle(new Vector2( -5, screenHeight/2 );, 10, screenHeight, 10); PhysicsBody wallRight = CreatePhysicsBodyRectangle(new Vector2( screenWidth + 5, screenHeight/2 );, 10, screenHeight, 10); // Disable dynamics to floor and walls physics bodies floor->enabled = false; platformLeft->enabled = false; platformRight->enabled = false; wallLeft->enabled = false; wallRight->enabled = false; // Create movement physics body PhysicsBody body = CreatePhysicsBodyRectangle(new Vector2( screenWidth/2, screenHeight/2 );, 50, 50, 1); body->freezeOrient = true; // Constrain body rotation to avoid little collision torque amounts SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (IsKeyPressed('R')) // Reset physics input { // Reset movement physics body position, velocity and rotation body->position = new Vector2( screenWidth/2, screenHeight/2 );; body->velocity = new Vector2( 0, 0 );; SetPhysicsBodyRotation(body, 0); } // Horizontal movement input if (IsKeyDown((int)Key.RIGHT)) body->velocity.x = VELOCITY; else if (IsKeyDown((int)Key.LEFT)) body->velocity.x = -VELOCITY; // Vertical movement input checking if player physics body is grounded if (IsKeyDown((int)Key.UP) && body->isGrounded) body->velocity.y = -VELOCITY*4; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(BLACK); DrawFPS(screenWidth - 90, screenHeight - 30); // Draw created physics bodies int bodiesCount = GetPhysicsBodiesCount(); for (int i = 0; i < bodiesCount; i++) { PhysicsBody body = GetPhysicsBody(i); int vertexCount = GetPhysicsShapeVerticesCount(i); for (int j = 0; j < vertexCount; j++) { // Get physics bodies shape vertices to draw lines // Note: GetPhysicsShapeVertex() already calculates rotation transformations Vector2 vertexA = GetPhysicsShapeVertex(body, j); int jj = (((j + 1) < vertexCount) ? (j + 1) : 0); // Get next vertex or first to close the shape Vector2 vertexB = GetPhysicsShapeVertex(body, jj); DrawLineV(vertexA, vertexB, GREEN); // Draw a line between two vertex positions } } DrawText("Use 'ARROWS' to move player", 10, 10, 10, WHITE); DrawText("Press 'R' to reset example", 10, 30, 10, WHITE); DrawText("Physac", logoX, logoY, 30, WHITE); DrawText("Powered by", logoX + 50, logoY - 7, 10, WHITE); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- ClosePhysics(); // Unitialize physics CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * Physac - Physics movement * * NOTE 1: Physac requires multi-threading, when InitPhysics() a second thread is created to manage physics calculations. * NOTE 2: Physac requires static C library linkage to avoid dependency on MinGW DLL (-static -lpthread) * * Use the following line to compile: * * gcc -o $(NAME_PART).exe $(FILE_NAME) -s $(RAYLIB_DIR)\raylib\raylib.rc.o -static -lraylib -lpthread * -lglfw3 -lopengl32 -lgdi32 -lopenal32 -lwinmm -std=c99 -Wl,--subsystem,windows -Wl,-allow-multiple-definition * * Copyright (c) 2016-2018 Victor Fisac * ********************************************************************************************/ public const float VELOCITY = 0.5f; public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; SetConfigFlags(FLAG_MSAA_4X_HINT); InitWindow(screenWidth, screenHeight, "Physac [raylib] - Physics movement"); // Physac logo drawing position int logoX = screenWidth - MeasureText("Physac", 30) - 10; int logoY = 15; // Initialize physics and default physics bodies InitPhysics(); + + // Create floor and walls rectangle physics body + PhysicsBodyData floor = CreatePhysicsBodyRectangle(new Vector2( screenWidth/2, screenHeight ), screenWidth, 100, 10); PhysicsBodyData platformLeft = CreatePhysicsBodyRectangle(new Vector2( screenWidth*0.25f, screenHeight*0.6f ), screenWidth*0.25f, 10, 10); PhysicsBodyData platformRight = CreatePhysicsBodyRectangle(new Vector2( screenWidth*0.75f, screenHeight*0.6f ), screenWidth*0.25f, 10, 10); PhysicsBodyData wallLeft = CreatePhysicsBodyRectangle(new Vector2( -5, screenHeight/2 ), 10, screenHeight, 10); PhysicsBodyData wallRight = CreatePhysicsBodyRectangle(new Vector2( screenWidth + 5, screenHeight/2 ), 10, screenHeight, 10); // Disable dynamics to floor and walls physics bodies floor.enabled = false; platformLeft.enabled = false; platformRight.enabled = false; wallLeft.enabled = false; wallRight.enabled = false; // Create movement physics body PhysicsBodyData body = CreatePhysicsBodyRectangle(new Vector2( screenWidth/2, screenHeight/2 ), 50, 50, 1); body.freezeOrient = true; // Constrain body rotation to avoid little collision torque amounts SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (IsKeyPressed('R')) // Reset physics input { // Reset movement physics body position, velocity and rotation body.position = new Vector2( screenWidth/2, screenHeight/2 ); body.velocity = new Vector2( 0, 0 ); SetPhysicsBodyRotation(body, 0); } // Horizontal movement input if (IsKeyDown(KEY_RIGHT)) body.velocity.x = VELOCITY; else if (IsKeyDown(KEY_LEFT)) body.velocity.x = -VELOCITY; // Vertical movement input checking if player physics body is grounded if (IsKeyDown(KEY_UP) && body.isGrounded) body.velocity.y = -VELOCITY*4; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(BLACK); DrawFPS(screenWidth - 90, screenHeight - 30); // Draw created physics bodies int bodiesCount = GetPhysicsBodiesCount(); for (int i = 0; i < bodiesCount; i++) { var ibody = GetPhysicsBody(i); int vertexCount = GetPhysicsShapeVerticesCount(i); for (int j = 0; j < vertexCount; j++) { // Get physics bodies shape vertices to draw lines // Note: GetPhysicsShapeVertex() already calculates rotation transformations Vector2 vertexA = GetPhysicsShapeVertex(ibody, j); int jj = (((j + 1) < vertexCount) ? (j + 1) : 0); // Get next vertex or first to close the shape Vector2 vertexB = GetPhysicsShapeVertex(ibody, jj); DrawLineV(vertexA, vertexB, GREEN); // Draw a line between two vertex positions } } DrawText("Use 'ARROWS' to move player", 10, 10, 10, WHITE); DrawText("Press 'R' to reset example", 10, 30, 10, WHITE); DrawText("Physac", logoX, logoY, 30, WHITE); DrawText("Powered by", logoX + 50, logoY - 7, 10, WHITE); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- ClosePhysics(); // Unitialize physics CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/physac/physics_restitution.cs b/Examples/physac/physics_restitution.cs index 3fdb997..4993809 100644 --- a/Examples/physac/physics_restitution.cs +++ b/Examples/physac/physics_restitution.cs @@ -1,7 +1,7 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class physics_restitution { - /******************************************************************************************* * * Physac - Physics restitution * * NOTE 1: Physac requires multi-threading, when InitPhysics() a second thread is created to manage physics calculations. * NOTE 2: Physac requires static C library linkage to avoid dependency on MinGW DLL (-static -lpthread) * * Use the following line to compile: * * gcc -o $(NAME_PART).exe $(FILE_NAME) -s $(RAYLIB_DIR)\raylib\raylib.rc.o -static -lraylib -lpthread * -lglfw3 -lopengl32 -lgdi32 -lopenal32 -lwinmm -std=c99 -Wl,--subsystem,windows -Wl,-allow-multiple-definition * * Copyright (c) 2016-2018 Victor Fisac * ********************************************************************************************/ public const #define PHYSAC_IMPLEMENTATION public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; SetConfigFlags((int)Flag.MSAA_4X_HINT); InitWindow(screenWidth, screenHeight, "Physac [raylib] - Physics restitution"); // Physac logo drawing position int logoX = screenWidth - MeasureText("Physac", 30) - 10; int logoY = 15; // Initialize physics and default physics bodies InitPhysics(); // Create floor rectangle physics body PhysicsBody floor = CreatePhysicsBodyRectangle(new Vector2( screenWidth/2, screenHeight );, screenWidth, 100, 10); floor->enabled = false; // Disable body state to convert it to static (no dynamics, but collisions) floor->restitution = 1; // Create circles physics body PhysicsBody circleA = CreatePhysicsBodyCircle(new Vector2( screenWidth*0.25f, screenHeight/2 );, 30, 10); circleA->restitution = 0; PhysicsBody circleB = CreatePhysicsBodyCircle(new Vector2( screenWidth*0.5f, screenHeight/2 );, 30, 10); circleB->restitution = 0.5f; PhysicsBody circleC = CreatePhysicsBodyCircle(new Vector2( screenWidth*0.75f, screenHeight/2 );, 30, 10); circleC->restitution = 1; SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (IsKeyPressed('R')) // Reset physics input { // Reset circles physics bodies position and velocity circleA->position = new Vector2( screenWidth*0.25f, screenHeight/2 );; circleA->velocity = new Vector2( 0, 0 );; circleB->position = new Vector2( screenWidth*0.5f, screenHeight/2 );; circleB->velocity = new Vector2( 0, 0 );; circleC->position = new Vector2( screenWidth*0.75f, screenHeight/2 );; circleC->velocity = new Vector2( 0, 0 );; } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(BLACK); DrawFPS(screenWidth - 90, screenHeight - 30); // Draw created physics bodies int bodiesCount = GetPhysicsBodiesCount(); for (int i = 0; i < bodiesCount; i++) { PhysicsBody body = GetPhysicsBody(i); int vertexCount = GetPhysicsShapeVerticesCount(i); for (int j = 0; j < vertexCount; j++) { // Get physics bodies shape vertices to draw lines // Note: GetPhysicsShapeVertex() already calculates rotation transformations Vector2 vertexA = GetPhysicsShapeVertex(body, j); int jj = (((j + 1) < vertexCount) ? (j + 1) : 0); // Get next vertex or first to close the shape Vector2 vertexB = GetPhysicsShapeVertex(body, jj); DrawLineV(vertexA, vertexB, GREEN); // Draw a line between two vertex positions } } DrawText("Restitution amount", (screenWidth - MeasureText("Restitution amount", 30))/2, 75, 30, WHITE); DrawText("0", circleA->position.x - MeasureText("0", 20)/2, circleA->position.y - 7, 20, WHITE); DrawText("0.5", circleB->position.x - MeasureText("0.5", 20)/2, circleB->position.y - 7, 20, WHITE); DrawText("1", circleC->position.x - MeasureText("1", 20)/2, circleC->position.y - 7, 20, WHITE); DrawText("Press 'R' to reset example", 10, 10, 10, WHITE); DrawText("Physac", logoX, logoY, 30, WHITE); DrawText("Powered by", logoX + 50, logoY - 7, 10, WHITE); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- ClosePhysics(); // Unitialize physics CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * Physac - Physics restitution * * NOTE 1: Physac requires multi-threading, when InitPhysics() a second thread is created to manage physics calculations. * NOTE 2: Physac requires static C library linkage to avoid dependency on MinGW DLL (-static -lpthread) * * Use the following line to compile: * * gcc -o $(NAME_PART).exe $(FILE_NAME) -s $(RAYLIB_DIR)\raylib\raylib.rc.o -static -lraylib -lpthread * -lglfw3 -lopengl32 -lgdi32 -lopenal32 -lwinmm -std=c99 -Wl,--subsystem,windows -Wl,-allow-multiple-definition * * Copyright (c) 2016-2018 Victor Fisac * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; SetConfigFlags(FLAG_MSAA_4X_HINT); InitWindow(screenWidth, screenHeight, "Physac [raylib] - Physics restitution"); // Physac logo drawing position int logoX = screenWidth - MeasureText("Physac", 30) - 10; int logoY = 15; // Initialize physics and default physics bodies InitPhysics(); // Create floor rectangle physics body PhysicsBodyData floor = CreatePhysicsBodyRectangle(new Vector2( screenWidth/2, screenHeight ), screenWidth, 100, 10); floor.enabled = false; // Disable body state to convert it to static (no dynamics, but collisions) floor.restitution = 1; // Create circles physics body PhysicsBodyData circleA = CreatePhysicsBodyCircle(new Vector2( screenWidth*0.25f, screenHeight/2 ), 30, 10); circleA.restitution = 0; PhysicsBodyData circleB = CreatePhysicsBodyCircle(new Vector2( screenWidth*0.5f, screenHeight/2 ), 30, 10); circleB.restitution = 0.5f; PhysicsBodyData circleC = CreatePhysicsBodyCircle(new Vector2( screenWidth*0.75f, screenHeight/2 ), 30, 10); circleC.restitution = 1; SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (IsKeyPressed('R')) // Reset physics input { // Reset circles physics bodies position and velocity circleA.position = new Vector2( screenWidth*0.25f, screenHeight/2 ); circleA.velocity = new Vector2( 0, 0 ); circleB.position = new Vector2( screenWidth*0.5f, screenHeight/2 ); circleB.velocity = new Vector2( 0, 0 ); circleC.position = new Vector2( screenWidth*0.75f, screenHeight/2 ); circleC.velocity = new Vector2( 0, 0 ); } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(BLACK); DrawFPS(screenWidth - 90, screenHeight - 30); // Draw created physics bodies int bodiesCount = GetPhysicsBodiesCount(); for (int i = 0; i < bodiesCount; i++) { PhysicsBodyData body = GetPhysicsBody(i); int vertexCount = GetPhysicsShapeVerticesCount(i); for (int j = 0; j < vertexCount; j++) { // Get physics bodies shape vertices to draw lines // Note: GetPhysicsShapeVertex() already calculates rotation transformations Vector2 vertexA = GetPhysicsShapeVertex(body, j); int jj = (((j + 1) < vertexCount) ? (j + 1) : 0); // Get next vertex or first to close the shape Vector2 vertexB = GetPhysicsShapeVertex(body, jj); DrawLineV(vertexA, vertexB, GREEN); // Draw a line between two vertex positions } } DrawText("Restitution amount", (screenWidth - MeasureText("Restitution amount", 30))/2, 75, 30, WHITE); DrawText("0", (int)circleA.position.x - MeasureText("0", 20)/2, (int)circleA.position.y - 7, 20, WHITE); DrawText("0.5", (int)circleB.position.x - MeasureText("0.5", 20)/2, (int)circleB.position.y - 7, 20, WHITE); DrawText("1", (int)circleC.position.x - MeasureText("1", 20)/2, (int)circleC.position.y - 7, 20, WHITE); DrawText("Press 'R' to reset example", 10, 10, 10, WHITE); DrawText("Physac", logoX, logoY, 30, WHITE); DrawText("Powered by", logoX + 50, logoY - 7, 10, WHITE); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- ClosePhysics(); // Unitialize physics CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/physac/physics_shatter.cs b/Examples/physac/physics_shatter.cs index 830c96f..d232b77 100644 --- a/Examples/physac/physics_shatter.cs +++ b/Examples/physac/physics_shatter.cs @@ -1,7 +1,8 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class physics_shatter { - /******************************************************************************************* * * Physac - Body shatter * * NOTE 1: Physac requires multi-threading, when InitPhysics() a second thread is created to manage physics calculations. * NOTE 2: Physac requires static C library linkage to avoid dependency on MinGW DLL (-static -lpthread) * * Use the following line to compile: * * gcc -o $(NAME_PART).exe $(FILE_NAME) -s $(RAYLIB_DIR)\raylib\raylib.rc.o -static -lraylib -lpthread * -lglfw3 -lopengl32 -lgdi32 -lopenal32 -lwinmm -std=c99 -Wl,--subsystem,windows -Wl,-allow-multiple-definition * * Copyright (c) 2016-2018 Victor Fisac * ********************************************************************************************/ public const #define PHYSAC_IMPLEMENTATION public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; SetConfigFlags((int)Flag.MSAA_4X_HINT); InitWindow(screenWidth, screenHeight, "Physac [raylib] - Body shatter"); // Physac logo drawing position int logoX = screenWidth - MeasureText("Physac", 30) - 10; int logoY = 15; bool needsReset = false; // Initialize physics and default physics bodies InitPhysics(); SetPhysicsGravity(0, 0); // Create random polygon physics body to shatter CreatePhysicsBodyPolygon(new Vector2( screenWidth/2, screenHeight/2 );, GetRandomValue(80, 200), GetRandomValue(3, 8), 10); SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // Delay initialization of variables due to physics reset asynchronous if (needsReset) { // Create random polygon physics body to shatter CreatePhysicsBodyPolygon(new Vector2( screenWidth/2, screenHeight/2 );, GetRandomValue(80, 200), GetRandomValue(3, 8), 10); } if (IsKeyPressed('R')) // Reset physics input { ResetPhysics(); needsReset = true; } if (IsMouseButtonPressed((int)Mouse.LEFT_BUTTON)) // Physics shatter input { // Note: some values need to be stored in variables due to asynchronous changes during main thread int count = GetPhysicsBodiesCount(); for (int i = count - 1; i >= 0; i--) { PhysicsBody currentBody = GetPhysicsBody(i); if (currentBody != NULL) PhysicsShatter(currentBody, GetMousePosition(), 10/currentBody->inverseMass); } } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(BLACK); // Draw created physics bodies int bodiesCount = GetPhysicsBodiesCount(); for (int i = 0; i < bodiesCount; i++) { PhysicsBody currentBody = GetPhysicsBody(i); int vertexCount = GetPhysicsShapeVerticesCount(i); for (int j = 0; j < vertexCount; j++) { // Get physics bodies shape vertices to draw lines // Note: GetPhysicsShapeVertex() already calculates rotation transformations Vector2 vertexA = GetPhysicsShapeVertex(currentBody, j); int jj = (((j + 1) < vertexCount) ? (j + 1) : 0); // Get next vertex or first to close the shape Vector2 vertexB = GetPhysicsShapeVertex(currentBody, jj); DrawLineV(vertexA, vertexB, GREEN); // Draw a line between two vertex positions } } DrawText("Left mouse button in polygon area to shatter body\nPress 'R' to reset example", 10, 10, 10, WHITE); DrawText("Physac", logoX, logoY, 30, WHITE); DrawText("Powered by", logoX + 50, logoY - 7, 10, WHITE); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- ClosePhysics(); // Unitialize physics CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * Physac - Body shatter * * NOTE 1: Physac requires multi-threading, when InitPhysics() a second thread is created to manage physics calculations. * NOTE 2: Physac requires static C library linkage to avoid dependency on MinGW DLL (-static -lpthread) * * Use the following line to compile: * * gcc -o $(NAME_PART).exe $(FILE_NAME) -s $(RAYLIB_DIR)\raylib\raylib.rc.o -static -lraylib -lpthread * -lglfw3 -lopengl32 -lgdi32 -lopenal32 -lwinmm -std=c99 -Wl,--subsystem,windows -Wl,-allow-multiple-definition * * Copyright (c) 2016-2018 Victor Fisac * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; SetConfigFlags(FLAG_MSAA_4X_HINT); InitWindow(screenWidth, screenHeight, "Physac [raylib] - Body shatter"); // Physac logo drawing position int logoX = screenWidth - MeasureText("Physac", 30) - 10; int logoY = 15; bool needsReset = false; // Initialize physics and default physics bodies InitPhysics(); SetPhysicsGravity(0, 0); // Create random polygon physics body to shatter CreatePhysicsBodyPolygon(new Vector2( screenWidth/2, screenHeight/2 ), GetRandomValue(80, 200), GetRandomValue(3, 8), 10); SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // Delay initialization of variables due to physics reset asynchronous if (needsReset) { // Create random polygon physics body to shatter CreatePhysicsBodyPolygon(new Vector2( screenWidth/2, screenHeight/2 ), GetRandomValue(80, 200), GetRandomValue(3, 8), 10); } if (IsKeyPressed('R')) // Reset physics input { ResetPhysics(); needsReset = true; } if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) // Physics shatter input { // Note: some values need to be stored in variables due to asynchronous changes during main thread int count = GetPhysicsBodiesCount(); for (int i = count - 1; i >= 0; i--) { PhysicsBodyData currentBody = GetPhysicsBody(i); if (currentBody.id != 0) PhysicsShatter(currentBody, GetMousePosition(), 10/currentBody.inverseMass); } } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(BLACK); // Draw created physics bodies int bodiesCount = GetPhysicsBodiesCount(); for (int i = 0; i < bodiesCount; i++) { + PhysicsBodyData currentBody = GetPhysicsBody(i); int vertexCount = GetPhysicsShapeVerticesCount(i); for (int j = 0; j < vertexCount; j++) { // Get physics bodies shape vertices to draw lines // Note: GetPhysicsShapeVertex() already calculates rotation transformations Vector2 vertexA = GetPhysicsShapeVertex(currentBody, j); int jj = (((j + 1) < vertexCount) ? (j + 1) : 0); // Get next vertex or first to close the shape Vector2 vertexB = GetPhysicsShapeVertex(currentBody, jj); DrawLineV(vertexA, vertexB, GREEN); // Draw a line between two vertex positions } } DrawText("Left mouse button in polygon area to shatter body\nPress 'R' to reset example", 10, 10, 10, WHITE); DrawText("Physac", logoX, logoY, 30, WHITE); DrawText("Powered by", logoX + 50, logoY - 7, 10, WHITE); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- ClosePhysics(); // Unitialize physics CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/raylib-cs.ico b/Examples/raylib-cs.ico new file mode 100644 index 0000000000000000000000000000000000000000..296d5dd59c742944d814a44152a05b1d2a8018f1 GIT binary patch literal 142667 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 MAX_POSTPRO_SHADERS) currentShader = 0; else if (currentShader < 0) currentShader = MAX_POSTPRO_SHADERS - 1; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginTextureMode(target); // Enable drawing to texture BeginMode3D(camera); DrawModel(model, position, 0.1f, WHITE); // Draw 3d model with texture DrawGrid(10, 1.0f); // Draw a grid EndMode3D(); EndTextureMode(); // End drawing to texture (now we have a texture available for next passes) // Render previously generated texture using selected postpro shader BeginShaderMode(shaders[currentShader]); // NOTE: Render texture must be y-flipped due to default OpenGL coordinates (left-bottom) DrawTextureRec(target.texture, new Rectangle( 0, 0, target.texture.width, -target.texture.height }, (Vector2){ 0, 0 );, WHITE); EndShaderMode(); DrawRectangle(0, 9, 580, 30, Fade(LIGHTGRAY, 0.7f)); DrawText("(c) Church 3D model by Alberto Cano", screenWidth - 200, screenHeight - 20, 10, GRAY); DrawText("CURRENT POSTPRO SHADER:", 10, 15, 20, BLACK); DrawText(postproShaderText[currentShader], 330, 15, 20, RED); DrawText("< >", 540, 10, 30, DARKBLUE); DrawFPS(700, 15); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- // Unload all postpro shaders for (int i = 0; i < MAX_POSTPRO_SHADERS; i++) UnloadShader(shaders[i]); UnloadTexture(texture); // Unload texture UnloadModel(model); // Unload model UnloadRenderTexture(target); // Unload render texture CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [shaders] example - Apply a postprocessing shader to a scene * * NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, * OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. * * NOTE: Shaders used in this example are #version 330 (OpenGL 3.3), to test this example * on OpenGL ES 2.0 platforms (Android, Raspberry Pi, HTML5), use #version 100 shaders * raylib comes with shaders ready for both versions, check raylib/shaders install folder * * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public const int GLSL_VERSION = 330; // public const int GLSL_VERSION = 100; public const int MAX_POSTPRO_SHADERS = 12; enum PostproShader + { FX_GRAYSCALE = 0, FX_POSTERIZATION, FX_DREAM_VISION, FX_PIXELIZER, FX_CROSS_HATCHING, FX_CROSS_STITCHING, FX_PREDATOR_VIEW, FX_SCANLINES, FX_FISHEYE, FX_SOBEL, FX_BLOOM, FX_BLUR, //FX_FXAA } static string[] postproShaderText = { "GRAYSCALE", "POSTERIZATION", "DREAM_VISION", "PIXELIZER", "CROSS_HATCHING", "CROSS_STITCHING", "PREDATOR_VIEW", "SCANLINES", "FISHEYE", "SOBEL", "BLOOM", "BLUR", //"FXAA" }; public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; SetConfigFlags(FLAG_MSAA_4X_HINT); // Enable Multi Sampling Anti Aliasing 4x (if available) InitWindow(screenWidth, screenHeight, "raylib [shaders] example - postprocessing shader"); // Define the camera to look into our 3d world Camera3D camera = new Camera3D(new Vector3( 2.0f, 3.0f, 2.0f ), new Vector3( 0.0f, 1.0f, 0.0f ), new Vector3( 0.0f, 1.0f, 0.0f ), 45.0f, 0 ); Model model = LoadModel("resources/models/church.obj"); // Load OBJ model Texture2D texture = LoadTexture("resources/models/church_diffuse.png"); // Load model texture (diffuse map) model.material.maps[(int)MAP_ALBEDO].texture = texture; // Set model diffuse texture Vector3 position = new Vector3( 0.0f, 0.0f, 0.0f ); // Set model position // Load all postpro shaders // NOTE 1: All postpro shader use the base vertex shader (DEFAULT_VERTEX_SHADER) // NOTE 2: We load the correct shader depending on GLSL version Shader[] shaders = new Shader[MAX_POSTPRO_SHADERS]; // NOTE: Defining null (NULL) for vertex shader forces usage of internal default vertex shader shaders[(int)PostproShader.FX_GRAYSCALE] = LoadShader(null, FormatText("resources/shaders/glsl%i/grayscale.fs", GLSL_VERSION)); shaders[(int)PostproShader.FX_POSTERIZATION] = LoadShader(null, FormatText("resources/shaders/glsl%i/posterization.fs", GLSL_VERSION)); shaders[(int)PostproShader.FX_DREAM_VISION] = LoadShader(null, FormatText("resources/shaders/glsl%i/dream_vision.fs", GLSL_VERSION)); shaders[(int)PostproShader.FX_PIXELIZER] = LoadShader(null, FormatText("resources/shaders/glsl%i/pixelizer.fs", GLSL_VERSION)); shaders[(int)PostproShader.FX_CROSS_HATCHING] = LoadShader(null, FormatText("resources/shaders/glsl%i/cross_hatching.fs", GLSL_VERSION)); shaders[(int)PostproShader.FX_CROSS_STITCHING] = LoadShader(null, FormatText("resources/shaders/glsl%i/cross_stitching.fs", GLSL_VERSION)); shaders[(int)PostproShader.FX_PREDATOR_VIEW] = LoadShader(null, FormatText("resources/shaders/glsl%i/predator.fs", GLSL_VERSION)); shaders[(int)PostproShader.FX_SCANLINES] = LoadShader(null, FormatText("resources/shaders/glsl%i/scanlines.fs", GLSL_VERSION)); shaders[(int)PostproShader.FX_FISHEYE] = LoadShader(null, FormatText("resources/shaders/glsl%i/fisheye.fs", GLSL_VERSION)); shaders[(int)PostproShader.FX_SOBEL] = LoadShader(null, FormatText("resources/shaders/glsl%i/sobel.fs", GLSL_VERSION)); shaders[(int)PostproShader.FX_BLOOM] = LoadShader(null, FormatText("resources/shaders/glsl%i/bloom.fs", GLSL_VERSION)); shaders[(int)PostproShader.FX_BLUR] = LoadShader(null, FormatText("resources/shaders/glsl%i/blur.fs", GLSL_VERSION)); int currentShader = (int)PostproShader.FX_GRAYSCALE; // Create a RenderTexture2D to be used for render to texture RenderTexture2D target = LoadRenderTexture(screenWidth, screenHeight); // Setup orbital camera SetCameraMode(camera, (int)CAMERA_ORBITAL); // Set an orbital camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateCamera(ref camera); // Update camera if (IsKeyPressed(KEY_RIGHT)) currentShader++; else if (IsKeyPressed(KEY_LEFT)) currentShader--; if (currentShader >= MAX_POSTPRO_SHADERS) currentShader = 0; else if (currentShader < 0) currentShader = MAX_POSTPRO_SHADERS - 1; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginTextureMode(target); // Enable drawing to texture BeginMode3D(camera); DrawModel(model, position, 0.1f, WHITE); // Draw 3d model with texture DrawGrid(10, 1.0f); // Draw a grid EndMode3D(); EndTextureMode(); // End drawing to texture (now we have a texture available for next passes) // Render previously generated texture using selected postpro shader BeginShaderMode(shaders[currentShader]); // NOTE: Render texture must be y-flipped due to default OpenGL coordinates (left-bottom) DrawTextureRec(target.texture, new Rectangle( 0, 0, target.texture.width, -target.texture.height ), new Vector2( 0, 0 ), WHITE); EndShaderMode(); DrawRectangle(0, 9, 580, 30, Fade(LIGHTGRAY, 0.7f)); DrawText("(c) Church 3D model by Alberto Cano", screenWidth - 200, screenHeight - 20, 10, GRAY); DrawText("CURRENT POSTPRO SHADER:", 10, 15, 20, BLACK); DrawText(postproShaderText[currentShader], 330, 15, 20, RED); DrawText("< >", 540, 10, 30, DARKBLUE); DrawFPS(700, 15); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- // Unload all postpro shaders for (int i = 0; i < MAX_POSTPRO_SHADERS; i++) UnloadShader(shaders[i]); UnloadTexture(texture); // Unload texture UnloadModel(model); // Unload model UnloadRenderTexture(target); // Unload render texture CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/shaders/shaders_shapes_textures.cs b/Examples/shaders/shaders_shapes_textures.cs index 64cce51..213e5d8 100644 --- a/Examples/shaders/shaders_shapes_textures.cs +++ b/Examples/shaders/shaders_shapes_textures.cs @@ -1,7 +1,7 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class shaders_shapes_textures { - /******************************************************************************************* * * raylib [shaders] example - Apply a shader to some shape or texture * * NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, * OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. * * NOTE: Shaders used in this example are #version 330 (OpenGL 3.3), to test this example * on OpenGL ES 2.0 platforms (Android, Raspberry Pi, HTML5), use #version 100 shaders * raylib comes with shaders ready for both versions, check raylib/shaders install folder * * This example has been created using raylib 1.7 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [shaders] example - shapes and texture shaders"); Texture2D fudesumi = LoadTexture("resources/fudesumi.png"); // NOTE: Using GLSL 330 shader version, on OpenGL ES 2.0 use GLSL 100 shader version Shader shader = LoadShader("resources/shaders/glsl330/base.vs", "resources/shaders/glsl330/grayscale.fs"); SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update your variables here //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); // Start drawing with default shader DrawText("USING DEFAULT SHADER", 20, 40, 10, RED); DrawCircle(80, 120, 35, DARKBLUE); DrawCircleGradient(80, 220, 60, GREEN, SKYBLUE); DrawCircleLines(80, 340, 80, DARKBLUE); // Activate our custom shader to be applied on next shapes/textures drawings BeginShaderMode(shader); DrawText("USING CUSTOM SHADER", 190, 40, 10, RED); DrawRectangle(250 - 60, 90, 120, 60, RED); DrawRectangleGradientH(250 - 90, 170, 180, 130, MAROON, GOLD); DrawRectangleLines(250 - 40, 320, 80, 60, ORANGE); // Activate our default shader for next drawings EndShaderMode(); DrawText("USING DEFAULT SHADER", 370, 40, 10, RED); DrawTriangle(new Vector2(430, 80);, new Vector2(430 - 60, 150);, new Vector2(430 + 60, 150);, VIOLET); DrawTriangleLines(new Vector2(430, 160);, new Vector2(430 - 20, 230);, new Vector2(430 + 20, 230);, DARKBLUE); DrawPoly(new Vector2(430, 320);, 6, 80, 0, BROWN); // Activate our custom shader to be applied on next shapes/textures drawings BeginShaderMode(shader); DrawTexture(fudesumi, 500, -30, WHITE); // Using custom shader // Activate our default shader for next drawings EndShaderMode(); DrawText("(c) Fudesumi sprite by Eiden Marsal", 380, screenHeight - 20, 10, GRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadShader(shader); // Unload shader UnloadTexture(fudesumi); // Unload texture CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [shaders] example - Apply a shader to some shape or texture * * NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, * OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. * * NOTE: Shaders used in this example are #version 330 (OpenGL 3.3), to test this example * on OpenGL ES 2.0 platforms (Android, Raspberry Pi, HTML5), use #version 100 shaders * raylib comes with shaders ready for both versions, check raylib/shaders install folder * * This example has been created using raylib 1.7 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [shaders] example - shapes and texture shaders"); Texture2D fudesumi = LoadTexture("resources/fudesumi.png"); // NOTE: Using GLSL 330 shader version, on OpenGL ES 2.0 use GLSL 100 shader version Shader shader = LoadShader("resources/shaders/glsl330/base.vs", "resources/shaders/glsl330/grayscale.fs"); SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update your variables here //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); // Start drawing with default shader DrawText("USING DEFAULT SHADER", 20, 40, 10, RED); DrawCircle(80, 120, 35, DARKBLUE); DrawCircleGradient(80, 220, 60, GREEN, SKYBLUE); DrawCircleLines(80, 340, 80, DARKBLUE); // Activate our custom shader to be applied on next shapes/textures drawings BeginShaderMode(shader); DrawText("USING CUSTOM SHADER", 190, 40, 10, RED); DrawRectangle(250 - 60, 90, 120, 60, RED); DrawRectangleGradientH(250 - 90, 170, 180, 130, MAROON, GOLD); DrawRectangleLines(250 - 40, 320, 80, 60, ORANGE); // Activate our default shader for next drawings EndShaderMode(); DrawText("USING DEFAULT SHADER", 370, 40, 10, RED); DrawTriangle(new Vector2(430, 80), new Vector2(430 - 60, 150), new Vector2(430 + 60, 150), VIOLET); DrawTriangleLines(new Vector2(430, 160), new Vector2(430 - 20, 230), new Vector2(430 + 20, 230), DARKBLUE); DrawPoly(new Vector2(430, 320), 6, 80, 0, BROWN); // Activate our custom shader to be applied on next shapes/textures drawings BeginShaderMode(shader); DrawTexture(fudesumi, 500, -30, WHITE); // Using custom shader // Activate our default shader for next drawings EndShaderMode(); DrawText("(c) Fudesumi sprite by Eiden Marsal", 380, screenHeight - 20, 10, GRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadShader(shader); // Unload shader UnloadTexture(fudesumi); // Unload texture CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/shapes/shapes_basic_shapes.cs b/Examples/shapes/shapes_basic_shapes.cs index 3d698ed..437a150 100644 --- a/Examples/shapes/shapes_basic_shapes.cs +++ b/Examples/shapes/shapes_basic_shapes.cs @@ -1,7 +1,7 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class shapes_basic_shapes { - /******************************************************************************************* * * raylib [shapes] example - Draw basic shapes 2d (rectangle, circle, line...) * * 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) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [shapes] example - basic shapes drawing"); SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update your variables here //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText("some basic shapes available on raylib", 20, 20, 20, DARKGRAY); DrawLine(18, 42, screenWidth - 18, 42, BLACK); DrawCircle(screenWidth/4, 120, 35, DARKBLUE); DrawCircleGradient(screenWidth/4, 220, 60, GREEN, SKYBLUE); DrawCircleLines(screenWidth/4, 340, 80, DARKBLUE); DrawRectangle(screenWidth/4*2 - 60, 100, 120, 60, RED); DrawRectangleGradientH(screenWidth/4*2 - 90, 170, 180, 130, MAROON, GOLD); DrawRectangleLines(screenWidth/4*2 - 40, 320, 80, 60, ORANGE); DrawTriangle(new Vector2(screenWidth/4*3, 80);, new Vector2(screenWidth/4*3 - 60, 150);, new Vector2(screenWidth/4*3 + 60, 150);, VIOLET); DrawTriangleLines(new Vector2(screenWidth/4*3, 160);, new Vector2(screenWidth/4*3 - 20, 230);, new Vector2(screenWidth/4*3 + 20, 230);, DARKBLUE); DrawPoly(new Vector2(screenWidth/4*3, 320);, 6, 80, 0, BROWN); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [shapes] example - Draw basic shapes 2d (rectangle, circle, line...) * * 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) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [shapes] example - basic shapes drawing"); SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update your variables here //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText("some basic shapes available on raylib", 20, 20, 20, DARKGRAY); DrawLine(18, 42, screenWidth - 18, 42, BLACK); DrawCircle(screenWidth/4, 120, 35, DARKBLUE); DrawCircleGradient(screenWidth/4, 220, 60, GREEN, SKYBLUE); DrawCircleLines(screenWidth/4, 340, 80, DARKBLUE); DrawRectangle(screenWidth/4*2 - 60, 100, 120, 60, RED); DrawRectangleGradientH(screenWidth/4*2 - 90, 170, 180, 130, MAROON, GOLD); DrawRectangleLines(screenWidth/4*2 - 40, 320, 80, 60, ORANGE); DrawTriangle(new Vector2(screenWidth/4*3, 80), new Vector2(screenWidth/4*3 - 60, 150), new Vector2(screenWidth/4*3 + 60, 150), VIOLET); DrawTriangleLines(new Vector2(screenWidth/4*3, 160), new Vector2(screenWidth/4*3 - 20, 230), new Vector2(screenWidth/4*3 + 20, 230), DARKBLUE); DrawPoly(new Vector2(screenWidth/4*3, 320), 6, 80, 0, BROWN); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/shapes/shapes_colors_palette.cs b/Examples/shapes/shapes_colors_palette.cs index 64bbd7f..ebdf35b 100644 --- a/Examples/shapes/shapes_colors_palette.cs +++ b/Examples/shapes/shapes_colors_palette.cs @@ -1,7 +1,7 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class shapes_colors_palette { - /******************************************************************************************* * * raylib [shapes] example - Draw raylib custom color palette * * 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) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [shapes] example - raylib color palette"); SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update your variables here //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText("raylib color palette", 28, 42, 20, BLACK); DrawRectangle(26, 80, 100, 100, DARKGRAY); DrawRectangle(26, 188, 100, 100, GRAY); DrawRectangle(26, 296, 100, 100, LIGHTGRAY); DrawRectangle(134, 80, 100, 100, MAROON); DrawRectangle(134, 188, 100, 100, RED); DrawRectangle(134, 296, 100, 100, PINK); DrawRectangle(242, 80, 100, 100, ORANGE); DrawRectangle(242, 188, 100, 100, GOLD); DrawRectangle(242, 296, 100, 100, YELLOW); DrawRectangle(350, 80, 100, 100, DARKGREEN); DrawRectangle(350, 188, 100, 100, LIME); DrawRectangle(350, 296, 100, 100, GREEN); DrawRectangle(458, 80, 100, 100, DARKBLUE); DrawRectangle(458, 188, 100, 100, BLUE); DrawRectangle(458, 296, 100, 100, SKYBLUE); DrawRectangle(566, 80, 100, 100, DARKPURPLE); DrawRectangle(566, 188, 100, 100, VIOLET); DrawRectangle(566, 296, 100, 100, PURPLE); DrawRectangle(674, 80, 100, 100, DARKBROWN); DrawRectangle(674, 188, 100, 100, BROWN); DrawRectangle(674, 296, 100, 100, BEIGE); DrawText("DARKGRAY", 65, 166, 10, BLACK); DrawText("GRAY", 93, 274, 10, BLACK); DrawText("LIGHTGRAY", 61, 382, 10, BLACK); DrawText("MAROON", 186, 166, 10, BLACK); DrawText("RED", 208, 274, 10, BLACK); DrawText("PINK", 204, 382, 10, BLACK); DrawText("ORANGE", 295, 166, 10, BLACK); DrawText("GOLD", 310, 274, 10, BLACK); DrawText("YELLOW", 300, 382, 10, BLACK); DrawText("DARKGREEN", 382, 166, 10, BLACK); DrawText("LIME", 420, 274, 10, BLACK); DrawText("GREEN", 410, 382, 10, BLACK); DrawText("DARKBLUE", 498, 166, 10, BLACK); DrawText("BLUE", 526, 274, 10, BLACK); DrawText("SKYBLUE", 505, 382, 10, BLACK); DrawText("DARKPURPLE", 592, 166, 10, BLACK); DrawText("VIOLET", 621, 274, 10, BLACK); DrawText("PURPLE", 620, 382, 10, BLACK); DrawText("DARKBROWN", 705, 166, 10, BLACK); DrawText("BROWN", 733, 274, 10, BLACK); DrawText("BEIGE", 737, 382, 10, BLACK); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [shapes] example - Draw raylib custom color palette * * 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) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [shapes] example - raylib color palette"); SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update your variables here //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText("raylib color palette", 28, 42, 20, BLACK); DrawRectangle(26, 80, 100, 100, DARKGRAY); DrawRectangle(26, 188, 100, 100, GRAY); DrawRectangle(26, 296, 100, 100, LIGHTGRAY); DrawRectangle(134, 80, 100, 100, MAROON); DrawRectangle(134, 188, 100, 100, RED); DrawRectangle(134, 296, 100, 100, PINK); DrawRectangle(242, 80, 100, 100, ORANGE); DrawRectangle(242, 188, 100, 100, GOLD); DrawRectangle(242, 296, 100, 100, YELLOW); DrawRectangle(350, 80, 100, 100, DARKGREEN); DrawRectangle(350, 188, 100, 100, LIME); DrawRectangle(350, 296, 100, 100, GREEN); DrawRectangle(458, 80, 100, 100, DARKBLUE); DrawRectangle(458, 188, 100, 100, BLUE); DrawRectangle(458, 296, 100, 100, SKYBLUE); DrawRectangle(566, 80, 100, 100, DARKPURPLE); DrawRectangle(566, 188, 100, 100, VIOLET); DrawRectangle(566, 296, 100, 100, PURPLE); DrawRectangle(674, 80, 100, 100, DARKBROWN); DrawRectangle(674, 188, 100, 100, BROWN); DrawRectangle(674, 296, 100, 100, BEIGE); DrawText("DARKGRAY", 65, 166, 10, BLACK); DrawText("GRAY", 93, 274, 10, BLACK); DrawText("LIGHTGRAY", 61, 382, 10, BLACK); DrawText("MAROON", 186, 166, 10, BLACK); DrawText("RED", 208, 274, 10, BLACK); DrawText("PINK", 204, 382, 10, BLACK); DrawText("ORANGE", 295, 166, 10, BLACK); DrawText("GOLD", 310, 274, 10, BLACK); DrawText("YELLOW", 300, 382, 10, BLACK); DrawText("DARKGREEN", 382, 166, 10, BLACK); DrawText("LIME", 420, 274, 10, BLACK); DrawText("GREEN", 410, 382, 10, BLACK); DrawText("DARKBLUE", 498, 166, 10, BLACK); DrawText("BLUE", 526, 274, 10, BLACK); DrawText("SKYBLUE", 505, 382, 10, BLACK); DrawText("DARKPURPLE", 592, 166, 10, BLACK); DrawText("VIOLET", 621, 274, 10, BLACK); DrawText("PURPLE", 620, 382, 10, BLACK); DrawText("DARKBROWN", 705, 166, 10, BLACK); DrawText("BROWN", 733, 274, 10, BLACK); DrawText("BEIGE", 737, 382, 10, BLACK); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/shapes/shapes_lines_bezier.cs b/Examples/shapes/shapes_lines_bezier.cs index 90a0984..e496c3c 100644 --- a/Examples/shapes/shapes_lines_bezier.cs +++ b/Examples/shapes/shapes_lines_bezier.cs @@ -1,7 +1,7 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class shapes_lines_bezier { - /******************************************************************************************* * * raylib [shapes] example - Cubic-bezier lines * * This example has been created using raylib 1.7 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2017 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; SetConfigFlags((int)Flag.MSAA_4X_HINT); InitWindow(screenWidth, screenHeight, "raylib [shapes] example - cubic-bezier lines"); Vector2 start = { 0, 0 }; Vector2 end = { screenWidth, screenHeight }; SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (IsMouseButtonDown((int)Mouse.LEFT_BUTTON)) start = GetMousePosition(); else if (IsMouseButtonDown((int)Mouse.RIGHT_BUTTON)) end = GetMousePosition(); //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText("USE MOUSE LEFT-RIGHT CLICK to DEFINE LINE START and END POINTS", 15, 20, 20, GRAY); DrawLineBezier(start, end, 2.0f, RED); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [shapes] example - Cubic-bezier lines * * This example has been created using raylib 1.7 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2017 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; SetConfigFlags(FLAG_MSAA_4X_HINT); InitWindow(screenWidth, screenHeight, "raylib [shapes] example - cubic-bezier lines"); Vector2 start = new Vector2( 0, 0 ); Vector2 end = new Vector2( screenWidth, screenHeight ); SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) start = GetMousePosition(); else if (IsMouseButtonDown(MOUSE_RIGHT_BUTTON)) end = GetMousePosition(); //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText("USE MOUSE LEFT-RIGHT CLICK to DEFINE LINE START and END POINTS", 15, 20, 20, GRAY); DrawLineBezier(start, end, 2.0f, RED); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/shapes/shapes_logo_raylib.cs b/Examples/shapes/shapes_logo_raylib.cs index 1810d6b..53c994d 100644 --- a/Examples/shapes/shapes_logo_raylib.cs +++ b/Examples/shapes/shapes_logo_raylib.cs @@ -1,7 +1,7 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class shapes_logo_raylib { - /******************************************************************************************* * * raylib [shapes] example - Draw raylib logo using basic shapes * * 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) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [shapes] example - raylib logo using shapes"); SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update your variables here //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawRectangle(screenWidth/2 - 128, screenHeight/2 - 128, 256, 256, BLACK); DrawRectangle(screenWidth/2 - 112, screenHeight/2 - 112, 224, 224, RAYWHITE); DrawText("raylib", screenWidth/2 - 44, screenHeight/2 + 48, 50, BLACK); DrawText("this is NOT a texture!", 350, 370, 10, GRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [shapes] example - Draw raylib logo using basic shapes * * 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) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [shapes] example - raylib logo using shapes"); SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update your variables here //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawRectangle(screenWidth/2 - 128, screenHeight/2 - 128, 256, 256, BLACK); DrawRectangle(screenWidth/2 - 112, screenHeight/2 - 112, 224, 224, RAYWHITE); DrawText("raylib", screenWidth/2 - 44, screenHeight/2 + 48, 50, BLACK); DrawText("this is NOT a texture!", 350, 370, 10, GRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/shapes/shapes_logo_raylib_anim.cs b/Examples/shapes/shapes_logo_raylib_anim.cs index cd66bf6..a9d25c7 100644 --- a/Examples/shapes/shapes_logo_raylib_anim.cs +++ b/Examples/shapes/shapes_logo_raylib_anim.cs @@ -1,7 +1,8 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class shapes_logo_raylib_anim { - /******************************************************************************************* * * raylib [shapes] example - raylib logo animation * * 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) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [shapes] example - raylib logo animation"); int logoPositionX = screenWidth/2 - 128; int logoPositionY = screenHeight/2 - 128; int framesCounter = 0; int lettersCount = 0; int topSideRecWidth = 16; int leftSideRecHeight = 16; int bottomSideRecWidth = 16; int rightSideRecHeight = 16; int state = 0; // Tracking animation states (State Machine) float alpha = 1.0f; // Useful for fading SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (state == 0) // State 0: Small box blinking { framesCounter++; if (framesCounter == 120) { state = 1; framesCounter = 0; // Reset counter... will be used later... } } else if (state == 1) // State 1: Top and left bars growing { topSideRecWidth += 4; leftSideRecHeight += 4; if (topSideRecWidth == 256) state = 2; } else if (state == 2) // State 2: Bottom and right bars growing { bottomSideRecWidth += 4; rightSideRecHeight += 4; if (bottomSideRecWidth == 256) state = 3; } else if (state == 3) // State 3: Letters appearing (one by one) { framesCounter++; if (framesCounter/12) // Every 12 frames, one more letter! { lettersCount++; framesCounter = 0; } if (lettersCount >= 10) // When all letters have appeared, just fade out everything { alpha -= 0.02f; if (alpha <= 0.0f) { alpha = 0.0f; state = 4; } } } else if (state == 4) // State 4: Reset and Replay { if (IsKeyPressed('R')) { framesCounter = 0; lettersCount = 0; topSideRecWidth = 16; leftSideRecHeight = 16; bottomSideRecWidth = 16; rightSideRecHeight = 16; alpha = 1.0f; state = 0; // Return to State 0 } } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); if (state == 0) { if ((framesCounter/15)%2) DrawRectangle(logoPositionX, logoPositionY, 16, 16, BLACK); } else if (state == 1) { DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, BLACK); DrawRectangle(logoPositionX, logoPositionY, 16, leftSideRecHeight, BLACK); } else if (state == 2) { DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, BLACK); DrawRectangle(logoPositionX, logoPositionY, 16, leftSideRecHeight, BLACK); DrawRectangle(logoPositionX + 240, logoPositionY, 16, rightSideRecHeight, BLACK); DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, BLACK); } else if (state == 3) { DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, Fade(BLACK, alpha)); DrawRectangle(logoPositionX, logoPositionY + 16, 16, leftSideRecHeight - 32, Fade(BLACK, alpha)); DrawRectangle(logoPositionX + 240, logoPositionY + 16, 16, rightSideRecHeight - 32, Fade(BLACK, alpha)); DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, Fade(BLACK, alpha)); DrawRectangle(screenWidth/2 - 112, screenHeight/2 - 112, 224, 224, Fade(RAYWHITE, alpha)); DrawText(SubText("raylib", 0, lettersCount), screenWidth/2 - 44, screenHeight/2 + 48, 50, Fade(BLACK, alpha)); } else if (state == 4) { DrawText("[R] REPLAY", 340, 200, 20, GRAY); } EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [shapes] example - raylib logo animation * * 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) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [shapes] example - raylib logo animation"); int logoPositionX = screenWidth/2 - 128; int logoPositionY = screenHeight/2 - 128; int framesCounter = 0; int lettersCount = 0; int topSideRecWidth = 16; int leftSideRecHeight = 16; int bottomSideRecWidth = 16; int rightSideRecHeight = 16; int state = 0; // Tracking animation states (State Machine) float alpha = 1.0f; // Useful for fading SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (state == 0) // State 0: Small box blinking { framesCounter++; if (framesCounter == 120) { state = 1; framesCounter = 0; // Reset counter... will be used later... } } else if (state == 1) // State 1: Top and left bars growing { topSideRecWidth += 4; leftSideRecHeight += 4; if (topSideRecWidth == 256) state = 2; } else if (state == 2) // State 2: Bottom and right bars growing { bottomSideRecWidth += 4; rightSideRecHeight += 4; if (bottomSideRecWidth == 256) state = 3; } else if (state == 3) // State 3: Letters appearing (one by one) { framesCounter++; + if (framesCounter/12 != 0) // Every 12 frames, one more letter! { lettersCount++; framesCounter = 0; } if (lettersCount >= 10) // When all letters have appeared, just fade out everything { alpha -= 0.02f; if (alpha <= 0.0f) { alpha = 0.0f; state = 4; } } } else if (state == 4) // State 4: Reset and Replay { if (IsKeyPressed('R')) { framesCounter = 0; lettersCount = 0; topSideRecWidth = 16; leftSideRecHeight = 16; bottomSideRecWidth = 16; rightSideRecHeight = 16; alpha = 1.0f; state = 0; // Return to State 0 } } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); if (state == 0) { if ((framesCounter/15)%2 != 0) DrawRectangle(logoPositionX, logoPositionY, 16, 16, BLACK); } else if (state == 1) { DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, BLACK); DrawRectangle(logoPositionX, logoPositionY, 16, leftSideRecHeight, BLACK); } else if (state == 2) { DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, BLACK); DrawRectangle(logoPositionX, logoPositionY, 16, leftSideRecHeight, BLACK); DrawRectangle(logoPositionX + 240, logoPositionY, 16, rightSideRecHeight, BLACK); DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, BLACK); } else if (state == 3) { DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, Fade(BLACK, alpha)); DrawRectangle(logoPositionX, logoPositionY + 16, 16, leftSideRecHeight - 32, Fade(BLACK, alpha)); DrawRectangle(logoPositionX + 240, logoPositionY + 16, 16, rightSideRecHeight - 32, Fade(BLACK, alpha)); DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, Fade(BLACK, alpha)); DrawRectangle(screenWidth/2 - 112, screenHeight/2 - 112, 224, 224, Fade(RAYWHITE, alpha)); //DrawText(SubText("raylib", 0, lettersCount), screenWidth/2 - 44, screenHeight/2 + 48, 50, Fade(BLACK, alpha)); } else if (state == 4) { DrawText("[R] REPLAY", 340, 200, 20, GRAY); } EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/text/resources/custom_alagard.png b/Examples/text/resources/custom_alagard.png index c3eb63b7150c2ba8b2048f4501523125c9eb2756..63426555739356fd90b80f8c6355781e6ab12a56 100644 GIT binary patch literal 45351 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

dN0`FH*mJGP|l4uD#Fo`$b#r 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 L{an^LB{Ts58^292 literal 37935 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 L`njxgN@xNA)rW-U diff --git a/Examples/text/resources/custom_jupiter_crash.png b/Examples/text/resources/custom_jupiter_crash.png index 451b591f17180d69d1229a74117fb971367f9ec4..2deaaeff7ba75e1c02889a5b6ae18b26ffde78fa 100644 GIT binary patch literal 29128 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


fKlDd0-noF&Nl8HV$HfPw2M-?Zm;e8(xBlbN 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 T>fU8wU|{fc^>bP0l+XkKYA&)9 literal 26597 zcmeAS@N?(olHy`uVBq!ia0y~yVBE*Rz$nAP#=yX^Bl02-0|SF(iEBhjaDG}zd16s2 zgJVj5QmTSyZen_BP-r5%(GQ`zk9!uLS~AsQn;zFfp39xYDT68?trEmh5xxNm&iO^D3Z{Any2%D+ z1`1||dWOa(=H}))3PuKo2Koj@`i4fjhUQkrMpgy}3Q(YAr(jc*l4cd;;s&*=C?(BS zDWjyMz)D}gyu4hm+*mKaC|%#s($W%ShLMqOQA(O_ab;dfVufyAu`2bec=Y@6+;6mIX_pwBC$ZIIA zz^b}9q_QAYKPa_0zqBYhH7GSr8ObXA7J(EN`1)G;7iFer<|XF1y(9qS`($LM+*~QS=$i>mX#LUPUrq?sCxFj(zITdDaW@d^NRIepoy;jaesfi`| zMIrh5Ij|HEkda@KU!0L&px_*Ast}%;my%yz42m3Z$XmIj7G;*DrnnX5=PH0h*D4c> z?T*HTd=1f?LQaV3+bP)SgOUbPQh^BtxwwIt;8YDt;dTm$tdp9TVyjf7WN+80>1oZt zkRtBs;uunK>&;&73Yp`jdJ&gD*D*AkJ2d4ts(4JC(zI0)qPu+2!{pLYJ`OGdV4Nt

i$gDb-3w9i%i`bH7D zE~oi@{daxdt_{7Fe-zgEzy7^1w;`vX#BF-$etGFlGpr8JD^5+Ts-ENYeADxGgWo$6 zr5bKn9%3@sw85@jJ=55{U~kROu=}^tLhR38+T=e)f5(=ex(w|VJD8T=yYK#5d6w|u z$yp;E-dUX&6s_B(IsiIx@Ql(A3x{caf-ofy~dJl7ruR#*wVPg`s&8Et(_1h3-0jB%}AXUnz^BiA$>SG=Y;hS)M3Q$~17B zC$Z|W%AGCUNq4@TI7Y*yN7wMaN5G^3mQa!d{EKKYeAQ^(z0&Ewes{&6KWPF~#^= z#A6T3-D^rin9Q}?5AFLa5pvo+?*_x#&&>**D(j}L*390yJfMU1!0Dv-2PfBXZ*bF? zSSA=0_;TS6mb$3D?Q#b_dbnP5nY}q+9ec9m!GQ)NzwF57oc*i`E*ln#o-aP^y76T5 zP02_5V-i+7JE)&@PMp0-^?>z_3tjCiz9-&3cSP{BUQJ&AA!Ut_V7-U`Uok2cEd8-t zR8iONm!Z?*N*Tw6=I!YP3X#Vit_}LO`mbHL|MGM$UW?o3|E6$>vbRo?kKfYRE+Thb z?RwvptQge`TetfhQqP`gu|uHy*3%EK8hm*Avp);;ANV@?<#*9jDm9a)B$fteC%f#N zXp}AN{`ub3)8`&N{4VriE2r|7?Mo_4+;+ByIB{wEYEPMa)cK^HgT=$gTW@TVcD!8n zU|j|KfddQ9Z}fJ!S}9>0aHwEyD0`sqWYZ00+t?b6)1E!Lz3+mja0Ta$0>+FMzk?db z^md4N*d=#oWTkq0RfI zmMr?U#lgMZY$fkh!S@e%_PqOEINMow&!#=1I$qm^85MtR`W13R|Fb5O)0wuq6t2CW zU&OahwwMy#Ulw^k{F&6IFPqO~b){MyWeO8EJG?6W-SvHX zld>ahDx&;X9KOW9zK-kg#}_t@ml}@st&Tk3VK+^s&Tci&UzePm&6&x2e(2ds-{8qG zVe_AtSonPHsb7)T1yj6TCwm*3nBG608hrKJW=DG&^QIYYbFcpk-r8`z+G=sN|JS%z zb;|{N*R5f-y7GLwLgbwrxd$zp?k0chSZ~~JX&mCz$36GczQxo2>GU2wcxFL>ciF{6 z^@(hkZU%3YJnazp@2igBvBvZV%Pn`WFj;NJ#;d%dds?nfg3fjSa}%7`&zk;d!Az&U z>vX2aeYU%-C*jy#KJ!X@e(!9S=UnQ|4!h6&=kSgEaOP6qesKW<7jIADT=VH++k#kH z@5!iK-?II~q8wg3+j;+457-?}TxnHU`)BKP{;6*M>N$s4dM-RUCUID#x&G|I>0FLF zjMpV=injL)H;HV18niC?^Ubxa3e$F7VAw92vFcr3=8x;epZZVizQ619g5|P3YOdD; zzioQ;{x_4!?z0mo%jrv z|J#Q?xFPSeKqc`v=gT`iIdf(UNcuhwpYfx85 ztflnwN&Zo@EcTg9@0B$cFkxJDEg@*#9B+|}!Y!|AU3XvQSpDMkwDQGf7p7g^kzUDY zu;ZV9wLagMu8;nL3`_aB!~H%#6Jf}D77hyWZ_9&~Vlw_slgzlr`9ref{6R$qMi>%P zD8A1U6VFieaCe(Pj03|bxAY6Ajy$NJvtOWTzF33LnSwX}zdmReh{@pGktOtufhmen z(QtA8BE}<*LX6k1G6*osnK?MzV0dKP&@h{ep{3x6kbnRa6n(fY;J9!hBhx#c|C|O4 YTNc0hnQF~q4(cg+y85}Sb4q9e0E4mbnE(I) diff --git a/Examples/text/resources/fonts/mecha.png b/Examples/text/resources/fonts/mecha.png index 8022d18c44ca8c74770faecb067c4ff7d4733d26..9213fa2d16d73a2e0793d95ce915e2dec6c8fa56 100644 GIT binary patch literal 2355 zcmeAS@N?(olHy`uVBq!ia0y~yU}ykg4rT@hhA$5${$yZaU@Q)DcVbv~PUa;80|QIC zqpu?a!^VE@KZ&di49pAxJ|V6Q3=IDn{{R2~pJ5b?hQP=Rft{T)`xqD)8A^iuf0#LT=By}Z;C z1rt3(J;P+JIo=EmEIpnsjv*CsZ^OB(Zy5+k|M~xakLU7gOFxYOg}dRqSNiQ+{-|Zs z-<@;z{EPWl6#K#X%h{d{yLK(Vc}MK0)PG~f>!+`lJ$?C2>h_oWjj;^37oQYeE77($ zW+!7(WQ0`Fr3~YZ9S;R=JzB`n8tc%e>G0`=q;7YHj{A`dtObufIR0;BD1NxzLT9%8 z+ymMy62JD&=H5S<;rs06kt&t`PgPE>l)K0II)cIa>VkvnVLKafkY@ zS@+alEaAC>*YuCGnQriLR&@kAPR#fmFWk>^+W(8+ znX-RN7`6sXi(HoSXfx9qC-bY^cDfCYK9hJp=``yywq?#_eAIcK>%%>c8_Een#Q|wa zX^dIkr_)rtdbkvoqx(4x?y*M1f0Qs>khgYHP{aGfcTZgZF@s_Mq0d%~>g&sxj?Fsc zR$F?$wnF6OT_Fa>UoHm{*G;=>ZyR;@a={567iI;it+AzNZMZf(SjW&X{pPFQO?TVM zTkcEwitf2n9?Wp?bk0||wRaE97ZW(So9WG#RVzNUG8yoltkCdr65F$OhRTmCc@JbC z?)PSx&T>FJxbU`pS&iE1-H8Z&*^WI6N0Ql?L$>cX6Na<~-_*vo7e+$nop_QGbH713EOsq|jdh_P~leXjkW^Lxu`OF+(oEez@ zUC8bGsMg?lhr73D?oscCmzr|3HlBat6y^HE_TaZuk7O!y7d;c|<&mAkuWrD%=&=KX zzCGhn&h4x(%4V3I`_;zqHYa(`ibb)E8`e5k$q7wpKFn9RsOz3O!<|KYX89K`61}+k zlQrv;%ZGd28J zHKG54yyG%+t|$Crd%k>-dMw@JUZB!&toG5qU)vu>tUQ<$HtBclmuA+xZ56%h4v#lR?9M(Fv-Fot6pz1q~+bJkAtyLGWLZg>zPc|HAcBKW6RYp2FI9 z@Zgy$n+dWz5RZ$1Ll6iVOHZd^P^(xM+4s>Y;vJ&JD?yz6|#RZRQHI z-r&?>^gd9@^kwS#^Gxd8{#K21?WeqtZ)T9LUBu8UR+pp8C{pmPoblMr-SyKNCSMoY jzyi{MkIEM>*!hP!)_CiB@BeMFpeoJN)z4*}Q$iB}?-@$P literal 2399 zcmeAS@N?(olHy`uVBq!ia0y~yU}ykg4mJh`hQoG=rx_R+BuiW)N`mv#O3D+9QW+dm z@{>{(JaZG%Q-e|yQz{EjrrIztFsEdOM3hAM`dB6B=jtVb)aX^@7BGN-jeSKyVsdtB zi9%9pdS;%j()-=}l@u~lY?Z=IeGPmIoKrJ0J*tXQgRA^PlB=?lEmM^2?G$V(tSWK~ za#KqZ6)JLb@`|l0Y?Z*~TICg6frRyy6u?SKvTcwn`Gtf;oFf&jv zGt@IQHZeCh*HJJsFf`CNFw!?P(ls=X%D*TxJu@#c$0a|xG&eP`#M8xAsUo*P zFC{a@%F*1?*vP`j!r9o^!qwQ&(8{6dBr7(dC93Tdowdrte|?G@#?j5E=o--$uA1Y z&(DFSfPjqrlKkR~`~n5%U{i(g%)FHR@?ucrfJ5HOCABECEH%ZgC_h&L9J*GSSZp^l zcXo7hG&8U?GIjy`+S$a_!ob|z(9Oiy)YQ^R392`RoDkEuQ?StoB@Lvc0uu^yaRV{I zsT!2R?GzAMCp9m{R;ftI-cIMzv@Hw_tP?$5978H@y_tJ^(qjc4m$M=N{!hQTYHiA~ zGL;ECBy#-TJEs|L~@~FyMg0dgXt;xHr`Be8}9h_vgQwzE9_$m%qCFThU?L zr@g!rSKo43{iQCa-2QK@~dEchPDb?J_bLn$CYooFPzh|nj|;=X@88ztR!1&F$-Sk#+@+NErbJ@eNyNs_Dv3t7!MKbrpX8 z@|M{5>n`%QOiKS%A2hvly2Cl{(T0W3cf?fpsUF&{GwH^AeQw((<^8I6t;>U=*FWdn z<+C^DHIu|KUu&)l)pJrdRVl5Stn#3UNhW=HP1ODsv)txSjc}N0&Ca++w07R(>r6dU zl77sPn;pq@^ZnKP_l395v3Ae-_9x;>qYul5Z@cEaaNufCd6<^*E%f?8po4(-L1Gsu#W@;O6D^QWG1PY!3u-ua9mB;c*BkPiB&lHkegqIAab&=KTBj z*ekDYl`~J^-o2T=bkG2sl&cJeC@xY4N^Ds=3aF$kmGRbU<~muDi6N> z+47pO>!0%-?Ga0UXDaS!c$xEQtF*sDgE`aooR-dGe+7kk7G7?eF!80BV~eXsV3qyL zz2}@={q^&9eq8b`Zg*mBoWLdJzs088=jShxJlA_&cX#V~UbBbqlw%Hv<|Xf6pSWpj zuek0Ng@o5vR|l^jC$!o{YNNw5KL++qU~bzcbVv&bA$ywezcX)#^QE z^05c6E!nqsF87C3u}fF{@|qd$*SKV&LV3~26+apk3LF%k<^Gv>F!sjZ=y?qM*7I5u zA58Wr2rl{+dQkOebhql3ncJrAD=xV(OWV8mLu&m^1&*EBRllDfabDV%Gx_Duw4c09 zrz#t+@`Y{k3y=O3yH(LVT!lq3`>;00%B%aY{wX=FQJ!?xdh>+TkChAzj1HWPk6y-~ zEl^#)Wand+^UP{X_hd8vW6F*`!>GsLW3cJ3Jx@>4`M>YhN6DXCT3_#FwMREw*=v6M z7m`#n-kw-*rCS!M$U0?Y*^?73s0P zKaYDHijsY7Wb}w%eDVV4$MT#7PbWNE^w{5R*0p6vv?ngu-QH-*F59%Pw|)!DS*iVZ zSQngnnSV?_t9knE<7aF7;@4IzTC!>F@k5zi3xyQD-!1C?RYC2ww< zx4JQ~H2+%Bnf+2T@|)ZA7(UytU#k7lkHhI&n+nIpGljv5Of#76XH@Dm$efkCZ1JU# zlRLqhL(1kJD+33E0z(5s0x#1Qt-6C}+Z%VTJ^QfSZa!Q68=D5v7i?mEj5EX)I9LQ2 zY^E`o?!U^MC&%I?E%V`LKYNov45(GZ1T}(z+KdE?f1Cyk@qRl#u8A_N0yTL&UHx3v IIVCg!09YZ!u>b%7 diff --git a/Examples/text/resources/fonts/pixantiqua.png b/Examples/text/resources/fonts/pixantiqua.png index ce422e7e7890a0a0b96beab13cb5e627c9354bef..17ad1ab7d4b7c0eed2f88e6f372aea894319f594 100644 GIT binary patch literal 2739 zcmeAS@N?(olHy`uVBq!ia0y~yU}ykg4rT@hhA$5${$yZaU@Q)DcVbv~PUa;80|QIC zqpu?a!^VE@KZ&di49pAxJ|V6Q3=IDn{{R2~pJ5b?hQP=Rft{T)`xqD)8A^iuf0#LT=By}Z;C z1rt3(J;P+JIo=EmY&@PWjv*CsZ>M$k$yo9@8~^?Pf6h~7)#%a^e}M!;?i@?KKz7y5 zeSV)_ziz+2e*OI@qxkjr^?!5L?`IN~T)F>9IR^3x+I})hxY-c)vH`$3v?BF z-7=Efcz4=ezP2~}S^0g3jU7FYR*1&wm9JskFt^?BnB|&Fxp&_mFkDI1$`+E15JuAnLhf~!rM6stF-@jFSPjjYp z)7;xkpF&GQtp9DBoDwoa=cR*d+dr<2OYS^ODO#`Fp!CvZ@8f)H&nKT2ue>Kc!;Ilo zP;t@zDO)E!dQr4>Td>`kv)aKr-(^@tHZRWPF6wZ9=oz0zPRN*%aq04CNkyP@$EqhCE-SVuXr|ZhkwxL9xMMOQ9?R=rYvfQn! zj_lsvz$3Fa*n$0ci0@3M6aIW6LgoGqQ`G|&xlcZPc*!D}pfi&``!(qG9d5qt6S?`8 zn!7{r*SrgUg*TKMR_nzx9TJ={&D(1Ci!~FsoU?}+`SKEeQpc9xl{i}e(|*(dxh_{Z{P4?66Xiih=%(P z^}5@>E@UzMw2=9Efy+zDwQiQCWkOwhSxk1@b;!BRn}0{5j!Qblt4>us&S+Wq1*U?t zC(T!Me_AA4bzX7f{L_0IQexIQb69IIF1dV^_nH5t=b6(3rq8h#Vo;Q@dMb9{;zk)c zp)l>A^URzpeyW^fl362o?#4!jM2;!fwP!GG%D(aRh~y!D&S>L~mRl_wECSnnJ|=m_ z>|>1f-&lT3N#%+ggJ2rRgB^32xo2^EGaTE-dLh*#^Qa@2Zf;xA+_Mvl(p+9V(JEP5 zd1G;doJ5|@*9q?>cdq7}`CgO-tdhD`%zLJT$!PTo@-`P5|I6SLfs5|v*JmY?K z1;#YFD(B)whmWrP!|KO$ZTnX1?@zYWchGN=O z_cWgj#u{rb+pC|Af}HtyjXk)xSgq31b-1>0ub1qB-1#gT3*DM$^a-7jIrBJ1m2aWV zd%u^Ho_n(meZ=uvtY&GDn{Ms2$EnWbv~6%Lf_mcRZdzVO&P zX{&ipIz`{FdclN=Umsg>t>AMzQ*+>U z`VW)khPxMTP%h($ literal 3003 zcmeAS@N?(olHy`uVBq!ia0y~yU}ykg4mJh`hQoG=rx_R+BuiW)N`mv#O3D+9QW+dm z@{>{(JaZG%Q-e|yQz{EjrrIztFsEdOM3hAM`dB6B=jtVb)aX^@7BGN-jeSKyVsdtB zi9%9pdS;%j()-=}l@u~lY?Z=IeGPmIoKrJ0J*tXQgRA^PlB=?lEmM^2?G$V(tSWK~ za#KqZ6)JLb@`|l0Y?Z*~TICg6frRyy6u?SKvTcwn`Gtf;oFf&jv zGt@IQHZeCh*HJJsFf`CNFw!?P(ls=X%D*TxJu@#c$0a|xG&eP`#M8xAsUo*P zFC{a@%FNi=(aq7!z|zRr#nsr*(8<}v)xyBs+|bR$*wob031$X1y~b{)#)fXL&PGPg zW`>5Y=9Z?GmQKcQre+34E(Rv%W-z^;dBr7(dC93Tdowdrte|?G@ana4E=o--$uA1Y z&(DFSfPjqrlKkR~`~n5%U{i(g%)FHR@?ucrfJ5HOCABECEH%ZgC_h&L9J*GSSZp_O zHZwFaax!x^H8OHFH#D>`GBI^EF>`TsHn4Ouv@lYF>P;ah#PsbHZ1h1%11YJ%go0e$ zKumC|2BmO21w__K%}cRWDpIny(~b7dU|?W>>*?YcQgQ1|Y;@5R1s<1mJO5AJ8hSGA zxLFnRw#}FSPL)V@FmduYAYlHCtw!fXH^ZG5Kep_hU;F>>-*9W2(0xCqZt{P=zjCRG zcD(SbD}GNu-;dhr?6qXy?@voM?fv4jcWwUm#^=eE`!+~Ec~HOT>*b~8=U++|Z1^+( z-O|Im-~Z2i_~4<_?sq!TXEq=Ga>U*-XoH5`UjI(6|0Ob|PbWs(y+5^F+B&23dHCm& zPt~HU4|uiSSaPxaTyg3RnY(pAjS?+=_pEZ*`Ym{Y@Rsj;pHG><9^G87ZTjCr=wwDo z>&*0|Ga*}R4xV_^saq-_Z!&ku-X+iH_4Lo$EWg60ouRPlix~sws@V4`dP1vXZ(O`J z<$BpOP0MBtm)aPEQYg6Cd z@-!isW0j{)0<+B8Z>Mh6Y^@Dkd$}<6P-Fh_6hYt1^ZQTC@p(LFOXvZQ_D>BLk9#sj zO)Fg%x7q1v=%rbZXon}TmDjx=l$$DHY+H!8bXxO)y{ZkYa&#N?qN$S?g7j|Co6E6r{y4k7e zj7+>}!n(c5c7j|J_FD$u5@A}yzhBPOD=j5Wx%KyV6{8DpE`E{T$XmY5%hVJAkyG=9y@7sTG`zzJAR`WLZ zt^3WmMzrGfwvE4xu7AGrhavuJpOC`45X;HQ_ZOTHdnVe$g8}G=WV1TA`iQrV{qG^9G)b&HXwcF z-V&+#uft#Lt5>~l7qtCKtBm8+bJw}f{Meemp{{PK`iA@AH?Pmu+H{Xe*6LW=>EGpR z8P+Ce6u+7(y>s5Ro>SQ;gm=z-<`l;r5EOmptND|yS8IfNGHtvB5>NeXSQ}GV|L^HZ z6^W0pFE6r6UFPEHe8u16_g|+_CKvOBHD(_??XJpPr-&-}SLSDRYPG z(7BkUM*AxNygK@#-gx)%4_;PsHU0}_0#eg^~H4bKk1JcUfw`OuW2% z=Hj0&(hj>WO>NI*(2VhZwCF5fd0$KU`OW2aYqD88*6t~qd9C{Aj`}dMXCfP%HlFL? zzn~v>qJQ1*vc?I@-~YwEW7Mu@dOqoY*`8^$!Z&6ozAxnXsH*(sV^qTK2^(vi`O z&syADe_HxCm`Yoh=+B!XXMaymK5cjALW$b~lb)x|Jv){A%KZFnkFXXo_8q>=5#mBG z?9WXzUcIO;`(*t2xeVz)zI>f}Muzvo5e){-Sj zjN{*goMxx`Q;gnkJ1U+{;P$=bGBe(_T7_}b?|*5Wea+bnzOlc(b?xt;($unAd(Ww1 z&MT{bPObLwzm{jFh}ykBzEa8FvifU?+grxVEzdYEHA_!DaJp-0#LT=By}Z;C z1rt3(J;P+JIo=EmY&o7Tjv*CsZzH%T-Lewkx%2;==l?X7M&7m!4?}IU-@cr;UMg|& zsz1AGD*x{K^K93HelzYTxAI)weecE`2zcJUJ@@(rfr7m;_3^=nzI?4(x>Ue=Rb#i6 z>MAjbEJh8douAfyQE;!Cvs#X$Ve#G{$8}A6V&AYoX3;b%SPluWvKV`9@CYn6Fjtz%{je!Zt$x6 zLL2H>H${3Zk5=fHwy1Du*ryb3e8fbF!$xp{+E+){U6HF_^fGv>^3P>i;Cx3gVoB!Q z>B+nG8O)5cl$yF3?wp#{mD&9wRW^BLV#}1|w$1-VHx!92IR1SF!`01wea2m1ax6Es z`!~G#!I_ZDIYGC*Gd#}OHY{b0=UOp?D?hc;V=XtmT2=U)Y0rc{hNiX`EGd5#SBXjN z(q2#&T*Ld8D?%>XDnaDIxt(G+1I|3SGUc~)|5=MI{O)BO0lV5JrN~|lNkccZyLqUjnmY6oscCW z_4X}C)|n{+X;)Mf`Z;B}J^H6lFcSDG^E>IKU-c)SsAQo^k;T@#-54%yHPx1z>)<6B z&AK8s&$3C%SjnH|29t0a!)n{wQjnh`KhVlO5xQlQ>p^g4yAlyXIUa( zn9KVrbaC*iO|v*AUp#HscEfU^gfctJk#+N`mQOx^Vr8wv$r-|{u1ye{5P5i0i95ru z8}FCi58L)5@@<(l)ASyfP~)ZwzlP0X+_l9I%+6}YOkKNaXI9~~7K4egjM)#&Vpm6= zm^6Q`s-n*m5e3HhILpRs;qMZ%A1ym$al5fO;Vx^hNW<}+aeQt(d=g(Te80W5qU`a? zts73pP2e~!e4$N7)wA-n_JNn59ndi~^Z)R-pWc4iQ)pBAnm}0j34|DKoey)b83~sA@7j*kLiQE@H@VxWzgFcB) zCdH$TzLz#vGVME)#&|3HqlKGXwryfO!vfFHd^={A8}pVs*nNKV@X?ONOtS=xRQ6O<~5Z=Q(mXcKGhocUZ3|uXg8O zriei>PlW$`p-&eyW~VgW={LP~XsgmQua(N78$MJp#T_hSj}|shJ$92%hUK+hh7Ic< zb(WgSk1Q(73O1!_=U8|7b1{p6)zxOjo6 zw>L|M@sS@v&!;=(O`Xhj>zwN^NiDrK*0Jk36#V4%p4zT@dz^KHnA*c_n(qU1#TmKH zm6{U&hdJbGod2%Q^1@MQ#i|@@6F0dmJ`1=o?Jd} z=W5Gn-RlQv`ZvWD|>x%S%#M5 z;hwy+i}R;%ndG!RfQmpotJ~(^=?Rj*lRZ2-zmQF z-P9ye<2s*){Q-r?U&U#L876~+Pb2Mybya`0WYk~z+fRh$*2XegT$L(lua=D1lUbv7 zOWY>vxB7=^4FBYMrcYRJ8@BCMoV`xNxBprV)$+mz@;iC|Y)bhPHGTd3cdYM~-J#=SQ`8BMa`?M5dmzjv_UpeaUX=XIF{;}kPBasaK zTQu3%tT-*L$K>#$)~R8ZkEP<{xtGds=d4n=ROi63dmguhB%9l1Yo?k==e9dhQL%A)>lIFmro3DQR#F?_?)+Or~w&x~tbREAPwlC%H28ON2m)AayKfGVW zK=JKsrUEyur;#h~_%`2r9M|@(lrcVTc|-64%?Ba{To$ZznEV*AaHq4z=+!fHA7cN! T(Lgl~)MW8=^>bP0l+XkKoF*7U literal 2912 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 T^Uq=ewRt^V{an^LB{Ts5Z#%Ai diff --git a/Examples/text/resources/fonts/romulus.png b/Examples/text/resources/fonts/romulus.png index 46ccc3273afd654294183699d9c17909999c4bbb..648aa8b06fa9292b3da92decaab7b352b7d1cfa5 100644 GIT binary patch literal 2702 zcmeAS@N?(olHy`uVBq!ia0y~yU}ykg4rT@hhA$5${$yZaU@Q)DcVbv~PUa;80|QIC zqpu?a!^VE@KZ&di49pAxJ|V6Q3=IDn{{R2~pJ5b?hQP=Rft{T)`xqD)8A^iuf0#LT=By}Z;C z1rt3(J;P+JIo=Emtj|4N978JN-bQp!y5+&c^ZWn*IbXal_3YKTX~hv;dhKAz>aPXK z1?wioZ#O@_{&qgwIW_IDU9XnBzO4{;V#cL&>~c~+W|Umb-*0c1Coexq$vbv};nKPM zIc$4`)$i2^3JN4LhfVQc?Bfx}aD>Znq3_Ep8<}4B^9a;AKdD_YXM2iaL+Xrav$(~t zx$J6Ny+pCYoq3nYZ%LVlX#shcxfZYB`N8LLHM>CVPv^5!Y;Uck1rj?$Wtj4d^<PHK3ldt&SHz9oiF8``Vptl%v2OPR>` z?ZXv;MB{+nHC#_`-dy(j(M@5=Ni$Y;>Rl~ta%U5}QF7_4?*>`9z-3pCbI!|DSOfO? zkpr`p%OCU|XWM^w=xe~XWx~v zz&vfgRoR2?5Ho?8vkPC!9lIvCC1&S@{+tgP4c#|ylu7-#B+{{Gcdzo*ZG0r)Joi+MIUFWxIO^&C^x(nAIJ zFWqIc5l~SGW1h@h%YI;5;8m^HQt?_3Q;zrweOS-qqxa^%!(GNYrCgB}Wdd8f!atu3 zEGsqde-$Duyevp{{R^w-xegy0Hk>*cw$kPH5wnV(`vwR4h3zhM+D*4BYT19}{hdaY z=u~eB_J@k64$NNs&SAHa=eBO|eV3BHZ#co%A)lmD{3Um6?;4<$XR}UUh@7 zvgH)3+!n@d3hCm3Z#PBObcDa$oXl$YI%@3*~4w)pBJD6??N|4R(z zlTt*#8a9M(z0KRrcrDxOLAZwGy*Fi_E!XSDOFCrD-PHf^im~Vmp?e9JvY2OWo5LG2 z)7wM(>v|rY8bwJtSDhtY&wHnON3i8Gn9O&6`){h(RXv7cA?EdhuihuzJ@Be>am$N_ zE4LdKUr@QJr}xvVJNJdQrBj*1o+}J8CGIEqI<8AaSUHtB962z1@%sZ=Z&UVhCSKP1 zxn$pC$KD^xJTE3bn0S1}iuntsvV6FV%b}zCJP$(JO|+Y|HcfOjU7~l=NV-So>&+Fnn?L6qSby|@ z7lU3`b^}vz*Q7sb&F0Hh)vt7DJ#*(+rNg4%c`d|G@WCQi$%G~jA&uf2%1;Xo4US4Y zIKZP+C3fWcr#<%V>s3GPWZbsQ=h2?fMfz>VY+tOO70gPR-1GaX#xZf`3+Bu#Cubc= zZTZ~%>Yw2P39~OA7Us7mh19-a9HY)_{TN=&X?>F*R&S7!iJYj9_ zg$1Ae*dMh^K1g;vlDud!tF3-YSDK>j{>6^Z=kgtS$Ty`?M){98^XWH&2Xh$a3naFj zxa@CnS)uh$<6V~Y&@iFg)x;<1Xx8I^~;Au}^p?7B45c44)= zRKi-;zt%Hmc5M8V+n*oOHP3d@jqmRc)G~K?1+#}3Zg!co!g9J2bI8mO2coZOzH6G~ zwe@6kspG<;xs09rHV9}x;Z-%g$x!;us>Nu*me#H`#bgG`POOzP$kCjTYWLmUjD@8D(0TC2PWJauwoVuKMfD zykl3~;*ajn>SLuF$1;1l_*xx&-vP#y3y(v!!XjojJ(0sm2{)7Eu^W&)xj0z-o@Wim`F;8zi ieE=W#|L(@yZ~4U=PTiY7-{S(PwczRM=d#Wzp$P!{m-+Gl literal 2932 zcmeAS@N?(olHy`uVBq!ia0y~yU}ykg4mJh`hQoG=rx_R+BuiW)N`mv#O3D+9QW+dm z@{>{(JaZG%Q-e|yQz{EjrrIztFsEdOM3hAM`dB6B=jtVb)aX^@7BGN-jeSKyVsdtB zi9%9pdS;%j()-=}l@u~lY?Z=IeGPmIoKrJ0J*tXQgRA^PlB=?lEmM^2?G$V(tSWK~ za#KqZ6)JLb@`|l0Y?Z*~TICg6frRyy6u?SKvTcwn`Gtf;oFf&jv zGt@IQHZeCh*HJJsFf`CNFw!?P(ls=X%D*TxJu@#c$0a|xG&eP`#M8xAsUo*P zFC{a@%GAZc(!kKn!otzm#nsr*(8<}v)xyBs+|bR$*wob031$X1y)NdCrsigrjz&h# z#)gKj=1wk-CeB6{22L(!P6j4UhA_RJdBr7(dC93Tdowdrte|==@#?j5E=o--$uA1Y z&(DFSfPjqrlKkR~`~n5%U{i(g%)FHR@?ucrfJ5HOCABECEH%ZgC_h&L9J*GSSZp^l zb9QudG&8U?!sTm--V|~|Oy5qyMjwub9`^R(acGtAn$&9~y;ypxYTr}do*dwu`e+PZaL=1R`a{a640N9C-q_xIl{&%RW{ zu%q{P@Pq&F=l}2javG*FEU;#Ny!KMqj1{5`9S7y}`~L;>Gb>zHJM*oeQ}@8}#r7J{e0JvV z`>96doP32c8t3$ihu{MY1Ti5&; z7-l)JF-+Ukaa5PVxN^q&bt`X9i(uMmmHy31FGZ?#y)LJ2@oo7ehl?y_JN7Qx=+AIL zEhP5b((vtlci1A4`?fGv9R8TY@TEDoA%r=_@ORxI zu?vS3yhWbQ`plGd;AoaiKK~8w2YWhpiC>Ulh?&a%;-QQDLFNS~?oI#1aGk}0ebqk; zrH-eJEDVN?_Zb*Y=Bi$2`02ID_eG-ggA=E&zBOthxttKB1-OoGu+PQMimW>NU#UGqx3aZ`M)^SVVr^8i=gKFw* z2LiLow|dE}%ul=2$K+tzWl^VgNVTcReC6bQ*1`>vr-lEs{a?^_#`0B|W!XLFaGw8W z`_ct#?+c3?Xut03JI=gCX|dU%eIF}t2%p|jdoR&=^NT)){ktr*=UcBkJ1-%s(CC*4 zLxh*$)s+`5il!Alt+*5*(|DW7YQYhKz$Y(PY%H>@+$z9u=DesZgGp4^24&);={yj&U4%jVLR3fNir0a z^M7PYZ1OFYW?-MdWp?2CM~0o==JC(GYz}mpso6AiC@?xO?9gXW*)D1)6Z3G<%&QYw zGXo|Z&XHfzb!+-pM%JZ2j<36#_a@}fa}9~xhgP5cDz$X=G*O1I zrT&Z!+(}RVnXOvfo_Eod(O^G&y#T{1N1ij2LLI)GWq9zrnu+0+i}SXs&zle2@fQAM zQ2O?+^K;u9hSjn@A#AJf(!uwCYPqdm-4nS4<~n~v*yoM{$3V`Uve^@ zvJ9e=mVMKhUdZqv|C|`ZG^56^3NHK_rviB=*a`$PSd?&|(DMk(V?3JwpriLdhv|{& zuB;8_*$oCoV8B~}WTo@*BFbFX^C^2}jFm%#a@c9XQCLV?tWz74NR8NJ1+QFW#elF{r5}E+= CbeX3B diff --git a/Examples/text/resources/fonts/setback.png b/Examples/text/resources/fonts/setback.png index 086f3e27b346617e2b1d3f8b1f18168b8592e16d..1630a73302d4decc2f52488a257627bda454ef3c 100644 GIT binary patch literal 2517 zcmeAS@N?(olHy`uVBq!ia0y~yU}ykg4rT@hhA$5${$yZaU@Q)DcVbv~PUa;80|QIC zqpu?a!^VE@KZ&di49pAxJ|V6Q3=IDn{{R2~pJ5b?hQP=Rft{T)`xqD)8A^iuf0#LT=By}Z;C z1rt3(J;P+JIo=Emta_d8E38Q%|9`Rxt2MeC>TC`SlvPM|@#0(*= zBiTvIW--JIJSl8UPYij!i|Oj2Ii1CoQIoeBis&BmxhtUHEE31+7TfCMcl6xFezhJK z5BFywkG&a_dKPsRR-U~U+8kAQj2Ev7_;ha#4rA)3InKu@$cinCFXpNb6QFaDL<kWd0%h>pae@2A|Ve3Rsi2C;UyUxfoSr5iL8W+~2LnPIQYaJ|E`-Rb0nXu#FI*|AKOVY`@TkCSTjj;XKb{E9j#5*~8GqqTm2L-LM==Sm$l_MEz`%ksd? z^a4{~;>Tp$nol#rV>0|MUDE&Sed20&&Bgc+%YU3Lt77tA`BcbPiDky5{sfL0af^1O z9C)x@bxyVG7w5jhjw=szCi&0#w8@=yh31OlStogx*{Czf)#x@DaC)qg;c*mqi5 z*d-PBB%J9(f4U$ZXvovB>7mqo!bcqzN( z)gLF6FNj1W%Jjq z)v|A2{Y9DS%d@_==LJ*axITm#)$G$~2o8Js+uz}?y~2V0$N!#h^-ta=HhE9ydclTV z<6Zk%WIo&Vx*p#7iLFol!r>nRrEw|_(toc?&S6!#UOAVcvS62IL*5fB=Z2RnK4+kV%Ua(?`({5n?=}~Mj zU;n3LL({qX%?vz`Ur6b^?{#kY_G*tq!?#k#XAM6&4gLu+&brMqVJ@qJ%I`YHTg&s+ zw5JGgUO4(%)j{lU{IbP0l+XkKB-D;s literal 2539 zcmeAS@N?(olHy`uVBq!ia0y~yU}ykg4mJh`hQoG=rx_R+BuiW)N`mv#O3D+9QW+dm z@{>{(JaZG%Q-e|yQz{EjrrIztFsEdOM3hAM`dB6B=jtVb)aX^@7BGN-jeSKyVsdtB zi9%9pdS;%j()-=}l@u~lY?Z=IeGPmIoKrJ0J*tXQgRA^PlB=?lEmM^2?G$V(tSWK~ za#KqZ6)JLb@`|l0Y?Z*~TICg6frRyy6u?SKvTcwn`Gtf;oFf&jv zGt@IQHZeCh*HJJsFf`CNFw!?P(ls=X%D*TxJu@#c$0a|xG&eP`#M8xAsUo*P zFC{a@%GBJz(!kKn!otzm#nsr*(8<}v)xyBs+|bR$*wob031$X1y>3p9&ZZ_N=0--& zriO;D=8mo=ZWb;UE-p@n#uko7hA_RJdBr7(dC93Tdowdrte|?$@ana4E=o--$uA1Y z&(DFSfPjqrlKkR~`~n5%U{i(g%)FHR@?ucrfJ5HOCABECEH%ZgC_h&L9J*GSSZp_O zG&3|Yax!x^H8OHFH#D>`GBI^EF>`TsHn4Ouv@lYF>P;ah#PsbHZ1h1%11YJ%go0e$ zKumC|2BmO21w__K%}cRWDpIny)306J#=yWP>*?YcQgQ3e+=r8vDDbpA{3}0e^{w5j zOHEYf3OLMtCm&sWd_mKEMU@9v!lJaVTwnE%;eyxRX;be1x37Cw>u&RF>7KuT-uL{v zwDHyc_uCg{Z~M*ia`lOy#{E|{w=?|szf;EQzjla-pYI}QI@*JuypgQgG?q%gQJ%FYBPM;vXW0W zTZuuCY5nsH=Tojv-}l>+rDEMr;UkZByfk7s`#FRw%(pp{!;GI{7QaCfc`-;c285yqGOEZ2rCp4>g-fi=}5i$wp3}-uXdyX+K<7d1t#(70{ z|8!TT&5Sd`{TSF77R=xY(zLR7-F>RM{`Y1&julj%{S|^?s9o=3^Lx#O!Tn^sX~zXh}pxKg!jK{(X3!<;ky;88*z@v4`!p zbAt@iCgyO{8*OY+TYMOb5=`3~)R`_M2y3+WymFAXV-DA6P%uk-I9L3$;DqRW`?D*q zX1uezz?jjOTzM@(fni3u*KF1w^Djhxy&l!T_JhNhC)WN3lZ|A$d?E|I}Z#N4CXrFGZo;;W5lcnv~58Icz2^K!j zO*PV9Zx{A1Ld>rG)}_xIp0`f?`1AL?Cuev4lVxBy&$@_O*Ki8jNl< zzE0x#%;0dmLPu=kMK>OXjqhxg8h1Z>RK4!uuHBi*|AiW?Rd;V=bf{fxq;p_>WcImF z8F#CU7VrJ?Zu!Np%bQkDXqt4p;C#{FQ}zru9(o?1tSET=^(&pk)g5cUvd`n@=kqtNW|%d+m+O>E{`3vizFc`}BRg-fwX} z6>Vq3q9CZZa<$F=Zxb!g>=AAFSjsQVn8AE`Sq{Uzuzh(CPpdG@l2YBE+;g9uVVBjf zP_YH}|J508GoIiKaJgUFzo+Z#x!ncsr^9vY*%?mMPR;%^-Ec?ydAl-|M0bW|_a1as z{|FK)V@bFv9CzfGB}2^q=^PG{uYOcBKDd8W=5>1xcf$|EZ_g|@E_$6(pbbDLQ^L2s^)l3Ph%~FgJ{0DY2*V;QYusS3$m?)b( z`qRj=DxcBj_pdEKH-4RGEz+=uLy?uA@y5M9b_}=d_6Bk%ux4`}NaId;du1vA2L|~E zuh>&`S|ZH3AD9$8)KL&po-fLtppYTRkbH8{y~(qMIj@}aU&#=_(xAj3!nlBg!IeRS l$w82ziw;6ji|v_s7`m3#PLG%-av9Y8@^tlcS?83{1OT_&;aC6w diff --git a/Examples/text/text_bmfont_ttf.cs b/Examples/text/text_bmfont_ttf.cs index e81bc47..7313f41 100644 --- a/Examples/text/text_bmfont_ttf.cs +++ b/Examples/text/text_bmfont_ttf.cs @@ -1,7 +1,7 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class text_bmfont_ttf { - /******************************************************************************************* * * raylib [text] example - BMFont and TTF Fonts loading * * 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) * * Copyright (c) 2016 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [text] example - bmfont and ttf sprite fonts loading"); const char msgBm[64] = "THIS IS AN AngelCode SPRITE FONT"; const char msgTtf[64] = "THIS SPRITE FONT has been GENERATED from a TTF"; // NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required) Font fontBm = LoadFont("resources/bmfont.fnt"); // BMFont (AngelCode) Font fontTtf = LoadFont("resources/pixantiqua.ttf"); // TTF font Vector2 fontPosition; fontPosition.x = screenWidth/2 - MeasureTextEx(fontBm, msgBm, fontBm.baseSize, 0).x/2; fontPosition.y = screenHeight/2 - fontBm.baseSize/2 - 80; SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update variables here... //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawTextEx(fontBm, msgBm, fontPosition, fontBm.baseSize, 0, MAROON); DrawTextEx(fontTtf, msgTtf, new Vector2( 75.0f, 240.0f );, fontTtf.baseSize*0.8f, 2, LIME); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadFont(fontBm); // AngelCode Font unloading UnloadFont(fontTtf); // TTF Font unloading CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [text] example - BMFont and TTF Fonts loading * * 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) * * Copyright (c) 2016 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [text] example - bmfont and ttf sprite fonts loading"); string msgBm = "THIS IS AN AngelCode SPRITE FONT"; string msgTtf = "THIS SPRITE FONT has been GENERATED from a TTF"; // NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required) Font fontBm = LoadFont("resources/bmfont.fnt"); // BMFont (AngelCode) Font fontTtf = LoadFont("resources/pixantiqua.ttf"); // TTF font Vector2 fontPosition; fontPosition.x = screenWidth/2 - MeasureTextEx(fontBm, msgBm, fontBm.baseSize, 0).x/2; fontPosition.y = screenHeight/2 - fontBm.baseSize/2 - 80; SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update variables here... //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawTextEx(fontBm, msgBm, fontPosition, fontBm.baseSize, 0, MAROON); DrawTextEx(fontTtf, msgTtf, new Vector2( 75.0f, 240.0f ), fontTtf.baseSize*0.8f, 2, LIME); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadFont(fontBm); // AngelCode Font unloading UnloadFont(fontTtf); // TTF Font unloading CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/text/text_bmfont_unordered.cs b/Examples/text/text_bmfont_unordered.cs index bee9caa..7ecb238 100644 --- a/Examples/text/text_bmfont_unordered.cs +++ b/Examples/text/text_bmfont_unordered.cs @@ -1,7 +1,7 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class text_bmfont_unordered { - /******************************************************************************************* * * raylib [text] example - BMFont unordered chars loading and drawing * * 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) * * Copyright (c) 2016 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [text] example - bmfont unordered loading and drawing"); // NOTE: Using chars outside the [32..127] limits! // NOTE: If a character is not found in the font, it just renders a space const char msg[256] = "ASCII extended characters:\n¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆ\nÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæ\nçèéêëìíîïðñòóôõö÷øùúûüýþÿ"; // NOTE: Loaded font has an unordered list of characters (chars in the range 32..255) Font font = LoadFont("resources/pixantiqua.fnt"); // BMFont (AngelCode) SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update variables here... //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText("Font name: PixAntiqua", 40, 50, 20, GRAY); DrawText(FormatText("Font base size: %i", font.baseSize), 40, 80, 20, GRAY); DrawText(FormatText("Font chars number: %i", font.charsCount), 40, 110, 20, GRAY); DrawTextEx(font, msg, new Vector2( 40, 180 );, font.baseSize, 0, MAROON); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadFont(font); // AngelCode Font unloading CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [text] example - BMFont unordered chars loading and drawing * * 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) * * Copyright (c) 2016 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [text] example - bmfont unordered loading and drawing"); // NOTE: Using chars outside the [32..127] limits! // NOTE: If a character is not found in the font, it just renders a space string msg = "ASCII extended characters:\n¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆ\nÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæ\nçèéêëìíîïðñòóôõö÷øùúûüýþÿ"; // NOTE: Loaded font has an unordered list of characters (chars in the range 32..255) Font font = LoadFont("resources/pixantiqua.fnt"); // BMFont (AngelCode) SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update variables here... //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText("Font name: PixAntiqua", 40, 50, 20, GRAY); DrawText(FormatText("Font base size: %i", font.baseSize), 40, 80, 20, GRAY); DrawText(FormatText("Font chars number: %i", font.charsCount), 40, 110, 20, GRAY); DrawTextEx(font, msg, new Vector2( 40, 180 ), font.baseSize, 0, MAROON); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadFont(font); // AngelCode Font unloading CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/text/text_font_sdf.cs b/Examples/text/text_font_sdf.cs index 4206778..43ec445 100644 --- a/Examples/text/text_font_sdf.cs +++ b/Examples/text/text_font_sdf.cs @@ -1,7 +1,20 @@ using Raylib; using static Raylib.Raylib; +using static Raylib.TextureFilterMode; -public partial class Examples +public partial class text_font_sdf { - /******************************************************************************************* * * raylib [text] example - TTF loading and usage * * This example has been created using raylib 1.3.0 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [text] example - SDF fonts"); // NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required) const char msg[50] = "Signed Distance Fields"; // Default font generation from TTF font Font fontDefault = { 0 }; fontDefault.baseSize = 16; fontDefault.charsCount = 95; // Parameters > font size: 16, no chars array provided (0), chars count: 95 (autogenerate chars array) fontDefault.chars = LoadFontData("resources/AnonymousPro-Bold.ttf", 16, 0, 95, false); // Parameters > chars count: 95, font size: 16, chars padding in image: 4 px, pack method: 0 (default) Image atlas = GenImageFontAtlas(fontDefault.chars, 95, 16, 4, 0); fontDefault.texture = LoadTextureFromImage(atlas); UnloadImage(atlas); // SDF font generation from TTF font // NOTE: SDF chars data is generated with LoadFontData(), it's just a bool option Font fontSDF = { 0 }; fontSDF.baseSize = 16; fontSDF.charsCount = 95; // Parameters > font size: 16, no chars array provided (0), chars count: 0 (defaults to 95) fontSDF.chars = LoadFontData("resources/AnonymousPro-Bold.ttf", 16, 0, 0, true); // Parameters > chars count: 95, font size: 16, chars padding in image: 0 px, pack method: 1 (Skyline algorythm) atlas = GenImageFontAtlas(fontSDF.chars, 95, 16, 0, 1); fontSDF.texture = LoadTextureFromImage(atlas); UnloadImage(atlas); // Load SDF required shader (we use default vertex shader) Shader shader = LoadShader(0, "resources/shaders/sdf.fs"); SetTextureFilter(fontSDF.texture, FILTER_BILINEAR); // Required for SDF font Vector2 fontPosition = { 40, screenHeight/2 - 50 }; Vector2 textSize = { 0.0f }; float fontSize = 16.0f; int currentFont = 0; // 0 - fontDefault, 1 - fontSDF SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- fontSize += GetMouseWheelMove()*8.0f; if (fontSize < 6) fontSize = 6; if (IsKeyDown((int)Key.SPACE)) currentFont = 1; else currentFont = 0; if (currentFont == 0) textSize = MeasureTextEx(fontDefault, msg, fontSize, 0); else textSize = MeasureTextEx(fontSDF, msg, fontSize, 0); fontPosition.x = GetScreenWidth()/2 - textSize.x/2; fontPosition.y = GetScreenHeight()/2 - textSize.y/2 + 80; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); if (currentFont == 1) { // NOTE: SDF fonts require a custom SDf shader to compute fragment color BeginShaderMode(shader); // Activate SDF font shader DrawTextEx(fontSDF, msg, fontPosition, fontSize, 0, BLACK); EndShaderMode(); // Activate our default shader for next drawings DrawTexture(fontSDF.texture, 10, 10, BLACK); } else { DrawTextEx(fontDefault, msg, fontPosition, fontSize, 0, BLACK); DrawTexture(fontDefault.texture, 10, 10, BLACK); } if (currentFont == 1) DrawText("SDF!", 320, 20, 80, RED); else DrawText("default font", 315, 40, 30, GRAY); DrawText("FONT SIZE: 16.0", GetScreenWidth() - 240, 20, 20, DARKGRAY); DrawText(FormatText("RENDER SIZE: %02.02f", fontSize), GetScreenWidth() - 240, 50, 20, DARKGRAY); DrawText("Use MOUSE WHEEL to SCALE TEXT!", GetScreenWidth() - 240, 90, 10, DARKGRAY); DrawText("PRESS SPACE to USE SDF FONT VERSION!", 340, GetScreenHeight() - 30, 20, MAROON); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadFont(fontDefault); // Default font unloading UnloadFont(fontSDF); // SDF font unloading UnloadShader(shader); // Unload SDF shader CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [text] example - TTF loading and usage * * This example has been created using raylib 1.3.0 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [text] example - SDF fonts"); // NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required) string msg = "Signed Distance Fields"; // Default font generation from TTF font Font fontDefault = new Font(); fontDefault.baseSize = 16; fontDefault.charsCount = 95; + // Parameters > font size: 16, no chars array provided (0), chars count: 95 (autogenerate chars array) + // TODO: fix conversion + //fontDefault.chars = LoadFontData("resources/AnonymousPro-Bold.ttf", 16, null, 95, false); + // Parameters > chars count: 95, font size: 16, chars padding in image: 4 px, pack method: 0 (default) + //Image atlas = GenImageFontAtlas(fontDefault.chars, 95, 16, 4, 0); //fontDefault.texture = LoadTextureFromImage(atlas); //UnloadImage(atlas); // SDF font generation from TTF font // NOTE: SDF chars data is generated with LoadFontData(), it's just a bool option Font fontSDF = new Font(); fontSDF.baseSize = 16; fontSDF.charsCount = 95; + // Parameters > font size: 16, no chars array provided (0), chars count: 0 (defaults to 95) + // TODO: fix conversion + //fontSDF.chars = LoadFontData("resources/AnonymousPro-Bold.ttf", 16, null, 0, true); + // Parameters > chars count: 95, font size: 16, chars padding in image: 0 px, pack method: 1 (Skyline algorythm) + // TODO: fix conversion + //atlas = GenImageFontAtlas(fontSDF.chars, 95, 16, 0, 1); + //fontSDF.texture = LoadTextureFromImage(atlas); //UnloadImage(atlas); // Load SDF required shader (we use default vertex shader) Shader shader = LoadShader(null, "resources/shaders/sdf.fs"); SetTextureFilter(fontSDF.texture, (int)FILTER_BILINEAR); // Required for SDF font Vector2 fontPosition = new Vector2( 40, screenHeight/2 - 50 ); Vector2 textSize = new Vector2( 0.0f ); float fontSize = 16.0f; int currentFont = 0; // 0 - fontDefault, 1 - fontSDF SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- fontSize += GetMouseWheelMove()*8.0f; if (fontSize < 6) fontSize = 6; if (IsKeyDown(KEY_SPACE)) currentFont = 1; else currentFont = 0; if (currentFont == 0) textSize = MeasureTextEx(fontDefault, msg, fontSize, 0); else textSize = MeasureTextEx(fontSDF, msg, fontSize, 0); fontPosition.x = GetScreenWidth()/2 - textSize.x/2; fontPosition.y = GetScreenHeight()/2 - textSize.y/2 + 80; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); if (currentFont == 1) { // NOTE: SDF fonts require a custom SDf shader to compute fragment color BeginShaderMode(shader); // Activate SDF font shader DrawTextEx(fontSDF, msg, fontPosition, fontSize, 0, BLACK); EndShaderMode(); // Activate our default shader for next drawings DrawTexture(fontSDF.texture, 10, 10, BLACK); } else { DrawTextEx(fontDefault, msg, fontPosition, fontSize, 0, BLACK); DrawTexture(fontDefault.texture, 10, 10, BLACK); } if (currentFont == 1) DrawText("SDF!", 320, 20, 80, RED); else DrawText("default font", 315, 40, 30, GRAY); DrawText("FONT SIZE: 16.0", GetScreenWidth() - 240, 20, 20, DARKGRAY); DrawText(FormatText("RENDER SIZE: %02.02f", fontSize), GetScreenWidth() - 240, 50, 20, DARKGRAY); DrawText("Use MOUSE WHEEL to SCALE TEXT!", GetScreenWidth() - 240, 90, 10, DARKGRAY); DrawText("PRESS SPACE to USE SDF FONT VERSION!", 340, GetScreenHeight() - 30, 20, MAROON); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadFont(fontDefault); // Default font unloading UnloadFont(fontSDF); // SDF font unloading UnloadShader(shader); // Unload SDF shader CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/text/text_format_text.cs b/Examples/text/text_format_text.cs index ff09b99..33f999b 100644 --- a/Examples/text/text_format_text.cs +++ b/Examples/text/text_format_text.cs @@ -1,7 +1,7 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class text_format_text { - /******************************************************************************************* * * raylib [text] example - Text formatting * * This example has been created using raylib 1.1 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [text] example - text formatting"); int score = 100020; int hiscore = 200450; int lives = 5; SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update your variables here //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText(FormatText("Score: %08i", score), 200, 80, 20, RED); DrawText(FormatText("HiScore: %08i", hiscore), 200, 120, 20, GREEN); DrawText(FormatText("Lives: %02i", lives), 200, 160, 40, BLUE); DrawText(FormatText("Elapsed Time: %02.02f ms", GetFrameTime()*1000), 200, 220, 20, BLACK); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [text] example - Text formatting * * This example has been created using raylib 1.1 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [text] example - text formatting"); int score = 100020; int hiscore = 200450; int lives = 5; SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update your variables here //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText(FormatText("Score: %08i", score), 200, 80, 20, RED); DrawText(FormatText("HiScore: %08i", hiscore), 200, 120, 20, GREEN); DrawText(FormatText("Lives: %02i", lives), 200, 160, 40, BLUE); DrawText(FormatText("Elapsed Time: %02.02f ms", GetFrameTime()*1000), 200, 220, 20, BLACK); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/text/text_input_box.cs b/Examples/text/text_input_box.cs index f2a0ede..ef6f2a4 100644 --- a/Examples/text/text_input_box.cs +++ b/Examples/text/text_input_box.cs @@ -1,7 +1,10 @@ using Raylib; +using System.Text; using static Raylib.Raylib; -public partial class Examples +public partial class text_input_box { - /******************************************************************************************* * * raylib [text] example - Input Box * * This example has been created using raylib 1.7 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2017 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public const #define MAX_INPUT_CHARS 9 public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [text] example - input box"); char name[MAX_INPUT_CHARS + 1] = "\0"; // NOTE: One extra space required for line ending char '\0' int letterCount = 0; Rectangle textBox = { screenWidth/2 - 100, 180, 225, 50 }; bool mouseOnText = false; int framesCounter = 0; SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (CheckCollisionPointRec(GetMousePosition(), textBox)) mouseOnText = true; else mouseOnText = false; if (mouseOnText) { int key = GetKeyPressed(); // NOTE: Only allow keys in range [32..125] if ((key >= 32) && (key <= 125) && (letterCount < MAX_INPUT_CHARS)) { name[letterCount] = (char)key; letterCount++; } if (IsKeyPressed((int)Key.BACKSPACE)) { letterCount--; name[letterCount] = '\0'; if (letterCount < 0) letterCount = 0; } } if (mouseOnText) framesCounter++; else framesCounter = 0; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText("PLACE MOUSE OVER INPUT BOX!", 240, 140, 20, GRAY); DrawRectangleRec(textBox, LIGHTGRAY); if (mouseOnText) DrawRectangleLines(textBox.x, textBox.y, textBox.width, textBox.height, RED); else DrawRectangleLines(textBox.x, textBox.y, textBox.width, textBox.height, DARKGRAY); DrawText(name, textBox.x + 5, textBox.y + 8, 40, MAROON); DrawText(FormatText("INPUT CHARS: %i/%i", letterCount, MAX_INPUT_CHARS), 315, 250, 20, DARKGRAY); if (mouseOnText) { if (letterCount < MAX_INPUT_CHARS) { // Draw blinking underscore char if (((framesCounter/20)%2) == 0) DrawText("_", textBox.x + 8 + MeasureText(name, 40), textBox.y + 12, 40, MAROON); } else DrawText("Press BACKSPACE to delete chars...", 230, 300, 20, GRAY); } EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } // Check if any key is pressed // NOTE: We limit keys check to keys between 32 ((int)Key.SPACE) and 126 bool IsAnyKeyPressed() { bool keyPressed = false; int key = GetKeyPressed(); if ((key >= 32) && (key <= 126)) keyPressed = true; return keyPressed; } + /******************************************************************************************* * * raylib [text] example - Input Box * * This example has been created using raylib 1.7 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2017 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public const int MAX_INPUT_CHARS = 9; public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [text] example - input box"); + + StringBuilder name = new StringBuilder(' ', MAX_INPUT_CHARS + 1); // NOTE: One extra space required for line ending char '\0' int letterCount = 0; Rectangle textBox = new Rectangle( screenWidth/2 - 100, 180, 225, 50 ); bool mouseOnText = false; int framesCounter = 0; SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (CheckCollisionPointRec(GetMousePosition(), textBox)) mouseOnText = true; else mouseOnText = false; if (mouseOnText) { int key = GetKeyPressed(); // NOTE: Only allow keys in range [32..125] if ((key >= 32) && (key <= 125) && (letterCount < MAX_INPUT_CHARS)) { name[letterCount] = (char)key; letterCount++; } if (IsKeyPressed(KEY_BACKSPACE)) { letterCount--; name[letterCount] = '\0'; if (letterCount < 0) letterCount = 0; } } if (mouseOnText) framesCounter++; else framesCounter = 0; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText("PLACE MOUSE OVER INPUT BOX!", 240, 140, 20, GRAY); DrawRectangleRec(textBox, LIGHTGRAY); if (mouseOnText) DrawRectangleLines((int)textBox.x, (int)textBox.y, (int)textBox.width, (int)textBox.height, RED); else DrawRectangleLines((int)textBox.x, (int)textBox.y, (int)textBox.width, (int)textBox.height, DARKGRAY); DrawText(name.ToString(), (int)textBox.x + 5, (int)textBox.y + 8, 40, MAROON); DrawText(FormatText("INPUT CHARS: %i/%i", letterCount, MAX_INPUT_CHARS), 315, 250, 20, DARKGRAY); if (mouseOnText) { if (letterCount < MAX_INPUT_CHARS) { // Draw blinking underscore char if (((framesCounter/20)%2) == 0) DrawText("_", (int)textBox.x + 8 + MeasureText(name.ToString(), 40), (int)textBox.y + 12, 40, MAROON); } else DrawText("Press BACKSPACE to delete chars...", 230, 300, 20, GRAY); } EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } // Check if any key is pressed // NOTE: We limit keys check to keys between 32 (KEY_SPACE) and 126 bool IsAnyKeyPressed() { bool keyPressed = false; int key = GetKeyPressed(); if ((key >= 32) && (key <= 126)) keyPressed = true; return keyPressed; } } diff --git a/Examples/text/text_raylib_fonts.cs b/Examples/text/text_raylib_fonts.cs index f556d5b..b5b76a7 100644 --- a/Examples/text/text_raylib_fonts.cs +++ b/Examples/text/text_raylib_fonts.cs @@ -1,7 +1,7 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class text_raylib_fonts { - /******************************************************************************************* * * raylib [text] example - raylib font loading and usage * * NOTE: raylib is distributed with some free to use fonts (even for commercial pourposes!) * To view details and credits for those fonts, check raylib license file * * This example has been created using raylib 1.7 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2017 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public const #define MAX_FONTS 8 public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [text] example - raylib fonts"); // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) Font[] fonts = new Font[MAX_FONTS]; fonts[0] = LoadFont("resources/fonts/alagard.png"); fonts[1] = LoadFont("resources/fonts/pixelplay.png"); fonts[2] = LoadFont("resources/fonts/mecha.png"); fonts[3] = LoadFont("resources/fonts/setback.png"); fonts[4] = LoadFont("resources/fonts/romulus.png"); fonts[5] = LoadFont("resources/fonts/pixantiqua.png"); fonts[6] = LoadFont("resources/fonts/alpha_beta.png"); fonts[7] = LoadFont("resources/fonts/jupiter_crash.png"); const char *messages[MAX_FONTS] = { "ALAGARD FONT designed by Hewett Tsoi", "PIXELPLAY FONT designed by Aleksander Shevchuk", "MECHA FONT designed by Captain Falcon", "SETBACK FONT designed by Brian Kent (AEnigma)", "ROMULUS FONT designed by Hewett Tsoi", "PIXANTIQUA FONT designed by Gerhard Grossmann", "ALPHA_BETA FONT designed by Brian Kent (AEnigma)", "JUPITER_CRASH FONT designed by Brian Kent (AEnigma)" }; const int spacings[MAX_FONTS] = { 2, 4, 8, 4, 3, 4, 4, 1 }; Vector2[] positions = new Vector2[MAX_FONTS]; for (int i = 0; i < MAX_FONTS; i++) { positions[i].x = screenWidth/2 - MeasureTextEx(fonts[i], messages[i], fonts[i].baseSize*2, spacings[i]).x/2; positions[i].y = 60 + fonts[i].baseSize + 45*i; } // Small Y position corrections positions[3].y += 8; positions[4].y += 2; positions[7].y -= 8; Color colors[MAX_FONTS] = { MAROON, ORANGE, DARKGREEN, DARKBLUE, DARKPURPLE, LIME, GOLD, RED }; //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update your variables here //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText("free fonts included with raylib", 250, 20, 20, DARKGRAY); DrawLine(220, 50, 590, 50, DARKGRAY); for (int i = 0; i < MAX_FONTS; i++) { DrawTextEx(fonts[i], messages[i], positions[i], fonts[i].baseSize*2, spacings[i], colors[i]); } EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- // Fonts unloading for (int i = 0; i < MAX_FONTS; i++) UnloadFont(fonts[i]); CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [text] example - raylib font loading and usage * * NOTE: raylib is distributed with some free to use fonts (even for commercial pourposes!) * To view details and credits for those fonts, check raylib license file * * This example has been created using raylib 1.7 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2017 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public const int MAX_FONTS = 8; public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [text] example - raylib fonts"); // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) Font[] fonts = new Font[MAX_FONTS]; fonts[0] = LoadFont("resources/fonts/alagard.png"); fonts[1] = LoadFont("resources/fonts/pixelplay.png"); fonts[2] = LoadFont("resources/fonts/mecha.png"); fonts[3] = LoadFont("resources/fonts/setback.png"); fonts[4] = LoadFont("resources/fonts/romulus.png"); fonts[5] = LoadFont("resources/fonts/pixantiqua.png"); fonts[6] = LoadFont("resources/fonts/alpha_beta.png"); fonts[7] = LoadFont("resources/fonts/jupiter_crash.png"); string[] messages = new string[MAX_FONTS] { "ALAGARD FONT designed by Hewett Tsoi", "PIXELPLAY FONT designed by Aleksander Shevchuk", "MECHA FONT designed by Captain Falcon", "SETBACK FONT designed by Brian Kent (AEnigma)", "ROMULUS FONT designed by Hewett Tsoi", "PIXANTIQUA FONT designed by Gerhard Grossmann", "ALPHA_BETA FONT designed by Brian Kent (AEnigma)", "JUPITER_CRASH FONT designed by Brian Kent (AEnigma)" }; int[] spacings = new int[MAX_FONTS]{ 2, 4, 8, 4, 3, 4, 4, 1 }; Vector2[] positions = new Vector2[MAX_FONTS]; for (int i = 0; i < MAX_FONTS; i++) { positions[i].x = screenWidth/2 - MeasureTextEx(fonts[i], messages[i], fonts[i].baseSize*2, spacings[i]).x/2; positions[i].y = 60 + fonts[i].baseSize + 45*i; } // Small Y position corrections positions[3].y += 8; positions[4].y += 2; positions[7].y -= 8; Color[] colors = new Color[MAX_FONTS] { MAROON, ORANGE, DARKGREEN, DARKBLUE, DARKPURPLE, LIME, GOLD, RED }; //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update your variables here //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText("free fonts included with raylib", 250, 20, 20, DARKGRAY); DrawLine(220, 50, 590, 50, DARKGRAY); for (int i = 0; i < MAX_FONTS; i++) { DrawTextEx(fonts[i], messages[i], positions[i], fonts[i].baseSize*2, spacings[i], colors[i]); } EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- // Fonts unloading for (int i = 0; i < MAX_FONTS; i++) UnloadFont(fonts[i]); CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/text/text_sprite_fonts.cs b/Examples/text/text_sprite_fonts.cs index 7fd1b3d..052bb8b 100644 --- a/Examples/text/text_sprite_fonts.cs +++ b/Examples/text/text_sprite_fonts.cs @@ -1,7 +1,7 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class text_sprite_fonts { - /******************************************************************************************* * * raylib [text] example - Font loading and usage * * 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) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [text] example - sprite fonts usage"); const char msg1[50] = "THIS IS A custom SPRITE FONT..."; const char msg2[50] = "...and this is ANOTHER CUSTOM font..."; const char msg3[50] = "...and a THIRD one! GREAT! :D"; // NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required) Font font1 = LoadFont("resources/custom_mecha.png"); // Font loading Font font2 = LoadFont("resources/custom_alagard.png"); // Font loading Font font3 = LoadFont("resources/custom_jupiter_crash.png"); // Font loading Vector2 fontPosition1, fontPosition2, fontPosition3; fontPosition1.x = screenWidth/2 - MeasureTextEx(font1, msg1, font1.baseSize, -3).x/2; fontPosition1.y = screenHeight/2 - font1.baseSize/2 - 80; fontPosition2.x = screenWidth/2 - MeasureTextEx(font2, msg2, font2.baseSize, -2).x/2; fontPosition2.y = screenHeight/2 - font2.baseSize/2 - 10; fontPosition3.x = screenWidth/2 - MeasureTextEx(font3, msg3, font3.baseSize, 2).x/2; fontPosition3.y = screenHeight/2 - font3.baseSize/2 + 50; //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update variables here... //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawTextEx(font1, msg1, fontPosition1, font1.baseSize, -3, WHITE); DrawTextEx(font2, msg2, fontPosition2, font2.baseSize, -2, WHITE); DrawTextEx(font3, msg3, fontPosition3, font3.baseSize, 2, WHITE); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadFont(font1); // Font unloading UnloadFont(font2); // Font unloading UnloadFont(font3); // Font unloading CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [text] example - Font loading and usage * * 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) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [text] example - sprite fonts usage"); string msg1 = "THIS IS A custom SPRITE FONT..."; string msg2 = "...and this is ANOTHER CUSTOM font..."; string msg3 = "...and a THIRD one! GREAT! :D"; // NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required) Font font1 = LoadFont("resources/custom_mecha.png"); // Font loading Font font2 = LoadFont("resources/custom_alagard.png"); // Font loading Font font3 = LoadFont("resources/custom_jupiter_crash.png"); // Font loading Vector2 fontPosition1, fontPosition2, fontPosition3; fontPosition1.x = screenWidth/2 - MeasureTextEx(font1, msg1, font1.baseSize, -3).x/2; fontPosition1.y = screenHeight/2 - font1.baseSize/2 - 80; fontPosition2.x = screenWidth/2 - MeasureTextEx(font2, msg2, font2.baseSize, -2).x/2; fontPosition2.y = screenHeight/2 - font2.baseSize/2 - 10; fontPosition3.x = screenWidth/2 - MeasureTextEx(font3, msg3, font3.baseSize, 2).x/2; fontPosition3.y = screenHeight/2 - font3.baseSize/2 + 50; //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update variables here... //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawTextEx(font1, msg1, fontPosition1, font1.baseSize, -3, WHITE); DrawTextEx(font2, msg2, fontPosition2, font2.baseSize, -2, WHITE); DrawTextEx(font3, msg3, fontPosition3, font3.baseSize, 2, WHITE); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadFont(font1); // Font unloading UnloadFont(font2); // Font unloading UnloadFont(font3); // Font unloading CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/text/text_ttf_loading.cs b/Examples/text/text_ttf_loading.cs index 751ac7e..67cfb21 100644 --- a/Examples/text/text_ttf_loading.cs +++ b/Examples/text/text_ttf_loading.cs @@ -1,7 +1,8 @@ using Raylib; using static Raylib.Raylib; +using static Raylib.TextureFilterMode; -public partial class Examples +public partial class text_ttf_loading { - /******************************************************************************************* * * raylib [text] example - TTF loading and usage * * This example has been created using raylib 1.3.0 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [text] example - ttf loading"); const char msg[50] = "TTF Font"; // NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required) // TTF Font loading with custom generation parameters Font font = LoadFontEx("resources/KAISG.ttf", 96, 0, 0); // Generate mipmap levels to use trilinear filtering // NOTE: On 2D drawing it won't be noticeable, it looks like FILTER_BILINEAR GenTextureMipmaps(&font.texture); float fontSize = font.baseSize; Vector2 fontPosition = { 40, screenHeight/2 - 80 }; Vector2 textSize; SetTextureFilter(font.texture, FILTER_POINT); int currentFontFilter = 0; // FILTER_POINT // NOTE: Drag and drop support only available for desktop platforms: Windows, Linux, OSX int count = 0; char **droppedFiles; SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- fontSize += GetMouseWheelMove()*4.0f; // Choose font texture filter method if (IsKeyPressed((int)Key.ONE)) { SetTextureFilter(font.texture, FILTER_POINT); currentFontFilter = 0; } else if (IsKeyPressed((int)Key.TWO)) { SetTextureFilter(font.texture, FILTER_BILINEAR); currentFontFilter = 1; } else if (IsKeyPressed((int)Key.THREE)) { // NOTE: Trilinear filter won't be noticed on 2D drawing SetTextureFilter(font.texture, FILTER_TRILINEAR); currentFontFilter = 2; } textSize = MeasureTextEx(font, msg, fontSize, 0); if (IsKeyDown((int)Key.LEFT)) fontPosition.x -= 10; else if (IsKeyDown((int)Key.RIGHT)) fontPosition.x += 10; // Load a dropped TTF file dynamically (at current fontSize) if (IsFileDropped()) { droppedFiles = GetDroppedFiles(&count); if (count == 1) // Only support one ttf file dropped { UnloadFont(font); font = LoadFontEx(droppedFiles[0], fontSize, 0, 0); ClearDroppedFiles(); } } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText("Use mouse wheel to change font size", 20, 20, 10, GRAY); DrawText("Use (int)Key.RIGHT and (int)Key.LEFT to move text", 20, 40, 10, GRAY); DrawText("Use 1, 2, 3 to change texture filter", 20, 60, 10, GRAY); DrawText("Drop a new TTF font for dynamic loading", 20, 80, 10, DARKGRAY); DrawTextEx(font, msg, fontPosition, fontSize, 0, BLACK); // TODO: It seems texSize measurement is not accurate due to chars offsets... //DrawRectangleLines(fontPosition.x, fontPosition.y, textSize.x, textSize.y, RED); DrawRectangle(0, screenHeight - 80, screenWidth, 80, LIGHTGRAY); DrawText(FormatText("Font size: %02.02f", fontSize), 20, screenHeight - 50, 10, DARKGRAY); DrawText(FormatText("Text size: [%02.02f, %02.02f]", textSize.x, textSize.y), 20, screenHeight - 30, 10, DARKGRAY); DrawText("CURRENT TEXTURE FILTER:", 250, 400, 20, GRAY); if (currentFontFilter == 0) DrawText("POINT", 570, 400, 20, BLACK); else if (currentFontFilter == 1) DrawText("BILINEAR", 570, 400, 20, BLACK); else if (currentFontFilter == 2) DrawText("TRILINEAR", 570, 400, 20, BLACK); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- ClearDroppedFiles(); // Clear internal buffers UnloadFont(font); // Font unloading CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [text] example - TTF loading and usage * * This example has been created using raylib 1.3.0 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [text] example - ttf loading"); string msg = "TTF Font"; // NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required) // TTF Font loading with custom generation parameters Font font = LoadFontEx("resources/KAISG.ttf", 96, 0, null); // Generate mipmap levels to use trilinear filtering // NOTE: On 2D drawing it won't be noticeable, it looks like FILTER_BILINEAR GenTextureMipmaps(ref font.texture); float fontSize = font.baseSize; Vector2 fontPosition = new Vector2( 40, screenHeight/2 - 80 ); Vector2 textSize; SetTextureFilter(font.texture, (int)FILTER_POINT); int currentFontFilter = 0; // FILTER_POINT // NOTE: Drag and drop support only available for desktop platforms: Windows, Linux, OSX int count = 0; string[] droppedFiles; SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- fontSize += GetMouseWheelMove()*4.0f; // Choose font texture filter method if (IsKeyPressed(KEY_ONE)) { SetTextureFilter(font.texture, (int)FILTER_POINT); currentFontFilter = 0; } else if (IsKeyPressed(KEY_TWO)) { SetTextureFilter(font.texture, (int)FILTER_BILINEAR); currentFontFilter = 1; } else if (IsKeyPressed(KEY_THREE)) { // NOTE: Trilinear filter won't be noticed on 2D drawing SetTextureFilter(font.texture, (int)FILTER_TRILINEAR); currentFontFilter = 2; } textSize = MeasureTextEx(font, msg, fontSize, 0); if (IsKeyDown(KEY_LEFT)) fontPosition.x -= 10; else if (IsKeyDown(KEY_RIGHT)) fontPosition.x += 10; // Load a dropped TTF file dynamically (at current fontSize) if (IsFileDropped()) { droppedFiles = GetDroppedFiles(ref count); if (count == 1) // Only support one ttf file dropped { UnloadFont(font); font = LoadFontEx(droppedFiles[0], (int)fontSize, 0, null); ClearDroppedFiles(); } } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText("Use mouse wheel to change font size", 20, 20, 10, GRAY); DrawText("Use KEY_RIGHT and KEY_LEFT to move text", 20, 40, 10, GRAY); DrawText("Use 1, 2, 3 to change texture filter", 20, 60, 10, GRAY); DrawText("Drop a new TTF font for dynamic loading", 20, 80, 10, DARKGRAY); DrawTextEx(font, msg, fontPosition, fontSize, 0, BLACK); // TODO: It seems texSize measurement is not accurate due to chars offsets... //DrawRectangleLines(fontPosition.x, fontPosition.y, textSize.x, textSize.y, RED); DrawRectangle(0, screenHeight - 80, screenWidth, 80, LIGHTGRAY); DrawText(FormatText("Font size: %02.02f", fontSize), 20, screenHeight - 50, 10, DARKGRAY); DrawText(FormatText("Text size: [%02.02f, %02.02f]", textSize.x, textSize.y), 20, screenHeight - 30, 10, DARKGRAY); DrawText("CURRENT TEXTURE FILTER:", 250, 400, 20, GRAY); if (currentFontFilter == 0) DrawText("POINT", 570, 400, 20, BLACK); else if (currentFontFilter == 1) DrawText("BILINEAR", 570, 400, 20, BLACK); else if (currentFontFilter == 2) DrawText("TRILINEAR", 570, 400, 20, BLACK); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- ClearDroppedFiles(); // Clear internal buffers UnloadFont(font); // Font unloading CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/text/text_writing_anim.cs b/Examples/text/text_writing_anim.cs index 7148428..9deb04f 100644 --- a/Examples/text/text_writing_anim.cs +++ b/Examples/text/text_writing_anim.cs @@ -1,7 +1,7 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class text_writing_anim { - /******************************************************************************************* * * raylib [text] example - Text Writing Animation * * 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) * * Copyright (c) 2016 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [text] example - text writing anim"); const char message[128] = "This sample illustrates a text writing\nanimation effect! Check it out! ;)"; int framesCounter = 0; SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (IsKeyDown((int)Key.SPACE)) framesCounter += 8; else framesCounter++; if (IsKeyPressed((int)Key.ENTER)) framesCounter = 0; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText(SubText(message, 0, framesCounter/10), 210, 160, 20, MAROON); DrawText("PRESS [ENTER] to RESTART!", 240, 260, 20, LIGHTGRAY); DrawText("PRESS [SPACE] to SPEED UP!", 239, 300, 20, LIGHTGRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [text] example - Text Writing Animation * * 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) * * Copyright (c) 2016 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [text] example - text writing anim"); string message = "This sample illustrates a text writing\nanimation effect! Check it out! ;)"; int framesCounter = 0; SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (IsKeyDown(KEY_SPACE)) framesCounter += 8; else framesCounter++; if (IsKeyPressed(KEY_ENTER)) framesCounter = 0; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText(SubText(message, 0, framesCounter/10), 210, 160, 20, MAROON); DrawText("PRESS [ENTER] to RESTART!", 240, 260, 20, LIGHTGRAY); DrawText("PRESS [SPACE] to SPEED UP!", 239, 300, 20, LIGHTGRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/textures/resources/custom_jupiter_crash.png b/Examples/textures/resources/custom_jupiter_crash.png index 451b591f17180d69d1229a74117fb971367f9ec4..2deaaeff7ba75e1c02889a5b6ae18b26ffde78fa 100644 GIT binary patch literal 29128 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


fKlDd0-noF&Nl8HV$HfPw2M-?Zm;e8(xBlbN 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 literal 0 HcmV?d00001 diff --git a/Examples/textures/resources/scarfy.png b/Examples/textures/resources/scarfy.png index beb5ffa063b7724cbe041a5b8f783c5f29c63d9c..4803ef77782447ba25399727ed381b2feeacf575 100644 GIT binary patch literal 10495 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 P7#KWV{an^LB{Ts5>X>Ze diff --git a/Examples/textures/textures_image_drawing.cs b/Examples/textures/textures_image_drawing.cs index 18206d6..8f7a3a9 100644 --- a/Examples/textures/textures_image_drawing.cs +++ b/Examples/textures/textures_image_drawing.cs @@ -1,7 +1,7 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class textures_image_drawing { - /******************************************************************************************* * * raylib [textures] example - Image loading and drawing on it * * NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) * * 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) * * Copyright (c) 2016 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] example - image drawing"); // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) Image cat = LoadImage("resources/cat.png"); // Load image in CPU memory (RAM) ImageCrop(&cat, new Rectangle( 100, 10, 280, 380 );); // Crop an image piece ImageFlipHorizontal(&cat); // Flip cropped image horizontally ImageResize(&cat, 150, 200); // Resize flipped-cropped image Image parrots = LoadImage("resources/parrots.png"); // Load image in CPU memory (RAM) // Draw one image over the other with a scaling of 1.5f ImageDraw(&parrots, cat, new Rectangle( 0, 0, cat.width, cat.height }, (Rectangle){ 30, 40, cat.width*1.5f, cat.height*1.5f );); ImageCrop(&parrots, new Rectangle( 0, 50, parrots.width, parrots.height - 100 );); // Crop resulting image UnloadImage(cat); // Unload image from RAM // Load custom font for frawing on image Font font = LoadFont("resources/custom_jupiter_crash.png"); // Draw over image using custom font ImageDrawTextEx(&parrots, new Vector2( 300, 230 );, font, "PARROTS & CAT", font.baseSize, -2, WHITE); UnloadFont(font); // Unload custom spritefont (already drawn used on image) Texture2D texture = LoadTextureFromImage(parrots); // Image converted to texture, uploaded to GPU memory (VRAM) UnloadImage(parrots); // Once image has been converted to texture and uploaded to VRAM, it can be unloaded from RAM SetTargetFPS(60); //--------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update your variables here //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawTexture(texture, screenWidth/2 - texture.width/2, screenHeight/2 - texture.height/2 - 40, WHITE); DrawRectangleLines(screenWidth/2 - texture.width/2, screenHeight/2 - texture.height/2 - 40, texture.width, texture.height, DARKGRAY); DrawText("We are drawing only one texture from various images composed!", 240, 350, 10, DARKGRAY); DrawText("Source images have been cropped, scaled, flipped and copied one over the other.", 190, 370, 10, DARKGRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(texture); // Texture unloading CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [textures] example - Image loading and drawing on it * * NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) * * 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) * * Copyright (c) 2016 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] example - image drawing"); // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) Image cat = LoadImage("resources/cat.png"); // Load image in CPU memory (RAM) ImageCrop(ref cat, new Rectangle( 100, 10, 280, 380 )); // Crop an image piece ImageFlipHorizontal(ref cat); // Flip cropped image horizontally ImageResize(ref cat, 150, 200); // Resize flipped-cropped image Image parrots = LoadImage("resources/parrots.png"); // Load image in CPU memory (RAM) // Draw one image over the other with a scaling of 1.5f ImageDraw(ref parrots, cat, new Rectangle( 0, 0, cat.width, cat.height ), new Rectangle( 30, 40, cat.width*1.5f, cat.height*1.5f )); ImageCrop(ref parrots, new Rectangle( 0, 50, parrots.width, parrots.height - 100 )); // Crop resulting image UnloadImage(cat); // Unload image from RAM // Load custom font for frawing on image Font font = LoadFont("resources/custom_jupiter_crash.png"); // Draw over image using custom font ImageDrawTextEx(ref parrots, new Vector2( 300, 230 ), font, "PARROTS ref CAT", font.baseSize, -2, WHITE); UnloadFont(font); // Unload custom spritefont (already drawn used on image) Texture2D texture = LoadTextureFromImage(parrots); // Image converted to texture, uploaded to GPU memory (VRAM) UnloadImage(parrots); // Once image has been converted to texture and uploaded to VRAM, it can be unloaded from RAM SetTargetFPS(60); //--------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update your variables here //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawTexture(texture, screenWidth/2 - texture.width/2, screenHeight/2 - texture.height/2 - 40, WHITE); DrawRectangleLines(screenWidth/2 - texture.width/2, screenHeight/2 - texture.height/2 - 40, texture.width, texture.height, DARKGRAY); DrawText("We are drawing only one texture from various images composed!", 240, 350, 10, DARKGRAY); DrawText("Source images have been cropped, scaled, flipped and copied one over the other.", 190, 370, 10, DARKGRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(texture); // Texture unloading CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/textures/textures_image_generation.cs b/Examples/textures/textures_image_generation.cs index 5153d1f..cddc2d0 100644 --- a/Examples/textures/textures_image_generation.cs +++ b/Examples/textures/textures_image_generation.cs @@ -1,7 +1,7 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class textures_image_generation { - /******************************************************************************************* * * raylib [textures] example - Procedural images generation * * This example has been created using raylib 1.8 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2O17 Wilhem Barbier (@nounoursheureux) * ********************************************************************************************/ public const #define NUM_TEXTURES 7 // Currently we have 7 generation algorithms public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] example - procedural images generation"); Image verticalGradient = GenImageGradientV(screenWidth, screenHeight, RED, BLUE); Image horizontalGradient = GenImageGradientH(screenWidth, screenHeight, RED, BLUE); Image radialGradient = GenImageGradientRadial(screenWidth, screenHeight, 0.0f, WHITE, BLACK); Image checked = GenImageChecked(screenWidth, screenHeight, 32, 32, RED, BLUE); Image whiteNoise = GenImageWhiteNoise(screenWidth, screenHeight, 0.5f); Image perlinNoise = GenImagePerlinNoise(screenWidth, screenHeight, 50, 50, 4.0f); Image cellular = GenImageCellular(screenWidth, screenHeight, 32); Texture2D[] textures = new Texture2D[NUM_TEXTURES]; textures[0] = LoadTextureFromImage(verticalGradient); textures[1] = LoadTextureFromImage(horizontalGradient); textures[2] = LoadTextureFromImage(radialGradient); textures[3] = LoadTextureFromImage(checked); textures[4] = LoadTextureFromImage(whiteNoise); textures[5] = LoadTextureFromImage(perlinNoise); textures[6] = LoadTextureFromImage(cellular); // Unload image data (CPU RAM) UnloadImage(verticalGradient); UnloadImage(horizontalGradient); UnloadImage(radialGradient); UnloadImage(checked); UnloadImage(whiteNoise); UnloadImage(perlinNoise); UnloadImage(cellular); int currentTexture = 0; SetTargetFPS(60); //--------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) { // Update //---------------------------------------------------------------------------------- if (IsMouseButtonPressed((int)Mouse.LEFT_BUTTON) || IsKeyPressed((int)Key.RIGHT)) { currentTexture = (currentTexture + 1)%NUM_TEXTURES; // Cycle between the textures } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawTexture(textures[currentTexture], 0, 0, WHITE); DrawRectangle(30, 400, 325, 30, Fade(SKYBLUE, 0.5f)); DrawRectangleLines(30, 400, 325, 30, Fade(WHITE, 0.5f)); DrawText("MOUSE LEFT BUTTON to CYCLE PROCEDURAL TEXTURES", 40, 410, 10, WHITE); switch(currentTexture) { case 0: DrawText("VERTICAL GRADIENT", 560, 10, 20, RAYWHITE); break; case 1: DrawText("HORIZONTAL GRADIENT", 540, 10, 20, RAYWHITE); break; case 2: DrawText("RADIAL GRADIENT", 580, 10, 20, LIGHTGRAY); break; case 3: DrawText("CHECKED", 680, 10, 20, RAYWHITE); break; case 4: DrawText("WHITE NOISE", 640, 10, 20, RED); break; case 5: DrawText("PERLIN NOISE", 630, 10, 20, RAYWHITE); break; case 6: DrawText("CELLULAR", 670, 10, 20, RAYWHITE); break; default: break; } EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- // Unload textures data (GPU VRAM) for (int i = 0; i < NUM_TEXTURES; i++) UnloadTexture(textures[i]); CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [textures] example - Procedural images generation * * This example has been created using raylib 1.8 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2O17 Wilhem Barbier (@nounoursheureux) * ********************************************************************************************/ public const int NUM_TEXTURES = 7; public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] example - procedural images generation"); Image verticalGradient = GenImageGradientV(screenWidth, screenHeight, RED, BLUE); Image horizontalGradient = GenImageGradientH(screenWidth, screenHeight, RED, BLUE); Image radialGradient = GenImageGradientRadial(screenWidth, screenHeight, 0.0f, WHITE, BLACK); Image isChecked = GenImageChecked(screenWidth, screenHeight, 32, 32, RED, BLUE); Image whiteNoise = GenImageWhiteNoise(screenWidth, screenHeight, 0.5f); Image perlinNoise = GenImagePerlinNoise(screenWidth, screenHeight, 50, 50, 4.0f); Image cellular = GenImageCellular(screenWidth, screenHeight, 32); Texture2D[] textures = new Texture2D[NUM_TEXTURES]; textures[0] = LoadTextureFromImage(verticalGradient); textures[1] = LoadTextureFromImage(horizontalGradient); textures[2] = LoadTextureFromImage(radialGradient); textures[3] = LoadTextureFromImage(isChecked); textures[4] = LoadTextureFromImage(whiteNoise); textures[5] = LoadTextureFromImage(perlinNoise); textures[6] = LoadTextureFromImage(cellular); // Unload image data (CPU RAM) UnloadImage(verticalGradient); UnloadImage(horizontalGradient); UnloadImage(radialGradient); UnloadImage(isChecked); UnloadImage(whiteNoise); UnloadImage(perlinNoise); UnloadImage(cellular); int currentTexture = 0; SetTargetFPS(60); //--------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) { // Update //---------------------------------------------------------------------------------- if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) || IsKeyPressed(KEY_RIGHT)) { currentTexture = (currentTexture + 1)%NUM_TEXTURES; // Cycle between the textures } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawTexture(textures[currentTexture], 0, 0, WHITE); DrawRectangle(30, 400, 325, 30, Fade(SKYBLUE, 0.5f)); DrawRectangleLines(30, 400, 325, 30, Fade(WHITE, 0.5f)); DrawText("MOUSE LEFT BUTTON to CYCLE PROCEDURAL TEXTURES", 40, 410, 10, WHITE); switch(currentTexture) { case 0: DrawText("VERTICAL GRADIENT", 560, 10, 20, RAYWHITE); break; case 1: DrawText("HORIZONTAL GRADIENT", 540, 10, 20, RAYWHITE); break; case 2: DrawText("RADIAL GRADIENT", 580, 10, 20, LIGHTGRAY); break; case 3: DrawText("CHECKED", 680, 10, 20, RAYWHITE); break; case 4: DrawText("WHITE NOISE", 640, 10, 20, RED); break; case 5: DrawText("PERLIN NOISE", 630, 10, 20, RAYWHITE); break; case 6: DrawText("CELLULAR", 670, 10, 20, RAYWHITE); break; default: break; } EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- // Unload textures data (GPU VRAM) for (int i = 0; i < NUM_TEXTURES; i++) UnloadTexture(textures[i]); CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/textures/textures_image_loading.cs b/Examples/textures/textures_image_loading.cs index ff4dc41..22d5d50 100644 --- a/Examples/textures/textures_image_loading.cs +++ b/Examples/textures/textures_image_loading.cs @@ -1,7 +1,7 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class textures_image_loading { - /******************************************************************************************* * * raylib [textures] example - Image loading and texture creation * * NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) * * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] example - image loading"); // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) Image image = LoadImage("resources/raylib_logo.png"); // Loaded in CPU memory (RAM) Texture2D texture = LoadTextureFromImage(image); // Image converted to texture, GPU memory (VRAM) UnloadImage(image); // Once image has been converted to texture and uploaded to VRAM, it can be unloaded from RAM //--------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update your variables here //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawTexture(texture, screenWidth/2 - texture.width/2, screenHeight/2 - texture.height/2, WHITE); DrawText("this IS a texture loaded from an image!", 300, 370, 10, GRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(texture); // Texture unloading CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [textures] example - Image loading and texture creation * * NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) * * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] example - image loading"); // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) Image image = LoadImage("resources/raylib_logo.png"); // Loaded in CPU memory (RAM) Texture2D texture = LoadTextureFromImage(image); // Image converted to texture, GPU memory (VRAM) UnloadImage(image); // Once image has been converted to texture and uploaded to VRAM, it can be unloaded from RAM //--------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update your variables here //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawTexture(texture, screenWidth/2 - texture.width/2, screenHeight/2 - texture.height/2, WHITE); DrawText("this IS a texture loaded from an image!", 300, 370, 10, GRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(texture); // Texture unloading CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/textures/textures_image_processing.cs b/Examples/textures/textures_image_processing.cs index ec6bcd4..29d4245 100644 --- a/Examples/textures/textures_image_processing.cs +++ b/Examples/textures/textures_image_processing.cs @@ -1,7 +1,9 @@ using Raylib; using static Raylib.Raylib; +using static Raylib.PixelFormat; -public partial class Examples +public partial class textures_image_processing { - /******************************************************************************************* * * raylib [textures] example - Image processing * * NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) * * 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) * * Copyright (c) 2016 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public const #define NUM_PROCESSES 8 typedef enum { NONE = 0, COLOR_GRAYSCALE, COLOR_TINT, COLOR_INVERT, COLOR_CONTRAST, COLOR_BRIGHTNESS, FLIP_VERTICAL, FLIP_HORIZONTAL } ImageProcess; static const char *processText[] = { "NO PROCESSING", "COLOR GRAYSCALE", "COLOR TINT", "COLOR INVERT", "COLOR CONTRAST", "COLOR BRIGHTNESS", "FLIP VERTICAL", "FLIP HORIZONTAL" }; public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] example - image processing"); // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) Image image = LoadImage("resources/parrots.png"); // Loaded in CPU memory (RAM) ImageFormat(&image, UNCOMPRESSED_R8G8B8A8); // Format image to RGBA 32bit (required for texture update) <-- ISSUE Texture2D texture = LoadTextureFromImage(image); // Image converted to texture, GPU memory (VRAM) int currentProcess = NONE; bool textureReload = false; Rectangle[] selectRecs = new Rectangle[NUM_PROCESSES]; for (int i = 0; i < NUM_PROCESSES; i++) selectRecs[i] = new Rectangle( 40, 50 + 32*i, 150, 30 );; SetTargetFPS(60); //--------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (IsKeyPressed((int)Key.DOWN)) { currentProcess++; if (currentProcess > 7) currentProcess = 0; textureReload = true; } else if (IsKeyPressed((int)Key.UP)) { currentProcess--; if (currentProcess < 0) currentProcess = 7; textureReload = true; } if (textureReload) { UnloadImage(image); // Unload current image data image = LoadImage("resources/parrots.png"); // Re-load image data // NOTE: Image processing is a costly CPU process to be done every frame, // If image processing is required in a frame-basis, it should be done // with a texture and by shaders switch (currentProcess) { case COLOR_GRAYSCALE: ImageColorGrayscale(&image); break; case COLOR_TINT: ImageColorTint(&image, GREEN); break; case COLOR_INVERT: ImageColorInvert(&image); break; case COLOR_CONTRAST: ImageColorContrast(&image, -40); break; case COLOR_BRIGHTNESS: ImageColorBrightness(&image, -80); break; case FLIP_VERTICAL: ImageFlipVertical(&image); break; case FLIP_HORIZONTAL: ImageFlipHorizontal(&image); break; default: break; } Color *pixels = GetImageData(image); // Get pixel data from image (RGBA 32bit) UpdateTexture(texture, pixels); // Update texture with new image data free(pixels); // Unload pixels data from RAM textureReload = false; } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText("IMAGE PROCESSING:", 40, 30, 10, DARKGRAY); // Draw rectangles for (int i = 0; i < NUM_PROCESSES; i++) { DrawRectangleRec(selectRecs[i], (i == currentProcess) ? SKYBLUE : LIGHTGRAY); DrawRectangleLines(selectRecs[i].x, selectRecs[i].y, selectRecs[i].width, selectRecs[i].height, (i == currentProcess) ? BLUE : GRAY); DrawText(processText[i], selectRecs[i].x + selectRecs[i].width/2 - MeasureText(processText[i], 10)/2, selectRecs[i].y + 11, 10, (i == currentProcess) ? DARKBLUE : DARKGRAY); } DrawTexture(texture, screenWidth - texture.width - 60, screenHeight/2 - texture.height/2, WHITE); DrawRectangleLines(screenWidth - texture.width - 60, screenHeight/2 - texture.height/2, texture.width, texture.height, BLACK); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(texture); // Unload texture from VRAM UnloadImage(image); // Unload image from RAM CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [textures] example - Image processing * * NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) * * 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) * * Copyright (c) 2016 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public const int NUM_PROCESSES = 8; enum ImageProcess + { NONE = 0, COLOR_GRAYSCALE, COLOR_TINT, COLOR_INVERT, COLOR_CONTRAST, COLOR_BRIGHTNESS, FLIP_VERTICAL, FLIP_HORIZONTAL } static string[] processText = { "NO PROCESSING", "COLOR GRAYSCALE", "COLOR TINT", "COLOR INVERT", "COLOR CONTRAST", "COLOR BRIGHTNESS", "FLIP VERTICAL", "FLIP HORIZONTAL" }; public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] example - image processing"); // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) Image image = LoadImage("resources/parrots.png"); // Loaded in CPU memory (RAM) ImageFormat(ref image, (int)UNCOMPRESSED_R8G8B8A8); // Format image to RGBA 32bit (required for texture update) <-- ISSUE Texture2D texture = LoadTextureFromImage(image); // Image converted to texture, GPU memory (VRAM) int currentProcess = (int)ImageProcess.NONE; bool textureReload = false; Rectangle[] selectRecs = new Rectangle[NUM_PROCESSES]; for (int i = 0; i < NUM_PROCESSES; i++) selectRecs[i] = new Rectangle( 40, 50 + 32*i, 150, 30 ); SetTargetFPS(60); //--------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (IsKeyPressed(KEY_DOWN)) { currentProcess++; if (currentProcess > 7) currentProcess = 0; textureReload = true; } else if (IsKeyPressed(KEY_UP)) { currentProcess--; if (currentProcess < 0) currentProcess = 7; textureReload = true; } if (textureReload) { UnloadImage(image); // Unload current image data image = LoadImage("resources/parrots.png"); // Re-load image data // NOTE: Image processing is a costly CPU process to be done every frame, // If image processing is required in a frame-basis, it should be done // with a texture and by shaders switch (currentProcess) { case (int)ImageProcess.COLOR_GRAYSCALE: ImageColorGrayscale(ref image); break; case (int)ImageProcess.COLOR_TINT: ImageColorTint(ref image, GREEN); break; case (int)ImageProcess.COLOR_INVERT: ImageColorInvert(ref image); break; case (int)ImageProcess.COLOR_CONTRAST: ImageColorContrast(ref image, -40); break; case (int)ImageProcess.COLOR_BRIGHTNESS: ImageColorBrightness(ref image, -80); break; case (int)ImageProcess.FLIP_VERTICAL: ImageFlipVertical(ref image); break; case (int)ImageProcess.FLIP_HORIZONTAL: ImageFlipHorizontal(ref image); break; default: break; } Color[] pixels = GetImageData(image); // Get pixel data from image (RGBA 32bit) UpdateTexture(texture, pixels); // Update texture with new image data // free(pixels); // Unload pixels data from RAM textureReload = false; } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawText("IMAGE PROCESSING:", 40, 30, 10, DARKGRAY); // Draw rectangles for (int i = 0; i < NUM_PROCESSES; i++) { DrawRectangleRec(selectRecs[i], (i == currentProcess) ? SKYBLUE : LIGHTGRAY); DrawRectangleLines((int)selectRecs[i].x, (int)selectRecs[i].y, (int)selectRecs[i].width, (int)selectRecs[i].height, (i == currentProcess) ? BLUE : GRAY); DrawText(processText[i], (int)(selectRecs[i].x + selectRecs[i].width/2 - MeasureText(processText[i], 10)/2), (int)selectRecs[i].y + 11, 10, (i == currentProcess) ? DARKBLUE : DARKGRAY); } DrawTexture(texture, screenWidth - texture.width - 60, screenHeight/2 - texture.height/2, WHITE); DrawRectangleLines(screenWidth - texture.width - 60, screenHeight/2 - texture.height/2, texture.width, texture.height, BLACK); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(texture); // Unload texture from VRAM UnloadImage(image); // Unload image from RAM CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/textures/textures_image_text.cs b/Examples/textures/textures_image_text.cs index 8f4e880..670350c 100644 --- a/Examples/textures/textures_image_text.cs +++ b/Examples/textures/textures_image_text.cs @@ -1,7 +1,7 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class textures_image_text { - /******************************************************************************************* * * raylib [texture] example - Image text drawing using TTF generated spritefont * * This example has been created using raylib 1.8 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2017 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [texture] example - image text drawing"); // TTF Font loading with custom generation parameters Font font = LoadFontEx("resources/KAISG.ttf", 64, 95, 0); Image parrots = LoadImage("resources/parrots.png"); // Load image in CPU memory (RAM) // Draw over image using custom font ImageDrawTextEx(&parrots, new Vector2( 20, 20 );, font, "[Parrots font drawing]", font.baseSize, 0, WHITE); Texture2D texture = LoadTextureFromImage(parrots); // Image converted to texture, uploaded to GPU memory (VRAM) UnloadImage(parrots); // Once image has been converted to texture and uploaded to VRAM, it can be unloaded from RAM Vector2 position = { screenWidth/2 - texture.width/2, screenHeight/2 - texture.height/2 - 20 }; bool showFont = false; SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (IsKeyDown((int)Key.SPACE)) showFont = true; else showFont = false; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); if (!showFont) { // Draw texture with text already drawn inside DrawTextureV(texture, position, WHITE); // Draw text directly using sprite font DrawTextEx(font, "[Parrots font drawing]", (Vector2){ position.x + 20, position.y + 20 + 280 }, font.baseSize, 0, WHITE); } else DrawTexture(font.texture, screenWidth/2 - font.texture.width/2, 50, BLACK); DrawText("PRESS SPACE to SEE USED SPRITEFONT ", 290, 420, 10, DARKGRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(texture); // Texture unloading UnloadFont(font); // Unload custom spritefont CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [texture] example - Image text drawing using TTF generated spritefont * * This example has been created using raylib 1.8 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2017 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [texture] example - image text drawing"); // TTF Font loading with custom generation parameters Font font = LoadFontEx("resources/KAISG.ttf", 64, 95, null); Image parrots = LoadImage("resources/parrots.png"); // Load image in CPU memory (RAM) // Draw over image using custom font ImageDrawTextEx(ref parrots, new Vector2( 20, 20 ), font, "[Parrots font drawing]", font.baseSize, 0, WHITE); Texture2D texture = LoadTextureFromImage(parrots); // Image converted to texture, uploaded to GPU memory (VRAM) UnloadImage(parrots); // Once image has been converted to texture and uploaded to VRAM, it can be unloaded from RAM Vector2 position = new Vector2( screenWidth/2 - texture.width/2, screenHeight/2 - texture.height/2 - 20 ); bool showFont = false; SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (IsKeyDown(KEY_SPACE)) showFont = true; else showFont = false; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); if (!showFont) { // Draw texture with text already drawn inside DrawTextureV(texture, position, WHITE); // Draw text directly using sprite font DrawTextEx(font, "[Parrots font drawing]", new Vector2( position.x + 20, position.y + 20 + 280 ), font.baseSize, 0, WHITE); } else DrawTexture(font.texture, screenWidth/2 - font.texture.width/2, 50, BLACK); DrawText("PRESS SPACE to SEE USED SPRITEFONT ", 290, 420, 10, DARKGRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(texture); // Texture unloading UnloadFont(font); // Unload custom spritefont CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/textures/textures_logo_raylib.cs b/Examples/textures/textures_logo_raylib.cs index c8b16f9..b91957e 100644 --- a/Examples/textures/textures_logo_raylib.cs +++ b/Examples/textures/textures_logo_raylib.cs @@ -1,7 +1,7 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class textures_logo_raylib { - /******************************************************************************************* * * raylib [textures] example - Texture loading and drawing * * 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) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] example - texture loading and drawing"); // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) Texture2D texture = LoadTexture("resources/raylib_logo.png"); // Texture loading //--------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update your variables here //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawTexture(texture, screenWidth/2 - texture.width/2, screenHeight/2 - texture.height/2, WHITE); DrawText("this IS a texture!", 360, 370, 10, GRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(texture); // Texture unloading CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [textures] example - Texture loading and drawing * * 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) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] example - texture loading and drawing"); // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) Texture2D texture = LoadTexture("resources/raylib_logo.png"); // Texture loading //--------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update your variables here //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawTexture(texture, screenWidth/2 - texture.width/2, screenHeight/2 - texture.height/2, WHITE); DrawText("this IS a texture!", 360, 370, 10, GRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(texture); // Texture unloading CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/textures/textures_particles_blending.cs b/Examples/textures/textures_particles_blending.cs index 5145aeb..49cfa6c 100644 --- a/Examples/textures/textures_particles_blending.cs +++ b/Examples/textures/textures_particles_blending.cs @@ -1,7 +1,13 @@ using Raylib; using static Raylib.Raylib; +using static Raylib.BlendMode; -public partial class Examples +public partial class textures_particles_blending { - /******************************************************************************************* * * raylib example - particles blending * * This example has been created using raylib 1.7 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2017 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public const #define MAX_PARTICLES 200 // Particle structure with basic data struct Particle { public Vector2 position; public Color color; public float alpha; public float size; public float rotation; public bool active; // NOTE: Use it to activate/deactive particle public } Particle; public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] example - particles blending"); // Particles pool, reuse them! Particle[] mouseTail = new Particle[MAX_PARTICLES]; // Initialize particles for (int i = 0; i < MAX_PARTICLES; i++) { mouseTail[i].position = new Vector2( 0, 0 );; mouseTail[i].color = new Color( GetRandomValue(0, 255), GetRandomValue(0, 255), GetRandomValue(0, 255), 255 );; mouseTail[i].alpha = 1.0f; mouseTail[i].size = (float)GetRandomValue(1, 30)/20.0f; mouseTail[i].rotation = GetRandomValue(0, 360); mouseTail[i].active = false; } float gravity = 3.0f; Texture2D smoke = LoadTexture("resources/smoke.png"); int blending = BLEND_ALPHA; SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // Activate one particle every frame and Update active particles // NOTE: Particles initial position should be mouse position when activated // NOTE: Particles fall down with gravity and rotation... and disappear after 2 seconds (alpha = 0) // NOTE: When a particle disappears, active = false and it can be reused. for (int i = 0; i < MAX_PARTICLES; i++) { if (!mouseTail[i].active) { mouseTail[i].active = true; mouseTail[i].alpha = 1.0f; mouseTail[i].position = GetMousePosition(); i = MAX_PARTICLES; } } for (int i = 0; i < MAX_PARTICLES; i++) { if (mouseTail[i].active) { mouseTail[i].position.y += gravity; mouseTail[i].alpha -= 0.01f; if (mouseTail[i].alpha <= 0.0f) mouseTail[i].active = false; mouseTail[i].rotation += 5.0f; } } if (IsKeyPressed((int)Key.SPACE)) { if (blending == BLEND_ALPHA) blending = BLEND_ADDITIVE; else blending = BLEND_ALPHA; } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(DARKGRAY); BeginBlendMode(blending); // Draw active particles for (int i = 0; i < MAX_PARTICLES; i++) { if (mouseTail[i].active) DrawTexturePro(smoke, new Rectangle( 0, 0, smoke.width, smoke.height );, new Rectangle( mouseTail[i].position.x, mouseTail[i].position.y, smoke.width*mouseTail[i].size, smoke.height*mouseTail[i].size );, new Vector2( smoke.width*mouseTail[i].size/2, smoke.height*mouseTail[i].size/2 );, mouseTail[i].rotation, Fade(mouseTail[i].color, mouseTail[i].alpha)); } EndBlendMode(); DrawText("PRESS SPACE to CHANGE BLENDING MODE", 180, 20, 20, BLACK); if (blending == BLEND_ALPHA) DrawText("ALPHA BLENDING", 290, screenHeight - 40, 20, BLACK); else DrawText("ADDITIVE BLENDING", 280, screenHeight - 40, 20, RAYWHITE); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(smoke); CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib example - particles blending * * This example has been created using raylib 1.7 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2017 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public const int MAX_PARTICLES = 200; + + // Particle structure with basic data + struct Particle { + public Vector2 position; public Color color; public float alpha; public float size; public float rotation; public bool active; // NOTE: Use it to activate/deactive particle + } public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] example - particles blending"); // Particles pool, reuse them! Particle[] mouseTail = new Particle[MAX_PARTICLES]; // Initialize particles for (int i = 0; i < MAX_PARTICLES; i++) { mouseTail[i].position = new Vector2( 0, 0 ); mouseTail[i].color = new Color( GetRandomValue(0, 255), GetRandomValue(0, 255), GetRandomValue(0, 255), 255 ); mouseTail[i].alpha = 1.0f; mouseTail[i].size = (float)GetRandomValue(1, 30)/20.0f; mouseTail[i].rotation = GetRandomValue(0, 360); mouseTail[i].active = false; } float gravity = 3.0f; Texture2D smoke = LoadTexture("resources/smoke.png"); int blending = (int)BLEND_ALPHA; SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // Activate one particle every frame and Update active particles // NOTE: Particles initial position should be mouse position when activated // NOTE: Particles fall down with gravity and rotation... and disappear after 2 seconds (alpha = 0) // NOTE: When a particle disappears, active = false and it can be reused. for (int i = 0; i < MAX_PARTICLES; i++) { if (!mouseTail[i].active) { mouseTail[i].active = true; mouseTail[i].alpha = 1.0f; mouseTail[i].position = GetMousePosition(); i = MAX_PARTICLES; } } for (int i = 0; i < MAX_PARTICLES; i++) { if (mouseTail[i].active) { mouseTail[i].position.y += gravity; mouseTail[i].alpha -= 0.01f; if (mouseTail[i].alpha <= 0.0f) mouseTail[i].active = false; mouseTail[i].rotation += 5.0f; } } if (IsKeyPressed(KEY_SPACE)) { if (blending == (int)BLEND_ALPHA) blending = (int)BLEND_ADDITIVE; else blending = (int)BLEND_ALPHA; } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(DARKGRAY); BeginBlendMode(blending); // Draw active particles for (int i = 0; i < MAX_PARTICLES; i++) { if (mouseTail[i].active) DrawTexturePro(smoke, new Rectangle( 0, 0, smoke.width, smoke.height ), new Rectangle( mouseTail[i].position.x, mouseTail[i].position.y, smoke.width*mouseTail[i].size, smoke.height*mouseTail[i].size ), new Vector2( smoke.width*mouseTail[i].size/2, smoke.height*mouseTail[i].size/2 ), mouseTail[i].rotation, Fade(mouseTail[i].color, mouseTail[i].alpha)); } EndBlendMode(); DrawText("PRESS SPACE to CHANGE BLENDING MODE", 180, 20, 20, BLACK); if (blending == (int)BLEND_ALPHA) DrawText("ALPHA BLENDING", 290, screenHeight - 40, 20, BLACK); else DrawText("ADDITIVE BLENDING", 280, screenHeight - 40, 20, RAYWHITE); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(smoke); CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/textures/textures_raw_data.cs b/Examples/textures/textures_raw_data.cs index 78314cd..05c8dc4 100644 --- a/Examples/textures/textures_raw_data.cs +++ b/Examples/textures/textures_raw_data.cs @@ -1,7 +1,8 @@ using Raylib; using static Raylib.Raylib; +using static Raylib.PixelFormat; -public partial class Examples +public partial class textures_raw_data { - /******************************************************************************************* * * raylib [textures] example - Load textures from raw data * * NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) * * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] example - texture from raw data"); // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) // Load RAW image data (512x512, 32bit RGBA, no file header) Image fudesumiRaw = LoadImageRaw("resources/fudesumi.raw", 384, 512, UNCOMPRESSED_R8G8B8A8, 0); Texture2D fudesumi = LoadTextureFromImage(fudesumiRaw); // Upload CPU (RAM) image to GPU (VRAM) UnloadImage(fudesumiRaw); // Unload CPU (RAM) image data // Generate a checked texture by code (1024x1024 pixels) int width = 1024; int height = 1024; // Dynamic memory allocation to store pixels data (Color type) Color *pixels = (Color *)malloc(width*height*sizeof(Color)); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { if (((x/32+y/32)/1)%2 == 0) pixels[y*height + x] = ORANGE; else pixels[y*height + x] = GOLD; } } // Load pixels data into an image structure and create texture Image checkedIm = LoadImageEx(pixels, width, height); Texture2D checked = LoadTextureFromImage(checkedIm); UnloadImage(checkedIm); // Unload CPU (RAM) image data // Dynamic memory must be freed after using it free(pixels); // Unload CPU (RAM) pixels data //--------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update your variables here //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawTexture(checked, screenWidth/2 - checked.width/2, screenHeight/2 - checked.height/2, Fade(WHITE, 0.5f)); DrawTexture(fudesumi, 430, -30, WHITE); DrawText("CHECKED TEXTURE ", 84, 100, 30, BROWN); DrawText("GENERATED by CODE", 72, 164, 30, BROWN); DrawText("and RAW IMAGE LOADING", 46, 226, 30, BROWN); DrawText("(c) Fudesumi sprite by Eiden Marsal", 310, screenHeight - 20, 10, BROWN); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(fudesumi); // Texture unloading UnloadTexture(checked); // Texture unloading CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [textures] example - Load textures from raw data * * NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) * * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] example - texture from raw data"); // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) // Load RAW image data (512x512, 32bit RGBA, no file header) Image fudesumiRaw = LoadImageRaw("resources/fudesumi.raw", 384, 512, (int)UNCOMPRESSED_R8G8B8A8, 0); Texture2D fudesumi = LoadTextureFromImage(fudesumiRaw); // Upload CPU (RAM) image to GPU (VRAM) UnloadImage(fudesumiRaw); // Unload CPU (RAM) image data // Generate a isChecked texture by code (1024x1024 pixels) int width = 1024; int height = 1024; // Dynamic memory allocation to store pixels data (Color type) // Color *pixels = (Color *)malloc(width*height*sizeof(Color)); Color[] pixels = new Color[width*height]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { if (((x/32+y/32)/1)%2 == 0) pixels[y*height + x] = ORANGE; else pixels[y*height + x] = GOLD; } } // Load pixels data into an image structure and create texture Image isCheckedIm = LoadImageEx(pixels, width, height); Texture2D isChecked = LoadTextureFromImage(isCheckedIm); UnloadImage(isCheckedIm); // Unload CPU (RAM) image data // Dynamic memory must be freed after using it // free(pixels); // Unload CPU (RAM) pixels data //--------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update your variables here //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawTexture(isChecked, screenWidth/2 - isChecked.width/2, screenHeight/2 - isChecked.height/2, Fade(WHITE, 0.5f)); DrawTexture(fudesumi, 430, -30, WHITE); DrawText("CHECKED TEXTURE ", 84, 100, 30, BROWN); DrawText("GENERATED by CODE", 72, 164, 30, BROWN); DrawText("and RAW IMAGE LOADING", 46, 226, 30, BROWN); DrawText("(c) Fudesumi sprite by Eiden Marsal", 310, screenHeight - 20, 10, BROWN); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(fudesumi); // Texture unloading UnloadTexture(isChecked); // Texture unloading CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/textures/textures_rectangle.cs b/Examples/textures/textures_rectangle.cs index f9440bc..f6cfd2a 100644 --- a/Examples/textures/textures_rectangle.cs +++ b/Examples/textures/textures_rectangle.cs @@ -1,7 +1,7 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class textures_rectangle { - /******************************************************************************************* * * raylib [textures] example - Texture loading and drawing a part defined by a rectangle * * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public const #define MAX_FRAME_SPEED 15 public const #define MIN_FRAME_SPEED 1 public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [texture] example - texture rectangle"); // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) Texture2D scarfy = LoadTexture("resources/scarfy.png"); // Texture loading Vector2 position = { 350.0f, 280.0f }; Rectangle frameRec = { 0.0f, 0.0f, (float)scarfy.width/6, (float)scarfy.height }; int currentFrame = 0; int framesCounter = 0; int framesSpeed = 8; // Number of spritesheet frames shown by second SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- framesCounter++; if (framesCounter >= (60/framesSpeed)) { framesCounter = 0; currentFrame++; if (currentFrame > 5) currentFrame = 0; frameRec.x = (float)currentFrame*(float)scarfy.width/6; } if (IsKeyPressed((int)Key.RIGHT)) framesSpeed++; else if (IsKeyPressed((int)Key.LEFT)) framesSpeed--; if (framesSpeed > MAX_FRAME_SPEED) framesSpeed = MAX_FRAME_SPEED; else if (framesSpeed < MIN_FRAME_SPEED) framesSpeed = MIN_FRAME_SPEED; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawTexture(scarfy, 15, 40, WHITE); DrawRectangleLines(15, 40, scarfy.width, scarfy.height, LIME); DrawRectangleLines(15 + frameRec.x, 40 + frameRec.y, frameRec.width, frameRec.height, RED); DrawText("FRAME SPEED: ", 165, 210, 10, DARKGRAY); DrawText(FormatText("%02i FPS", framesSpeed), 575, 210, 10, DARKGRAY); DrawText("PRESS RIGHT/LEFT KEYS to CHANGE SPEED!", 290, 240, 10, DARKGRAY); for (int i = 0; i < MAX_FRAME_SPEED; i++) { if (i < framesSpeed) DrawRectangle(250 + 21*i, 205, 20, 20, RED); DrawRectangleLines(250 + 21*i, 205, 20, 20, MAROON); } DrawTextureRec(scarfy, frameRec, position, WHITE); // Draw part of the texture DrawText("(c) Scarfy sprite by Eiden Marsal", screenWidth - 200, screenHeight - 20, 10, GRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(scarfy); // Texture unloading CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [textures] example - Texture loading and drawing a part defined by a rectangle * * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public const int MAX_FRAME_SPEED = 15; public const int MIN_FRAME_SPEED = 1; public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [texture] example - texture rectangle"); // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) Texture2D scarfy = LoadTexture("resources/scarfy.png"); // Texture loading Vector2 position = new Vector2( 350.0f, 280.0f ); Rectangle frameRec = new Rectangle( 0.0f, 0.0f, (float)scarfy.width/6, (float)scarfy.height ); int currentFrame = 0; int framesCounter = 0; int framesSpeed = 8; // Number of spritesheet frames shown by second SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- framesCounter++; if (framesCounter >= (60/framesSpeed)) { framesCounter = 0; currentFrame++; if (currentFrame > 5) currentFrame = 0; frameRec.x = (float)currentFrame*(float)scarfy.width/6; } if (IsKeyPressed(KEY_RIGHT)) framesSpeed++; else if (IsKeyPressed(KEY_LEFT)) framesSpeed--; if (framesSpeed > MAX_FRAME_SPEED) framesSpeed = MAX_FRAME_SPEED; else if (framesSpeed < MIN_FRAME_SPEED) framesSpeed = MIN_FRAME_SPEED; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawTexture(scarfy, 15, 40, WHITE); DrawRectangleLines(15, 40, scarfy.width, scarfy.height, LIME); DrawRectangleLines(15 + (int)frameRec.x, 40 + (int)frameRec.y, (int)frameRec.width, (int)frameRec.height, RED); DrawText("FRAME SPEED: ", 165, 210, 10, DARKGRAY); DrawText(FormatText("%02i FPS", framesSpeed), 575, 210, 10, DARKGRAY); DrawText("PRESS RIGHT/LEFT KEYS to CHANGE SPEED!", 290, 240, 10, DARKGRAY); for (int i = 0; i < MAX_FRAME_SPEED; i++) { if (i < framesSpeed) DrawRectangle(250 + 21*i, 205, 20, 20, RED); DrawRectangleLines(250 + 21*i, 205, 20, 20, MAROON); } DrawTextureRec(scarfy, frameRec, position, WHITE); // Draw part of the texture DrawText("(c) Scarfy sprite by Eiden Marsal", screenWidth - 200, screenHeight - 20, 10, GRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(scarfy); // Texture unloading CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/textures/textures_srcrec_dstrec.cs b/Examples/textures/textures_srcrec_dstrec.cs index 731dbad..597c9c3 100644 --- a/Examples/textures/textures_srcrec_dstrec.cs +++ b/Examples/textures/textures_srcrec_dstrec.cs @@ -1,7 +1,7 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class textures_srcrec_dstrec { - /******************************************************************************************* * * raylib [textures] example - Texture source and destination rectangles * * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] examples - texture source and destination rectangles"); // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) Texture2D scarfy = LoadTexture("resources/scarfy.png"); // Texture loading int frameWidth = scarfy.width/6; int frameHeight = scarfy.height; // NOTE: Source rectangle (part of the texture to use for drawing) Rectangle sourceRec = { 0, 0, frameWidth, frameHeight }; // NOTE: Destination rectangle (screen rectangle where drawing part of texture) Rectangle destRec = { screenWidth/2, screenHeight/2, frameWidth*2, frameHeight*2 }; // NOTE: Origin of the texture (rotation/scale point), it's relative to destination rectangle size Vector2 origin = { frameWidth, frameHeight }; int rotation = 0; SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- rotation++; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); // NOTE: Using DrawTexturePro() we can easily rotate and scale the part of the texture we draw // sourceRec defines the part of the texture we use for drawing // destRec defines the rectangle where our texture part will fit (scaling it to fit) // origin defines the point of the texture used as reference for rotation and scaling // rotation defines the texture rotation (using origin as rotation point) DrawTexturePro(scarfy, sourceRec, destRec, origin, rotation, WHITE); DrawLine(destRec.x, 0, destRec.x, screenHeight, GRAY); DrawLine(0, destRec.y, screenWidth, destRec.y, GRAY); DrawText("(c) Scarfy sprite by Eiden Marsal", screenWidth - 200, screenHeight - 20, 10, GRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(scarfy); // Texture unloading CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [textures] example - Texture source and destination rectangles * * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] examples - texture source and destination rectangles"); // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) Texture2D scarfy = LoadTexture("resources/scarfy.png"); // Texture loading int frameWidth = scarfy.width/6; int frameHeight = scarfy.height; // NOTE: Source rectangle (part of the texture to use for drawing) Rectangle sourceRec = new Rectangle( 0, 0, frameWidth, frameHeight ); // NOTE: Destination rectangle (screen rectangle where drawing part of texture) Rectangle destRec = new Rectangle( screenWidth/2, screenHeight/2, frameWidth*2, frameHeight*2 ); // NOTE: Origin of the texture (rotation/scale point), it's relative to destination rectangle size Vector2 origin = new Vector2( frameWidth, frameHeight ); int rotation = 0; SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- rotation++; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); // NOTE: Using DrawTexturePro() we can easily rotate and scale the part of the texture we draw // sourceRec defines the part of the texture we use for drawing // destRec defines the rectangle where our texture part will fit (scaling it to fit) // origin defines the point of the texture used as reference for rotation and scaling // rotation defines the texture rotation (using origin as rotation point) DrawTexturePro(scarfy, sourceRec, destRec, origin, rotation, WHITE); DrawLine((int)destRec.x, 0, (int)destRec.x, screenHeight, GRAY); DrawLine(0, (int)destRec.y, screenWidth, (int)destRec.y, GRAY); DrawText("(c) Scarfy sprite by Eiden Marsal", screenWidth - 200, screenHeight - 20, 10, GRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(scarfy); // Texture unloading CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Examples/textures/textures_to_image.cs b/Examples/textures/textures_to_image.cs index 31e1800..91970eb 100644 --- a/Examples/textures/textures_to_image.cs +++ b/Examples/textures/textures_to_image.cs @@ -1,7 +1,7 @@ using Raylib; using static Raylib.Raylib; -public partial class Examples +public partial class textures_to_image { - /******************************************************************************************* * * raylib [textures] example - Retrieve image data from texture: GetTextureData() * * NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) * * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static void Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] example - texture to image"); // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) Image image = LoadImage("resources/raylib_logo.png"); // Load image data into CPU memory (RAM) Texture2D texture = LoadTextureFromImage(image); // Image converted to texture, GPU memory (RAM -> VRAM) UnloadImage(image); // Unload image data from CPU memory (RAM) image = GetTextureData(texture); // Retrieve image data from GPU memory (VRAM -> RAM) UnloadTexture(texture); // Unload texture from GPU memory (VRAM) texture = LoadTextureFromImage(image); // Recreate texture from retrieved image data (RAM -> VRAM) UnloadImage(image); // Unload retrieved image data from CPU memory (RAM) //--------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update your variables here //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawTexture(texture, screenWidth/2 - texture.width/2, screenHeight/2 - texture.height/2, WHITE); DrawText("this IS a texture loaded from an image!", 300, 370, 10, GRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(texture); // Texture unloading CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } + /******************************************************************************************* * * raylib [textures] example - Retrieve image data from texture: GetTextureData() * * NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) * * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ public static int Main() { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] example - texture to image"); // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) Image image = LoadImage("resources/raylib_logo.png"); // Load image data into CPU memory (RAM) Texture2D texture = LoadTextureFromImage(image); // Image converted to texture, GPU memory (RAM -> VRAM) UnloadImage(image); // Unload image data from CPU memory (RAM) image = GetTextureData(texture); // Retrieve image data from GPU memory (VRAM -> RAM) UnloadTexture(texture); // Unload texture from GPU memory (VRAM) texture = LoadTextureFromImage(image); // Recreate texture from retrieved image data (RAM -> VRAM) UnloadImage(image); // Unload retrieved image data from CPU memory (RAM) //--------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // TODO: Update your variables here //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); DrawTexture(texture, screenWidth/2 - texture.width/2, screenHeight/2 - texture.height/2, WHITE); DrawText("this IS a texture loaded from an image!", 300, 370, 10, GRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(texture); // Texture unloading CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } } diff --git a/Raylib-cs.sln b/Raylib-cs.sln index 65ddc65..5ef9aa9 100644 --- a/Raylib-cs.sln +++ b/Raylib-cs.sln @@ -5,20 +5,16 @@ VisualStudioVersion = 15.0.27703.2035 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bindings", "Bindings\Bindings.csproj", "{9F30944C-415B-4763-91C7-81721117879D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Generator", "Generator\Generator.csproj", "{063F21F1-12D3-41C6-B598-125C725955B1}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Examples", "Examples\Examples.csproj", "{EF58DEDB-3ACA-46F5-A443-1B93D28F206C}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test.NetCore", "Test.NetCore\Test.NetCore.csproj", "{1298EE9D-E480-4014-BED0-C7CFE94C4AD7}" EndProject +Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Examples", "Examples\Examples.shproj", "{36E54E2A-5899-4D4D-9D78-120DB1B4C7B2}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.NetFX", "Test.NetFX\Test.NetFX.csproj", "{55D7BB37-3DC7-4A33-B21E-4F549EC988B5}" EndProject -Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Test.Common", "Test.Common\Test.Common.shproj", "{36E54E2A-5899-4D4D-9D78-120DB1B4C7B2}" -EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution - Test.Common\Test.Common.projitems*{36e54e2a-5899-4d4d-9d78-120db1b4c7b2}*SharedItemsImports = 13 - Test.Common\Test.Common.projitems*{55d7bb37-3dc7-4a33-b21e-4f549ec988b5}*SharedItemsImports = 4 + Examples\Examples.projitems*{36e54e2a-5899-4d4d-9d78-120db1b4c7b2}*SharedItemsImports = 13 + Examples\Examples.projitems*{55d7bb37-3dc7-4a33-b21e-4f549ec988b5}*SharedItemsImports = 4 EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -41,26 +37,6 @@ Global {9F30944C-415B-4763-91C7-81721117879D}.Release|x64.Build.0 = Release|x64 {9F30944C-415B-4763-91C7-81721117879D}.Release|x86.ActiveCfg = Release|x86 {9F30944C-415B-4763-91C7-81721117879D}.Release|x86.Build.0 = Release|x86 - {063F21F1-12D3-41C6-B598-125C725955B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {063F21F1-12D3-41C6-B598-125C725955B1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {063F21F1-12D3-41C6-B598-125C725955B1}.Debug|x64.ActiveCfg = Debug|x64 - {063F21F1-12D3-41C6-B598-125C725955B1}.Debug|x64.Build.0 = Debug|x64 - {063F21F1-12D3-41C6-B598-125C725955B1}.Debug|x86.ActiveCfg = Debug|x86 - {063F21F1-12D3-41C6-B598-125C725955B1}.Debug|x86.Build.0 = Debug|x86 - {063F21F1-12D3-41C6-B598-125C725955B1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {063F21F1-12D3-41C6-B598-125C725955B1}.Release|Any CPU.Build.0 = Release|Any CPU - {063F21F1-12D3-41C6-B598-125C725955B1}.Release|x64.ActiveCfg = Release|x64 - {063F21F1-12D3-41C6-B598-125C725955B1}.Release|x64.Build.0 = Release|x64 - {063F21F1-12D3-41C6-B598-125C725955B1}.Release|x86.ActiveCfg = Release|x86 - {063F21F1-12D3-41C6-B598-125C725955B1}.Release|x86.Build.0 = Release|x86 - {EF58DEDB-3ACA-46F5-A443-1B93D28F206C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EF58DEDB-3ACA-46F5-A443-1B93D28F206C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EF58DEDB-3ACA-46F5-A443-1B93D28F206C}.Debug|x64.ActiveCfg = Debug|x64 - {EF58DEDB-3ACA-46F5-A443-1B93D28F206C}.Debug|x86.ActiveCfg = Debug|x86 - {EF58DEDB-3ACA-46F5-A443-1B93D28F206C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EF58DEDB-3ACA-46F5-A443-1B93D28F206C}.Release|Any CPU.Build.0 = Release|Any CPU - {EF58DEDB-3ACA-46F5-A443-1B93D28F206C}.Release|x64.ActiveCfg = Release|x64 - {EF58DEDB-3ACA-46F5-A443-1B93D28F206C}.Release|x86.ActiveCfg = Release|x86 {1298EE9D-E480-4014-BED0-C7CFE94C4AD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1298EE9D-E480-4014-BED0-C7CFE94C4AD7}.Debug|Any CPU.Build.0 = Debug|Any CPU {1298EE9D-E480-4014-BED0-C7CFE94C4AD7}.Debug|x64.ActiveCfg = Debug|x64 diff --git a/Test.Common/Test.Common.projitems b/Test.Common/Test.Common.projitems deleted file mode 100644 index d597e9c..0000000 --- a/Test.Common/Test.Common.projitems +++ /dev/null @@ -1,14 +0,0 @@ - - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - true - 36e54e2a-5899-4d4d-9d78-120db1b4c7b2 - - - Test.Common - - - - - \ No newline at end of file diff --git a/Test.Common/Test.cs b/Test.Common/Test.cs deleted file mode 100644 index c9ada00..0000000 --- a/Test.Common/Test.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using Raylib; -using static Raylib.Raylib; - -namespace Test.Common -{ - public static class Test - { - public static void Run() - { - // Initialization - //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; - - // SetConfigFlags((int)Flag.WINDOW_UNDECORATED); - InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window"); - - var model = LoadModel("bridge.obj"); - model.mesh.Vertices[0] = 5f; - - SetTargetFPS(60); - //-------------------------------------------------------------------------------------- - - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update - //---------------------------------------------------------------------------------- - // TODO: Update your variables here - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - DrawText("Congrats! You created your first window!", 190, 200, 20, MAROON); - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - } - - } -} diff --git a/Test.NetCore/Program.cs b/Test.NetCore/Program.cs index c208cec..eebc491 100644 --- a/Test.NetCore/Program.cs +++ b/Test.NetCore/Program.cs @@ -1,12 +1,11 @@ -using Test.Common; - + namespace Test.NetCore { class Program { static void Main(string[] args) { - Common.Test.Run(); + core_basic_window.Main(); } } }

pSKq8%jfVb_y1e!H+R*3ztGaDst1KQ-JC#R zlh+ZaBkmv;j3Sl}N;;CBD8|jNFwY|G+0KA(8e(dRqU!gbPEwm1`}BGB&KWK>Ab6!h z=%Zkxz(+w4lnhjMIpPk3DK5PNg7PppQ4q!g(Gvq(O`TTV%5Ao{`_a)8;+J#oA_ZNO}J)^&5MQKl~M0Qrfr1XOoltEn&&J?EPA;tM8oMKDYJ#-v{pR zC#8DL__1KZoe#(R_on|~S$IGsF7x2=h4uVTU-?QO=x~~KaLen8vuj@qnBEM#^X25E zGB2OY`rKi94?B+@-9O>JrA~QZdqdx+GWFa-CgnSLeXWa3NL%-|Ni}aZ63S# z3a!b?kNXdQWmt0cd~mw)D@MsLov*lh?A-hVTQ~nS@w<7ct2h3J==@jr)4y;1^5KQAvy^%F z!GEzAH*(Jn3qNc6J!&g%0zb`@3CI>U;$6Bge*pA)Cv{e{=~i*|Ocby-=GOU+XEs<1T+ zgk$g5UVB!&(ZwaTQ+v_&s?!GrcicU%yf$LNZ^1Xd-OkfLY+V1snW53<^J|AovtRw) zE+2L9;E@TFcG-0-5so_Ut_?$Y8_Q@fNbY96-Cx^U@G$N5K7ZeKX3 zx%;`G>#R6_53g0cTbKWvKOuCP7uVvqJD+t2G*xaoJ@KLy&-q+aJGCEoc&hbI%P>WU zMKv9s_vc;FhKdKD+CTYNtI8EtEjXLBUG4H0hM%l@^)ast561uLyZ+J6uKm1p$t&3f zhix0@$=mkLe-ZKh@62CI-W^rblWTfj{#m2_%5jyyo06XX`f%jY%XqPlA5#=wZ@y{% zZ*TqUzy8mhYaDDQEzXMVFMk``uXbqN^(g^4jd#7b$W55S_ww!RoxdI}-}>I8X3?RJ zpQjR57~c%_G*H!3=RT`ppT4AZZ^oZ_0U^iM%-OX1mBfRLm!6NxdA)r<6lBddn_lwq zMIdNWdb zo#>JGt27MLlTY8YQ4X1OX%d^l-oqPLzFYr@qlHUuh1;X3=ytn?eGY0`iH{DqZu9cF zCS`dr;qa81VNRYZ`;(Iob^e$!YsOKJ^LlmRI-APoyH{#%)U;oh;}`K$e-Mz$*RS`@a=hc417hhXv`80a}|MU+Ux&@l` zAH5eY{L6W8)mGNdf|i?mU(Z{axBoADS-!XaFQ%C*t|;%*Fk7J|yryhjX6EC2KV+5d zmOq?xZHdypnrlCC+BD0g1J9RNyl9@$q@^p?X5{|$m)(zeyWR~cpG|xh zoxL*igiTKM*XzMaeu3vPR~D}6S3?&K2P^&mPX6#w9pk%hPAW3OCue&t7V)?`!z1 z8YRM+8KvNRRV-V^{yV>a_IVG7fCnvMiU*S(i`P3(UG(+C?s}6=yNqMycOSo=zCNqg z@OJTzUl$+VFR`0{)MUpY!B02C>tE-~or<}td6wti!cz&(3f7JRGna4td)sY;n0E1E z?;q1IX>UCwn8!P%X}z9@_1X2GRPA)kLU}4TzFwNp%<;3N>AuItnPv~NR%VBF-U4O5--TO zeMsU<&Ah3}?`@PEmNZ2x?wDOBe}4J)`B7&jB`co`8qT_KhwC|C;FB96w_^^s{@3ym zR4~4{(#%q<=1A!Nw_6rooh!NR#aWNj z|0W*JOuzNMXU&QeNz#XxOupUbF(+`Z;cfG;?>^q2dg!oxh^pwP1qQRvrd7>UetGm* zHJ_{d{W_1Xp1bc>M3pZ}`^{X>xBZ^Us_>ORvfg#@ztu7BUY+vV(d^RYKQ422)(M+XGTBR7AqoON4U`H{CnvQoQiTB&4o zZBz7@4B_9ezt2zmwXgldUTGzfH?xoP=uGIa&NkzZV&N{nep}&GaAb+ev79*Rn({Mt zB69^C`6a8a=%qCuOygDQH@gVzLyEBX3Eo;BF`nR#&vu(1nT$MZP z-irS1U(fx2AgHUeOng$@hgVPgJrr9jXDPeC*?0Z?tH94COMhgQJ@Q_byYYtiRymzl z>gQ%%5InIbWb@k(tUKI~q#t`Q6AI)div)Ge9udh72`P<+7 zeRnDzXQaIFVvpM%5wj*M`M7-L^?Uzz9epKp;Qr?gy+ZukdiVSj*H5oL^Der0Q{MIT zeXHJkC0&_ttwpKQ;L_w}j~yO~JzI7Em(SH@{Qno9jlF(6)q0!imqRDqXNg5FV%+{| zQjhCd)mN*zJNVs2O7?3Vt(tJ{M-toIn}1mLWlO6bHn#BAoOWqiWaiH}uOmTsUU|>I zecQV7-%0z4PR?_Gc=7)7UUbdzP1riY`7E~6C)FISTletA(Z3Q8_m^kA_eflSf9{*F zyIv0`zo5yqlXt(}CJ&J%>!jk(epxNlYq3pr z%8y?^u3Wu#Gh4DwX!edD`!nZmTyzSG6hV4H>boYDJ{9D2KZdc>=N*B!s zM+#R|yswDbX1n!U^StJr^Q3E&7nuFI$FuMp}yBkIXHKg7*vlsk(?|32u;n0xWi zGUnqJUp405cs*^g(e8hTOrPZxFduu?aI$J@>-uM(Rtrt4Or5S7Y%6?AT~)VyZR!jE zUonqERz9;1_R_fj^2u7+)}=o?r+k_GS8SU-Irg|*_~USEi{x{c&p%tUbH($<*G6Bz7>Tc0*V$$p|7*?7 zs;Rp`HU}-LJ@~9En#Ih&zGk8P^W@w(>zMi7VY*@5heMaH`4OF-dbV6ob79SL5C7Zy z3jUl`pV!I$=$5vA)ZWGuBA+_DBg6i3@}x?ARMp-iqehEBCTK6XcLCJm5>&SH&YN~8{;nC4M@8vPw1zU0#e6Wt2zt86AqsjL6 zukM%q%Xqv`U+&U#t|>Mf)B9CVWjS>4Et#=V&~uO^V{>n zi|T}1N`fc0D{IYMHa$}Ce$r1fsgItw0@7dZYir#t(5PP{{O@VKEcc(1x7<;weLW*@{h1E_{#3^FH!E*`Tj+k5 zcQ3!wjk>$r|Gj&EaBa}-bU*7?tke0v%fFwy*W#}91-qF>C7*2HzCZi_`EQAT=bo)Q z{BeE_pWV^q&a(FWIh7XAjSFi%H*egzq4L*HvtNiu!)RqpGDI^7_hVZ|%r`v^Mcs z+~ee}*3xP6Trm>q7Z(bwzJL4BoUMAfj4u0*H=pTyJ^%N?;KTcO%=^4^=08n^aJz{U z&FV!D%B333I;dRU@a3Jn-Pg)y@y zWTni%c;<_kvW?3nYs#Bq>;Ij4vsJ5uqgSqRN~h_~(l^nc|1iZbKhWW?yYX+?<{KT+ zm$HoBZn;{uRPN`)K7-}6tZ#&8-O{h;@I1f0?my?TOw|<2Exc;atK*~tu7;h?`?=r# z&hs@l|Kx|x=C?VVG5O;sm3>zPwHoJ5-&gnbW%rrOk5bKTk3{(XR==mY^&XE!F8`DA zh&grn*-nA{r!VegTUB;^`9B7!clDRbf;!aNpIgZAFOprE{MqWpGiB>EeLv=neS549 zylRMf{cy6-n^I}pX&S9hKUi<&{1+mb@t$|-+02g;bw`5v49;HIs_^>f?%*94%cFn& zeYx*sWb`zN_nAL~E}h`~b0~j<;X2Qorgzt$YWZ{S;puzxrtP)A_BXZb@HxlSt7bFi zzW15WeCaT&u6V(!j*PW7%64x#L~Uw{Uo2gHX8+>G+&}l#zin_8D;C*(clO(v>6r_* zXsBB0dwEJ^1Z+_*ot5|hl4AbrJAsaWkI%QSdfciV)f)Bx;_i7DryCbrPSa?eT2|v9 zr0;pL|ItI4*re39^A|i$-0_%JexyBhJ-@qO?4RxSCPJNOtlw$1$4_PanfP39!>QYB zpFhogSiI|O=a*A6er!<=F*vm2>391BZ{mLM@mS2F+H$<^huM#D^ZPUko(niaJ=Ue@TyzkNOg17I!xF|Mr$E(}^FZw^*O!K&MdV!Q- z)VqBJH}>zX`xe>!>#X+Yr7hESD}QI@n4G!y+LIr;Ro*- z_s^;SW8(7m9&6p!SJAqqiHqYO9op=xz5Uz7j{KRuYs*@^F3bM^d2f|(vHOZCuU@Ub z5)*%U?tJ?<_scS;UyU?oJJMjii2vZ%=~3UR_pLdyTx#ROXQehCzb0D!&wX8Nc139p3Ej&3*pIVL96g z_c*ieJY%tD>sm6+x2|$q=F@9-LLb*|NI&eA;=kvqTiwl1t0yNMNy*7OetHdqFsIqJ zS*L3p_5YmvU$frC_(qSkfyJt8U!MriUD~%hYv1Q`{s(cBcC4Ld=kL8_y4a`0Ez>oW zA3c71|7ldXm#YqE?t_Gh>@!+VPy1|Bc;-y;!Z(3BK8K9-b!|>M^}m~Xrj@B5VUgv~xbb7sAg9Rxc6)SGT{ zy5Yx%Erm7{8Nyv21r#aRN~z6PeguX(N_JY-r_4bkZG!TNf*%8Kg2v}2P5=RckL1xJ ztv|f}wx(4n&fdVW+GfM4x2^BJv@Zu;YVYXp=-2G=9umPgW;-4}_@(XN!>xv1x^e)~}K`ud!e z>34gr{SSS9eo*1=&lDZ$X;(vwdDrdd$ej0dYMSEbcn+O|?UL)g%s#aIyKSj zn{>3Deb503FQ25&4O{u8dOjETX0M6#bg`P@n!ssVpX{(h$9c!y=*@p8yB{(?XQR`e zFSBij%q@d?t--Tyo;*0`&+N{v3u1~&_%4)H%-0SRllPeZ>g?`*P!FZiHfd>3=#@`K z8|6f~yO$I#3HqD%^a%T#b&C`iw4a?Z_3FDHSCT)-zfs$*w!81I@Hal4iu(%;7Z|>3 zJeC2fzE+D!+Vsqrv2CjJEWZE8j3e`APx|kakg7eM^+>u>*ew1Ou65tIrZ9(XJbiji zRY-=;hKFj?VmKw5&YRpQT_bWyDRQERng8V!r@)yeVpskg3f=rTGR8b1s#c@)(cu+g zeWwom@Nl{ovbeEZ<5nGQ9dN$ok2s6A_f8S+?)4M7I<|V9?q(O;!pLWMW52f5t*;$fjb2)9w?FLKU3mTU zhx9cOnNPjs|K%ipz8`p)6~f(?b;u&BEFS3 zbKeM?=5T~vMt<6iqmvTCve(!ZJZ!IjmbdF``?@yS_1VWdv;z#ZHd|T<&2JK%&(g}6 zS>;ovCHyI#W6hVMjn-Y=N6jB;%UsLS)%S~N(mFmzD$M8Nh7k7*D_qlm9KPsaMGqS`@r-0F<#QIT1;41KWw@^E#T4X!{+DiNJ>h+n6p#t zRBz<@(wMXIZ>ry2UikXD)nRj`X9+K#Dm8n3>|C+4O1JT8tae#c?D^VT+Y|S*=iK8L z{SdqP>#AECuwx5diUdj zgy&b5zEquW{%G}&U3?EpEwk_0Xx@0{VYXLxTZC+I(_*bA?vR3YeZntiM$3EIKk_!< z)DqkmkY4)hx6rGM*3T}zDQrj2Z&dtwrODj<@$7tQ1XrK8`Ne}maNVtCSMaK7w$7^$zsqXX^}k!no;&}yP5xn+HEpitHr>4fhX3NSB1(U~;%-lx zoL;B@bos@L+U<`g|81B4R`*aqFTl|1RZz#T05!q*Ih?=r|C+z8Id!+>Z^DO58E-%6 z=bh=k^uw*DaM>>&-cqZ=8!n9>YJN<2J`?yj#drJq^OhnFlkeWUW*y&lXwI_*P6Bft z$A=nT>DuNMJEtang_)6zS&H_Fco~_`vi_g1Ezg;^bBpoP3lWW&t)3re5E-mC^XiDY1o*jo!V;Xko2Vi@f?Qi&wgq>9pXxa_KmRK!&|sFQrv= zB45{L8FJitZ?sDyWoOy5tJ_`_H$N{4Dr)fWTDeX2D&O^YE0SLv{wmLm->H5 zOipuAvzYw2&-AwZkEjjrcQz!*+IL<5Ah+(@L%ENRyNYz@|LhC-$GSRuQR4aOcC)+J zJSgrAJ|BAIW6g%E$sfKJuHE?3>e~((`4{SmApg)2pwzyf2yeeeM0vI~M=CweUi<`7O4(s;Qy5D--8EyT|_Y#gQ;woi#U0#O75q z&#PDGmuLsIn`g5m-10uTi&;9d=F=rTmHrwxr%kewB64#QmDk@*DBUf6bJzbZi}}M3 zzS5t|etMzZlz#!sXU)+FU-jI#Wj^aC>E?Tn*Jj1!T^8G3Apc5a>(%sQ-ul`9x-X0N zzUFS6!jkwjGA`{^t8`s<-S#<^vyCpTo)O`yv_DUwJKxQHx1O8(zrXMIthL*bmiRdT zYsrD!KL+KeEwBBs`{r6}SG9EFd?kyTM8-urKGm8BuWk)XKO13paYkKA!0j71-`jLE zx_N!DO+QlBU~idi_CNaSGv@nAzx=did?b!;4#<`Jt^Ol%L zW}j#)Q)2O6_Y9p1J+lkq+Y@fpRNeagIbO%`aM;wgts#{&SBm>R@m3RzH~gxl7AAO- ze|v^?>~`xB`0D%jcMPxf|K_y?ems|^DZG{Ye~sVv z)vEWk1uLJ=ExkRj%>1n#@BZ#53%klv1cYL%{$=OqB}CiZ{5b3G_Gcm!mtGetip-nvtD%ktBFwS!j@w^ur^ zyqkSPNq@_%#MMp-q9N;*e%#jSTQWobqo~7rr)l9*VJ_>P4+eR7=N~B4sJxQ2_4K-5 z+OoaxvuEyozN*}K_xh#k_choq?PJJf-?O&dW_!=^-YvSf1f#;*r!IYd|L&tyE5*O6 zHL~tT&+Zf+Sopy4ug;YPk`k(N9}V{&QmbAyIrjKI)ANzR?>`pKdwf|+K~M1hqo4lo zr#d?BpYr~X{GYP)iVt7*emr@{*1TEh3Z?`!w} zt}b{xwT7cRJxY@Ihrp8JRWJR%iT?j~T7K5r_gl^PzRA2<&GoLmXUW;HI)`swhFg@k zNPV-ZIda#gyhV)9_Eq2v%@&p!zn!kvS2FN#^>eNH#r-4Iv+k#Bjo`%Ab-o+B?^lYN z_vd==x2?5YaM!=!-V&+HAufK!HQi6_RbTVPy%cyePycoDzlow&ow0Lv?o+<-`O@{@ z{m<*lZ}UVyeRH+>ZBLS@D>!gXgyfg>PMohPIR9jo=%zhJ8*R?UZF_oMVs+;KBi7oo zLXT&L@qMyrm)2&u_}4<2i+h971R3{?))Lt>3byu>?p@IS|8eWY__*}1+f7Q>Sf7xX zAiu6kK3-KYzUXlDAD4EgZa)7{-9IMH&}v_J?&-7rAOB|06q=va^55#q!f8`GLPee9 z=2%Nst*npyHB;{6!ve7vIRdL6REZwG|ID=}@ubKj?Fn(MI_oPV{(Y<3_VB_Hxovy) zYM=Gd7OzaPZCVwx(gSNoXmJ<`jzcc9sXOwxAs~5@hdwW{yyeY z;{9J)&(_?onkO0kQ}~dHf$ou#AF;OtQs(X5=k#p9#I{qaj$3a2>i<@1Qoms9oG)6- zc$?oHo2#B(zPD6lV{C8Sv%Fiib3V>Ivpz)n+~G}?GRMrP9h)1lsK#oKifXicm(sKr zv)da^F#mY=Jm$piSiy9&hj}vIsy(77-sK+5&8d3!r{ZTs<_zm4A3m7Xyl0)x@Ot&a zd*{^8g6)n?C)Ygi^|3(Zt8x$C7rw4&4^f`DEF<9id{Lo?8@`U2UJF zZYLxpBs5t%;_ZvMuePmKe{cP>zT}anfeqgxRmGXTd8cjXtl#pG?+HdJ7zWOqmjWW6%T9T164&}Bx6f?|mi zdqLw4D;&T>5GUL~E(}p52VUI7AmeNu*(xIVc?{7lw8 zpddYsW!j46%Tw+gug=@NvBxZ<`^K82oFlVEc(xq={3T{HZ&+eZ*?lEC~nWfcDF}a$*$=-=OrOW4){4k%(z9#Qblw{bpA|+`t zdG8I?$5xw_{bSLa?`yiPpg#V^FMWQEjVpW8k|h=GJbq8R@uT(o@#Vk1hi>Yv5W4U6 zM<@7C?)O^xe|uPea;<;1Dw%XZNZT$Z0qxt$w$Ckzj9##6e zX;Guv?tQ=4tUa~&$>-qd_iUp!e{F0p(V4hmTL08AKjsF(6U*1E-18&ZGjOWvx{iCV zblKe>l-b{jZ|1Ga`Sj*G%kHxwI?7+=s=s(t8NZ+Vqwnfl1?ia&(q|e~{yX_?SM2|0eRLs%G3r02EZb9E;Ioyy|9`zsbtKib~B?D~A8 ztrxrg=v-Z<^wa3W#+$36-zGL)4GPSiFStfjSU$Mn$0COshpMJGwP%xxd!MYHAtcqz zCL$FanR+Jkj@Jx*Q$0q-=-+GB&HB7~`;&;xi`uMb%sOM=FQm!3rex*4J->IX-uE|V zpUW1Ry&=&%4s)GLYxGieKXz^Nud?uayycxQLM0<^T!`8(-99Dnucp8B+AHUSa#tD2rkc5*Hm>mH;;+AuH91SzY+=$ZyTuXO{Xas^ z^sw+PPGC5YRbKOo|B}@HrA{vd(uDsDzxa9aF=s-NkM_b9HC600^gY{>wkPkCYd(FW zx5T$h_P6>O{mmXx|Fl`OgPVSy+r2hvuNGH!;^Mrx%8x=D4q7Vguk$~BPhR}c`BN9& zPJcDd2$uKG4`$t6e&c@Gef$1-e_!*jGTf0Sx?=9x**^{}D2iy2(LCvTK%uDO%d`sz zR?nZhSh!lOw5a|4s@<92_wSG{-@D?gUx9~%;LKL$j|-=6saYBDz^r;z&_k87-OnCK z7@h9yI%u@oY^~Z}Ey3)##d$@Qg(~)M7+AQTra#SC{50ulR`An~BRWk-D`cV+-@fVU z^l#k|)Ymnk@rcex#h0$f*4KH(CS}}K^4b0{USZ$#$&&5&I@cJ@p6mRcAtHWOBhz-3 z8EdN^dMT)~xi#_Jl9}3ibgSOlpuJk6t7A@gzsmX-vGZ1lrA}tOtX@|7=e{3HBxl~7 zQ=GV2tM&Rx!I>vN9-SG!A$rDT@moCqzh+9ZADgCh;8|$c<9Q1tHPc=cu~=jZgb z8$(6J!XuYfg=&TEoF;zt>Yt58TUSb0Do(VB`PQ{@x!{_q!t!6#mb|n`4lQOYxt3cU zHAn8cd%Yd~^QE>_|N0_0@UR>YvF^vx1jSm=WW0 zBSZhWS(9{Fo#6eF9?s1DU$))*xM%OKud}q;_S~#9zWMjP|AYJ)R`*{-y=Pgsdh4-j z_Na(8$r>LMZl8Ev|M8Q}niWg#`kPpv7CZgr)E1U7#oUbVYb_(Uzc#Mt>AiAuYF<`= zR)nTt^YwR}ynBA#4$4?z%=~$^Ra(=Z39q#H*Tm$m;+Yuy$&@=ja+~0ujbV1j+4r&; zN~CX_`Xwu5+21tBV+$vI*riov(Q?$2=T8f}bN93RIcsixiwfJj+%fx3&Fk;;6K;lo zmE1Jf^00b$vZkPBWE|_p#3h$sRlU3XZ`*IZjZ^cp0!r4DaNf80{Nc#Ya_jV8>1pdt z?})uG`Qb0i^55ai%A$`yojel%t|@x8s{HL+dk>AI-tw~n>aP~(`%mln(ePu+j-Y9| zEs_yGc}v-neZHOFSO98@9z3nSf8K=6_Ow0gbiJQmv~JikBjKc! z)Z^b)GrqI5GevTFOIP=u_;9D!&vnkq%~q=dKDG$1@wq+oT6YYKcc162zfLy{7Opyz zwAFpazhB-v6PMl=xWxBxx7!Y#-4p6E*uoV5Y?x3N=2?36;r$;@bL*AMmi)15d@R?z zdy?~9hZ@11I=4BDH+<^(k#t6MX0)8h{5Q1)Z+a8WYAZkXt-hLjR_No=9dAk++zxHI zqZ_yF;o{q3d*n^OoSGVSX8x&_4$}@v{rbreU0xsz>3ysCKfk@&KQZ;zxizP@NQ7-_ z7uD|Il?{FE7m~m4c|7me1Kk}{^A5lAW$)YQa_HUty1xkv|4uN6yV3M()QLUcqTbHy z{qbZ%2sqp-&wV_)bzV@~dCv9L(syo|8O_|^$=5z}@2QE7HC^ANpWFS#j(bhrc+>0(tLKYTUgkS=RoC2PJNdAB zZQ5_<_l@~E3idHh|or+z0Ep`xP(Lp55QJ zQ2%dSNy(PChyK@0K52UHjq_X^rF||&I(~;c9G$TBriwU(HN&L6*L@tZ@8XKj3Pj-uX`J76K_uSq0J(lH0|g|(_TSA^6^iEn%G z`O3Lx-Zfc8j{{5}&lUJH@0OVRoLB#EsMK7VDgFK-ce@6t-?lVX?Cbp#HA?$RdRVt# z{&ZYgd#S(ShM=b1&l`gGq-4Cyn))KO%zsaWna+~)(h7U${`e)lj^+GMpVk{IrqoEy zzid{stjx^+(c#ZOlrA+*o$*6Z}!XCDf#tpS@J^G=7xbf zUa`+FTYKo`AC=v``BuPr`RNq_gvHUEKJrd7l33_QP&x4t!d- zI?1~4UFy88p=Sd3%847ep7LBDv+tn!Bkeu;BA1@`-Viu-LGN75eZd!XA78((dme5% zU%Om->LP#bDruj$IrEOR>#TX(HP=wT{r<;aFIF>K)=SB9ZEQ@h-aJW@Upw>XsgGGM zTJ=6p+oyWZFNqfA%6?ma>&TQJAX_q8_j+5VU@uDyvi5P`mR-Pd$M$X{^I$G$)`S5H%5T_Ua#*&?fWp7zrFtP z=FH5qr{$l?e@!^)T*#ZKt2(u9s+PLKUU}&omp5fprGDg{7vxnn^Vw&%+#OmuAxU-YSSw7c=#~)<4Nz`YtGFwEWiBj@-J({ z?QZV7-(9FS)E1L5yR6*tE^oo=IB?f>xPxyTHO* z*QkKOR23Hp3rfMb1nH%2HD8=G5(ULxMx2Z|`k}q(`r;`YI(~q=GaS(QR`47ubcPj4 zLW?6&5bo4afkR3H4{4QUO2y@4N6dUM?UhSX!G?oBQS4+53JSQWx%e z0$Sx;yW^XfjkH>|*d2A*OJ@=`CkW4|PCop`HB;-*qse>utD@gm@a^N1^bCe>dWfk% zbj0iykL{+Zr*$`eN-KOygrE;hYw_fg=_ zJ0XdHm_$W^Fv(<9B`xn5!M#_b`T7pLt=qAmP5Ru6A2-)?@?{@QNd0+o+RF0&|Lb&k zx0L`KY?)7v8u-t@vFY^GGFv8kHT?A1HD7oV(=J{vNN)5F-;-1&;r}`e*m6{!e!6(4V?& zmGJ#DSH`-H#ZolOI`V%MepLRzJaV|UZG-cuO%|DbR__b}n1@N5CI_hQ1w%2R+ z@1U?>5!;Tmb9+ynvBq>t z)1w#6?iTjd{(YvWFDAGwbMJeo(T}Mys2L?{@Up z=r!hFzRvribi43{a36+;x8~}e|8U^cs_<#Ygx70}&D_u1-LrLpqhr&A)~-tv*~9ea z&uLFii@p5y)Z{N>PvW`a?Q=d>ML2mHXqs%1m;1R+^2l=UqKW)BRF?7^KS)||{M?5J zFRKl^Tn>3hz?u8>UwpP*&Jt#gfHei&Di_$_@xK0 zWjO^;Tvaj%)LQeBVq0trUmZZ%hpE-}tYnvc8(c`f5^Ex2e4bW&jA4H-2Rzo$z(du)p`LUTgJ-tD-s;@b4Rwwv7*LsLVp zJDuCL_PO(Qf9EwVpK}keHLf&^*0|AT-uOrFET8WzfsYIAn6}*st;uCx@_m1Sh43k* zmLut9GpFAVP?x$lueQN*;o1d3k%vwu2G0oXN;UhaDJZFAx0>D|*lzWmndYx5#K_?0H~y*O~CImdtw6Th*SlwB>%ECGb&n z<({rq)~89AUr(5_Z!-5e&6Pp_^d*uboo_MwZvTI-@k6h1x!>1+kNlUuw1_D;DE#%y zy&zP+t~~7ajOD4l|n-$~ftnCFK*Z;V3HSFNCF6%$D&n*H0{9sfbycByl$ zw^m2F^GtVEb*T~hV(~#(wpT}L(&rbM%6{uocN=|i`e^6BCZ_6V{;IUEyR%J=KCQi9 z-z0hSXW~q=HMcd(KvV2Ya_1y{K6d>OxUPBgr#XYG#`>g0$HN<(x%l&glY;AJFV7U( z_kHO*Pl1oB_oa3=cveNjSY53zFem##Umfhu8NT+_!qaM*mR~SB1@cHnI44 z#yNWFcW0}=F6W;6Xv>Pk8883u`n#ofy7T+FRyMU?z0yB?G6~;1?X^0aYRAuzq{g!J zw*l!dsysH&{l6?@`PHv?mVLni*aq7Fr`|gcGc5if(_v39d;%)`-@3UWg??nq&G`p>W zx7^(mEv_3*dYAHiV9l6Q@oeFBr$@o2wxJXMo46RBS{)H_Ve@_4i(jt<-|9Y6rk#D` zcdN5m`P~SuM~7duHb-2zekAjYrR!(MFVZTZXT_&V&n+ss#J|I>u&OY7E2ud$&*uMT z`|Ab{`g8cVMX=`bapXS8+xJ!a>g@MF<-Ga!KhM2!<=E-u^!Al+bF2 zlld!*Sp=P%XRrPHVA-7awU(={&Hb?L-cKV5{r`oDvfAHm`qtcizA68%P*v|f!vO1l z&p5JoX6qh)?6}~1b=A^9i5p6MqEBW0Pj6d(t?ojx!S&(}(YpM$*L5|UMcso;ZF}8R zmIlQgJ#Tcx}USPLGFQ`yKiJ&)=G1tdzwqP~qb8BKzY>3F&`Fd7s@4 zSo$;V!JmM)U+2foKKgad&FrH`#Vp=WNoVdT4tzdg!jcOYg3tYW&7Qul=X&3K=~UC( z*^zJ8nKG_9?@;xh>wM|+-TBXgsxl>J^T{+H|Fz?6zwSeInG?!u&VN<4R(VnU%V4{R z+`hveJD+s@5OD6amh==s?CBIrSI3- znaQ=Xg!)4(BPw1*X7T((?{{>lU8wz*@x<-=#kTLY?>78v+9-JJujsF|4exh4 z1jyOW`Xs!2`%}@o>FXs__PTz(WXQ&tyez=(q-RpoUF)9N6|+P1xRv+qIOD-3^-+~~ zy^CydYu>dmGwzLIeD+C?m#s=mIQpeL>Q-ga%Weg|XBiT=cD|k(S@=aXl=QTlE3}w9%zHz5oRymKHghk=L+#gpMZWsLb)v>G06c-XPHW2UG$7wd_)I)VcL-JxFNg1R)eTp!>~`JrtdOg9Ye<;SkxONHoYK*G@jlXzT6QnaiuFIcjo)_H z(?;v~)%TvH|2j1UluUD70wJS#Pkv?Eb9atL9frZrGTKz2QFaeClD{ z@>sh&KmOf+V03-?*^jOokF+g5X5PM&z^@g>a5y~yG)jMMxDgsP*2B~H->1EPclXe% zve~btHTMc>@@&a0c@!2iV~Jpp%e8gWyZxuln!kjloZqlU#!vCK_OW9h9d3pF@UMCG zO8wr??&-JEeidBJH$ME`_U%2focvzF`LnJZpJG|1w9oaghxDmHu7n>VVK1U4eEoA* z^A5u{-M{}z?k_2uf8P64_v@v)DFz)=t@u9^RwC-EzqdX26YgB6VRpoblyJp|X ziq6t}8XH&K%PY6@i`!{-xj&2Qv%mk{d;jmthb6Z^ed&#<@-6NC6uBu}X1-3Oedey@ zwI3fB80A=$e!TxrAbdj8`8`QWKUGh&8*Fto%gIdkqf@^fDGNrfW{fLNn{~Y^zN7BqS z;mcS+E1$2ut$VGJv|HNt%-t=&EtY@MUKV%b#-8SCexq)Mt#@i4Zm6%`tGRDu(80Ca zKW)iZtlhNfuZw!ugWZqc^xpqp82vZ*Z0>El^=noBPW8;4p60Bxew+XOKOFm3cl=s( zZ$-V_lIH@=e|IZZFI<^!+UQz zH2zy={qOVM(Ajlc{h=d3GYcEC)WTlvl99ZxdoISl!`kMC4R7qq*AbR)?oGQ_qt-Y5 zlJ|V?s+FnxpP#<*`$^~4E1%sqY)W|i&FlGWYrEeQENm~NeKz6S@#^+@NxRa$C#q6i z>YmSfZ}rL2(rDW~p8F9m-+#5$t@ggDu6@^kOLIo@rf)N6bQrm>e3Q7oc9?*GZ_@|GJ@c5VOr@NUlCgNOfvw$kqR&n=(% zz|?!z^ML0$>w680mzfkLHhzo}>Uwg}z~0E&@3?_ZjSC&-!B8nfgpIgtJP5 zZ(YdEw&G(q%Jfx#%yM&@TA&rD%{RP_)4F>_a*0l*O6Z|A z9p{7eL|yDxR!V#OO?bqT@jvM^U&u$!?vDNqURUK$#rBH|#aG?lJ0;=vz1ekE$5*L= z77Kt@3_MzFqz+yz@JLw)v`69I5y$~4L7q-f7L!eLu;#>$6^U`v(kKAjJmI(6Rh?YgCVTCTo)4_aBw zo$|xi*e_9C5d;jKr`6t&pO+&$d&iFG&i=ArWm}A@H}Cc3iL+KY7gH~P=eFlE6_CP} z8jlWpTvNJ{!jty2<48y#qY=+m-`GFXmmh9k{+{(ywDU8FGKojREwdk=yS1%cCUo|^ zE`B!VPa!ibuU|9H?(ILSUM-(;+B#(dXw62;k`n*>Hm}K4S=?f3e|3B46 zIGHmrDXjW%=?-yC_Etrs($^}whtxS*)~#u4V%r;-zI|QsmYz><;}!*nuKP9PUA@gl zFH_xB?^S+!#H}}OFn&98U(uuMg?;Crt+Rg~UH|=i&b?*f2UZp=O+UFVs;Oo>Y`jnS z&AgARdgt0Vo=%@0EqSWcRP4oG{gS`a*{9sN;szQC4Y0k zT>pG_jh(OYQ$Bu8kZ<=Z>rO$zPyZGc6x-L_yY`>$v_trA8OgQY-+b2GVpk3e`&m4> z&amL;b(enm1+g7r z7tOwG)UMFfR^HjzrQpmTup#==$9z-f)f1|8TU+19o+_MrbI!I+diog+@~4k9oM-rX zpXt!6#*)Q+|Bsb_&8V=tZy7Kz^XVqXS-Kl!vc7&YIC_uugYdf4NUygX*LQ80)ydCO z`}xaM;rI*3?~9Apc5g}EvE!J7ZGu+_Q^M+RwSVr|+vKu^DSnOO6XPp=G{Jw7*NPRN zoO)jAvd?Flv-zh^Xgu#fb&HztyS}^sv#$GVy~I51%$7|z73O|<^5F%$GxPeous**x zhKKL9e)uhuI`jIqzNOdtKCIzhJ?+PV0`T^Tn#XV5oy@1z@m{!X^RwgZ>CA}_A2hR<#HpY2(6N(zoR#mW5o5h|!R4Kb zH;#RhR?@v$*5ZD1P1>Vw@F5Lv!@{<2Hhb=TIed9!j?yw$oi^9|*&^Bnxz)LW8`Esh z=^2!N&P^BGC-g;2WmoMx<$RAz?=T;|z3cbwbGLNY`^MKk z)W3SeLwB9V+9|(|NoSk7*PNEtnjrGd)?u~!%3Z7X{muQ+y!xtH;z2PE?O+$>CE-q0 zqKDfiJ^U*k-uc$cbnT5Jt}$1uvK3!hzu)BiC^-1%)T>v%mN)*GA;WyA_r%no`#+M` zhCOPIo2R<)$o2j?Kc97fQsPr;U%F&t=;LF@4C{SPi)~)+KF{z(x80dVGx}27bi3Dz zUz@md;i^xY5;cFgFrHqSa%q!Wj*gk-J+av~|BmeW?V<4N#1hvH$1mzE&0(%_53^q7 zJ8!;kjH~YJ&pV&Ycd2>#=!l}9$~Nu)pWa<+J+#z)@`Y*Uk8Pa7jKoCW)+uhVFpj_Y zg^PF2uKjCrBb@94H*GUkTzi7y%J1c3e%agK#2=q!ZN?@O`r5A|`hAV0)V-HM+Zwf& zpVDdmkyP|4luBb1V8}=+KVn=I=jlg5GXY&sQC3&4|n#$dh+Q!Sha=Jv% z=9k*nZ$J3FeCE^8Ff$#+`5KY`jTP6%e3gCQx~}*7E-5AVJ+Is987{KDAw-+zyv-(q@xe8(4~polCR_kK0gjd2V* z#yJrldzIdMzWFp++^6>fcjDooPn|(u?Ts%*t=Y%_?~B&$PZ#*a=I_~Z`dw}%tDgVV zRlGt$tImk=m1@mtv(mn3uleY5yisULviX~zmzq~bgQuoFyrl0vH(EERajNF6C%KIq z&TL6k{Icn%%$i-g-?OF6`sYT@HT^MZbHpXHGffNg?}ikBeP*~e=~}s5W~N|#$wQg> zGLyeff3AHzeMeH@k?D8BH1OzmEKQ;ixGQwsKi$o|%Vh4d-R$eUEOO-cr`0WLIkw zbN?wryY;j0MpvG&o%UL^Xu~CC<$`t7H(d9w((OxK_TQB~{l?bEJHy3iC+=>w&H8+5 zWy~clb7_T#4@*sx`~0tlm7Yq?)i=H^*!AO!@n)yL!E1ik&x^V6nD3ik*7wTZ#OYjN zUS@adcP@UacYgX;-gxCD*PV2($~>A}@LYWN^>erCYRk{Hx5e!|w(MY?P40AW`L`mx z=bj!(zrE(r($GA!13PVX_e-WU1Pb@hjqXZZ-?T;9rN&1(xUc_I&Wod~yUX3R1Xe#? zR~q2COe(Ty@l%eMTLrWenLa-3(|0&k>s$Wkn&SIi*X^ghl~lDV%zp4E2dnmlW;D;q+&Q~UKL6)~*2AXOuV!xFIt#Qg^vLTUpZ=cR z|M{Qt3+uA`vnKB;JiBfB$={W6qcV?Vo@BUd2PM+uzgW z(_Y(Gz38ub{rx}hljN@Lb`?U^C0kze^-Mau?QYTKLuVH!3yat1{m>u>*k z-|FX{xGTzcY=+d-o3i(Jw6ER&{&A)7{h}|8zvXH(ZiL)kJL8An-w&OW=U28}y?g77 z-3N32XTCL0Gn$uPy5v9YfIrK+?#$~SBmeNO%k!HN%I>pC{QE9n=ed%L=KC19Mzn+` z=zw;t?Re}~lJIh(hMe#(@0W}9nYyMddRx#w>C9cvu*tkdOPA))k~>{gyGy`o%BJ(6 z{n1lqyx4uNJal`mZRP#*_Sbh_`D_usm_M2|e0A>{zxw%}#cNemSSL@Ccx7^hTUFYJnV37s36=@!3B-z(C8h1Hyt*9>mgKy+2;0-amD{y{2LP1l#cb{lR;mbUTBN zV-)S_=!Y&6==iasN$?}m;s66ByF*60xuI{5z4!Z*|I2Z6i2mv6KVI0_2?+^Jl3`l1 zU3cM;>&KUaw+YJZo6r8~wc6<^+d-i;Aw(!JarQIs-6EI$JclOKYg6j-?8UKYWj}`hVds%sXd!A;Y@)%tbFx zDSM_HUD|BqAI&}aaG_dXj5W*k`6rC)Z;KYD1(!St{~dH4w9aHloz$oAW>XaeRrkn zp~^pnCww_}{_o$rz@pS`o} zli-dm{Ocl58mWlt*!6tT;gjBMe)UY7+6>mQl#3 z_q0Qhz`{1yo=$@Do@u$ENf*3BMbsiz%r7vi@N#wX>|hB^`G(ioU$glZ-&lQM z-m>4nZ5}Z<39)>r)?a^ca%<^IkvRJQB(D;+*q4_@!7|JGXs1Hwh z@z#COWbb~N9ZrqzIrG};e%w_pcyWPC+xKLmWmBU&qC*k6>erI*K~FgnB6TiA%VvAW zZm(9~`k(n{tQYU@C#%~N=3lr}Wd5#7@?XM}2glor(-wRWF7kOArFZm@)1}#!>tC-B z3AdybzyLa*`?=bfLGZl?L zc_#TCQD0GXrc<%1Mr+@b!+i6nt_<4I^>ll~vL_pI{J8gJ+&b`Sc9-4~yQ~KY2s%)9qPhp*J=w{F`Ui(ov`X;mPEXSg!(=V30G;1*C8Ket65$LuUQG zp}A|K3hZl?&$#3Wh)gehuA!(S^X$X6dq3sRyx8=@)gW!-8?k43``+sODW7FNErHec z+P#0wa#ayJ-`>1!(a8Q@InCQ}V*w*mT=>(UwQ{CfS^8$P8?+t1Y-VHLWVAK?PUPmw zfDN2$s*>Mv>co8&&uLYdJ$d4kSvuP4`xTEY&6yT|WV^!rybFuX?%z$FmZ_P3DiyuDh2s&_y=V|7wEjwTT z>e1nf-jwnsX<|9{+bNa{Jqt6${=^5RrSSVP4&ouUa6t1$0_nLv?K0y?&m(KPxp& zu5`ZNP=pQ-xmvf5{>f7#S~$_R)25|kHuXOYGiFV$p8`&SvKQ-lj)p7q~B+`EU9@gOBHq`o&c-wrQIc7M7RfEGYgVZvJdt_-)_S z-g}hne2iP>|5I3fPw35-2-#rJu@42-6WV3d`u$HyH8H>JowM_Tpd{DkW8aTj$^Hvw zKlsezyuIs@?Q4XZry1)QuD(4jvhjIUPon4SJ*Mwuj~;(?+Rc;aU}EaW11`}vAAGLG z-dn2&Iw|f;TRr0b;K`W|{to@5A9vTqy{P>kSMlL1|8Zvh zf0lYn4tQu-ncZmI!TI*iIhJDc`@ec$o&8?pFTcoZO0(_PnxxuN<(IvCf6h%04NRT$ z)hmK!_8guwLQ(rd@1(kh?6`hA#_V+e522`8VzU|EHZDkvSW^~rV{=lwm+X9#qGz-9 zwJzSNIxRReJ~pycaK6~L?lWSi{{_!cKJeS7E!B&&`+SF|5VQT?=AFymN7?V0`0%3Y z1!e2G`Tb{nYQtvpX9&(WJHFlEk+-gbkprK_`69mZ_tTx6{dY?JWpCcQc|^9uqR&X2RqxZVe0|qaeshGb&xY#sPn~+<~lKK)u_CO@P1hlr~8k@PiZ zuk}yJI^3aQCY2ce|7~p8=EaST3YQ_BXTw5+3d=y~0yRe*p+T$D)Ii z#(Bseu+-#rp4Gq5fn~8o$B!U)kKVl>`Oo{s&S_~2O}lD-)u4PbyLio?Gm+I>dG~t< z7nVIvUoW$E-^;g)dwQZwub;r&&p-HxGe$M`?Ek`^5{3`z1 zciL;d(zMf{<%MhIjfFL)oGsdWuHo<{w&y>#C@(SSU2Xp=ao<_foag!P-(NnF`1-Fu zm)Z4@!}AvYo!<9%Px7NX9JjyC-fjRo$@$^^Cyn>JY)W{({CQz0d@3(+?}L9UB$t?5 zw{YyRQMNOFC3L>#k=mULZC|eB{JyaGUE4i&*4^KC<^R3ABY`8nlgmix@sa5PU$5pA zRyrPDYszM!Bl7ezv%Z;F{>6BuvpWyFH|Dg9Cf+&G_mx#kT=Kr(63uf4_Q-|Gb=euz>slXWx%i&mM_c>SbQ9e9UC|NB7T87OOtLGTGbtZG96TN}iop zuu}K$KcD&wCe^R19){^j2WfA zn)SYEi_JH)H?==Hc0WCHI63{i?7M%bjn{lU7j~`W_=P%^7N?s!iYq;N?&K<46>7)S z$0*;Ou_o61@OOv*9$hkLE*M&AZ2ZoaE|xpv?7ID$2d95^yguFG`SzVWib~5)m_K@a z*KEc_|Gl3Lj(GTV{4i0U5cwi%LhO&*^YvdC`o+(>^3K?=o0qHi=+;ALCeDNJj9zbZ zb@Jz(PB+#i`WGMn)t@COyl;Kg*OaxDol!k(FMlB?s^iz}NngLm zzRTEo`g3aSJEJ6y5YL-IzU%Arl$}@4x!pD^=BJA0%MSnh8=35!4=YZt?r}X}r2c60 zs-zREP3P&yMTX^H(7A2-mrw0D)9r|&;zu8Y^u_P&;|w=4yZ>`$`>On17jFJve_md; zYU65+e_|EsN9IKBXnDVK(i!EZV^jNUeYgL=rkMZwwfyN*l2Insw+`y>ikUaxqv#|u8@NMGvD@;a~X87UC&RLn4E!@X}mZx`7; zyZs^^v`8@W(}B}dyE=Y{T4l|7bIpE_^>gRH$MrXzEI#a}{nAEf_VsnT-&5JPwVn!} z?{tGN{2FK&;(YLar&km2WjyYRSbIF6{B^YZ=0x#B_lr35b{;)EFS16z<8XsC-`CPD zclI{6+v?xEQ(B>N)joZ9r}K^<>y)nL&nsOOP-o;_GvWWn|MT~L{+X%N@#u${>xy0l z&d>`52bQ!{U2Il4)Yvjv@zu%ZB87(;hZe`uw@Yir{3tyvTF(=l}M;>|0qU)Cs1{aB)8l(Jf) zs8#vG%eI9g>+Z$Qcq#kS8?wYeRZt z!#|x0OH%keak;=cFI$_G_nW8Qe{x4>Zca#UzAy9k$aEw1+ut(Iw|(2U&R2E*r7n*{ z758-V_EnYb`29ETFoW;!nUiY0md@R9eNxD#H`nXe=KT56ztrVcfo0OX2icz2R(0-s z{=I#E-$ypZ$d50#-Ryt(W%aT3`Ev9Bs3)B`_CN2Eb^Yp`>9ZHwyFFSQT$a=CDt^y< z)9F<#g&Qxs%TG-X7h8FAWl%qx_I~|qg>_StpSgE#uUj_%?Zrm^U%S6bO^9}XY+c1y z_G!D<&R+G`-r2p=vz8VK*eyNe_b*6${lAUhZ(TXvzMS!0(Dnjpz49}UTefC-Et%B! zygPo+0lx1Zb%$A&sN0=glad&}NZL)>qcwlEL-EDKo$WJh!%9C#W^Fx?vhsp@&Zdx8 z4;5#>TQBS8sc*mYT4TShqv6I`aW9qT-@N^)e`DgumBy>jbhgf1eE03a$w!nH^GC3eJtTSn0R9eE$sg{Zq7;D+|jv$qC6H<9WQSqaqfP>gE;ZFWK$)!iw85kH` zI92Qz7#KWi7#J8Bgyb0*7#hIh3LhC!g%`|7W@KX!wmv@HZNhz1kZMm?KbLh*2~7ad CewL&F diff --git a/Examples/text/resources/fonts/alagard.png b/Examples/text/resources/fonts/alagard.png index 3ac4bf1cf5d65bbb749f4075570e1bbd2aab8b38..c0c54273140fa4c039cc15028852e5eaa0d6a173 100644 GIT binary patch literal 3626 zcmeAS@N?(olHy`uVBq!ia0y~yU}ykg4rT@hhA$5${$yZaU@Q)DcVbv~PUa;80|QIC zqpu?a!^VE@KZ&di49pAxJ|V6Q3=IDn{{R2~pJ5b?hQP=Rft{T)`xqD)8A^iuf0#LT=By}Z;C z1rt3(J;P+JIo=EmoXwstjv*CsZ>RSb$yo9=o7ep>zjv5@f>5-r@wuCYH^arRZDVOt zXubHy;`jOW`F-_uf4wVs@9a)GcraGD;3>cPqg69o?;C%(wjf#U!72H?BcaCJmk-RI zW<_?L66=vE@mrhRqJs%1xq9)%O~{=J5*TH!PSr z)xtZy$p72PsIY6Ta}I}f+`7xqTF2>fP$*-4W5A#1k52`t9q;?Mx<@qPcoz4mE0-Od ztV6X07Ukw~H)!7B*-&~ci}ygZ=!zKLC$Ytk+~hR&Z(gYz#>4DYD3M@%GtqaWqtaa4 zosC-r#n!J>;Lf~$Sb(dacf%VeUePP{OdrIV_ol2Dwz)MSs?h7s`=#yXIx81#YMcG_ zZ|Jvw(GA&-#agZT%qk{(jT~BEp51l3Xw!3fr`)?)dmFM3aX4?f@a0s)!j`kQ95!rP zp6|$Bz_0#7j_Glg@3QN!B^FgOUq8goBVf#Uy?4rvRnAAg=9Y=ooo+}jxX!X>xn5fA z5!WO7httv-neWS#GC$3}z2^=8jOz?@_S{sy{ZX0chw+(pOYMEnYW6%3HF%>MXp(U( z_C!V1-c;+91N*Alxda=5yCu}a#4TMoNce7fS& zdfZ#5r?D-|xP^-Yd4gvvGcSM|#VQ*rfSBWzqs& zO3Dg*%P#k={}p|~-Ml)*dfyp`r)TAE_URiv*uG@a#`QVJ&;MlaOjgxDkX;g>Qyx0^ z?GH(|AOAEKS?rH-`zPAUIdwn#Gcm7b%}EN=nuD&~H@z^&93uD)fX4gA3 zT`MEpHpom_bgt}#L+IB9U*FANdRAh_&ILh|k!mF(k$JxkGtA+Nn;UUT$%S9HRGq7n zE7$MEf-MpoTOMWB&V9S0of!_8~gZ}xqCenUz9K$cKLp>U59vu3Nd zNvh)A1DCGM3rx3urMuy|#D?1*SHB)>BV%<_RzEU4HOHNIinc7?r6tTuZ62N%l;AA+1Fy(DgMCJO2fB) z!K%%&|1{T0yafl|Z+SMC#a6c;+Pi6oePY_<#(uOY{OZlV`M>xlF}{BwSQS#^LaYKOk}C!O0+6zKi*z4Vg{=L>uFnhKf!PAIwPpuyx|{P)xs zk?ZeWFRZ-0%eskoo(~7D)Bqi(JIbM^1%+7ho4z<6igQONd&BAx85(pSDFYO6=r@UAQbq; zQijVUeNl#|b2XS1?=0o5FbrVz)?;(w@?#FO%vrFj%sfl@*3Wz`n*`BqjK`hA znXhhKy;Zwm?!8z3oc;CZ4_JISlfF>yQCPi~fgc;oJgErpN3-Nx{qnyqcey9zz*AE^ z$Na#jhN!|T$LiR(rbl00_}h@J!v2J#PI=aGKPla3Y+2Wjsq1wny*|}oFYx4F)(`3O z0OfbZ-}c-(?{#eLs|!aR>?S@jTqXS3R+0H_*wNZ^^TK~ep4<^CyG!DOr}rTv&9#fP zWIY2+q%&?yy?wNK=_$t8Yeqa%Hmq{>3}##OVe*m}Nn#)NNq@N%`uTp-*L`I-TT>70 z5{dAc$(uT7`6Q<|rjh}_vl8Bi2j;UBEX++1iO4zN&l3@N-gTZ~_Ptduk7E^HX5^F@ zUpUQt>ZV^0m(H_B#zsH)CD0z3s5U zWanbBZ9O(0OcFY$vrpMPmnBowOgLbL$-VGdS*IFLJG2YFk~V#`qVoF|wO1^QzUBDx zeK~Vr<=vGaAy<=yDdESiJ#pygeX>oj1u{%Wb8&uDk=tMb?7yicO1Xq%nuX8APt+4D7g|D>2Lr!Jz)2ht=2A&ZAPuB!>OBb ze;&Q&-#e$qE=Qr>Px8*>WCxGkv6k}rj8-e{O7^wcgrXT+2J-EL9KLh*Uw>|e&zU4D8Ffe$!`njxgN@xNA4NbgQ literal 4424 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 bo{^1#TOwCo0#LT=By}Z;C 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