From ed8c4c1b9b0154a84746c9316a58023d7d351ff2 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 17 Oct 2025 17:01:38 +0200 Subject: [PATCH] REXM: Update examples collection, some renames --- examples/Makefile | 6 +- examples/Makefile.Web | 18 ++-- examples/README.md | 12 +-- examples/core/core_highdpi_testbed.c | 6 +- ...nitor_change.c => core_monitor_detector.c} | 14 +-- ...r_change.png => core_monitor_detector.png} | Bin examples/core/core_screen_recording.c | 6 +- examples/examples_list.txt | 20 ++--- examples/shapes/shapes_pie_chart.c | 2 +- examples/shapes/shapes_simple_particles.c | 34 ++++--- ..._starfield.c => shapes_starfield_effect.c} | 83 +++++++++--------- ...rfield.png => shapes_starfield_effect.png} | Bin ....vcxproj => core_monitor_detector.vcxproj} | 6 +- ...cxproj => shapes_starfield_effect.vcxproj} | 6 +- projects/VS2022/raylib.sln | 4 +- tools/rexm/examples_report.md | 18 ++-- tools/rexm/examples_report_issues.md | 2 + 17 files changed, 126 insertions(+), 111 deletions(-) rename examples/core/{core_monitor_change.c => core_monitor_detector.c} (96%) rename examples/core/{core_monitor_change.png => core_monitor_detector.png} (100%) rename examples/shapes/{shapes_starfield.c => shapes_starfield_effect.c} (66%) rename examples/shapes/{shapes_starfield.png => shapes_starfield_effect.png} (100%) rename projects/VS2022/examples/{core_monitor_change.vcxproj => core_monitor_detector.vcxproj} (99%) rename projects/VS2022/examples/{shapes_starfield.vcxproj => shapes_starfield_effect.vcxproj} (99%) diff --git a/examples/Makefile b/examples/Makefile index 498a36f47..30d619e94 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -529,7 +529,7 @@ CORE = \ core/core_input_mouse_wheel \ core/core_input_multitouch \ core/core_input_virtual_controls \ - core/core_monitor_change \ + core/core_monitor_detector \ core/core_random_sequence \ core/core_random_values \ core/core_render_texture \ @@ -572,7 +572,7 @@ SHAPES = \ shapes/shapes_rounded_rectangle_drawing \ shapes/shapes_simple_particles \ shapes/shapes_splines_drawing \ - shapes/shapes_starfield \ + shapes/shapes_starfield_effect \ shapes/shapes_top_down_lights \ shapes/shapes_triangle_strip \ shapes/shapes_vector_angle @@ -632,7 +632,6 @@ MODELS = \ models/models_cubicmap_rendering \ models/models_first_person_maze \ models/models_geometric_shapes \ - models/models_rotating_cube \ models/models_heightmap_rendering \ models/models_loading \ models/models_loading_gltf \ @@ -643,6 +642,7 @@ MODELS = \ models/models_orthographic_projection \ models/models_point_rendering \ models/models_rlgl_solar_system \ + models/models_rotating_cube \ models/models_skybox_rendering \ models/models_tesseract_view \ models/models_textured_cube \ diff --git a/examples/Makefile.Web b/examples/Makefile.Web index 1b32ebddf..222c56e11 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -529,7 +529,7 @@ CORE = \ core/core_input_mouse_wheel \ core/core_input_multitouch \ core/core_input_virtual_controls \ - core/core_monitor_change \ + core/core_monitor_detector \ core/core_random_sequence \ core/core_random_values \ core/core_render_texture \ @@ -572,7 +572,7 @@ SHAPES = \ shapes/shapes_rounded_rectangle_drawing \ shapes/shapes_simple_particles \ shapes/shapes_splines_drawing \ - shapes/shapes_starfield \ + shapes/shapes_starfield_effect \ shapes/shapes_top_down_lights \ shapes/shapes_triangle_strip \ shapes/shapes_vector_angle @@ -632,7 +632,6 @@ MODELS = \ models/models_cubicmap_rendering \ models/models_first_person_maze \ models/models_geometric_shapes \ - models/models_rotating_cube \ models/models_heightmap_rendering \ models/models_loading \ models/models_loading_gltf \ @@ -643,6 +642,7 @@ MODELS = \ models/models_orthographic_projection \ models/models_point_rendering \ models/models_rlgl_solar_system \ + models/models_rotating_cube \ models/models_skybox_rendering \ models/models_tesseract_view \ models/models_textured_cube \ @@ -795,7 +795,7 @@ core/core_input_multitouch: core/core_input_multitouch.c core/core_input_virtual_controls: core/core_input_virtual_controls.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) -core/core_monitor_change: core/core_monitor_change.c +core/core_monitor_detector: core/core_monitor_detector.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) core/core_random_sequence: core/core_random_sequence.c @@ -920,7 +920,7 @@ shapes/shapes_simple_particles: shapes/shapes_simple_particles.c shapes/shapes_splines_drawing: shapes/shapes_splines_drawing.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) -shapes/shapes_starfield: shapes/shapes_starfield.c +shapes/shapes_starfield_effect: shapes/shapes_starfield_effect.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) shapes/shapes_top_down_lights: shapes/shapes_top_down_lights.c @@ -1154,10 +1154,6 @@ models/models_first_person_maze: models/models_first_person_maze.c models/models_geometric_shapes: models/models_geometric_shapes.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) -models/models_rotating_cube: models/models_rotating_cube.c - $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ - --preload-file models/resources/cubicmap_atlas.png@resources/cubicmap_atlas.png - models/models_heightmap_rendering: models/models_heightmap_rendering.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ --preload-file models/resources/heightmap.png@resources/heightmap.png @@ -1201,6 +1197,10 @@ models/models_point_rendering: models/models_point_rendering.c models/models_rlgl_solar_system: models/models_rlgl_solar_system.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) +models/models_rotating_cube: models/models_rotating_cube.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ + --preload-file models/resources/cubicmap_atlas.png@resources/cubicmap_atlas.png + models/models_skybox_rendering: models/models_skybox_rendering.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ --preload-file models/resources/shaders/glsl100/skybox.vs@resources/shaders/glsl100/skybox.vs \ diff --git a/examples/README.md b/examples/README.md index dbc36fe22..b40966a5a 100644 --- a/examples/README.md +++ b/examples/README.md @@ -49,7 +49,7 @@ Examples using raylib[core](../src/rcore.c) platform functionality like window c | [core_window_flags](core/core_window_flags.c) | core_window_flags | ⭐⭐⭐☆ | 3.5 | 3.5 | [Ramon Santamaria](https://github.com/raysan5) | | [core_window_letterbox](core/core_window_letterbox.c) | core_window_letterbox | ⭐⭐☆☆ | 2.5 | 4.0 | [Anata](https://github.com/anatagawa) | | [core_window_should_close](core/core_window_should_close.c) | core_window_should_close | ⭐☆☆☆ | 4.2 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) | -| [core_monitor_change](core/core_monitor_change.c) | core_monitor_change | ⭐☆☆☆ | 5.5 | 5.6 | [Maicon Santana](https://github.com/maiconpintoabreu) | +| [core_monitor_detector](core/core_monitor_detector.c) | core_monitor_detector | ⭐☆☆☆ | 5.5 | 5.6 | [Maicon Santana](https://github.com/maiconpintoabreu) | | [core_custom_logging](core/core_custom_logging.c) | core_custom_logging | ⭐⭐⭐☆ | 2.5 | 2.5 | [Pablo Marcos Oltra](https://github.com/pamarcos) | | [core_drop_files](core/core_drop_files.c) | core_drop_files | ⭐⭐☆☆ | 1.3 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) | | [core_random_values](core/core_random_values.c) | core_random_values | ⭐☆☆☆ | 1.1 | 1.1 | [Ramon Santamaria](https://github.com/raysan5) | @@ -66,8 +66,8 @@ Examples using raylib[core](../src/rcore.c) platform functionality like window c | [core_undo_redo](core/core_undo_redo.c) | core_undo_redo | ⭐⭐⭐☆ | 5.5 | 5.6 | [Ramon Santamaria](https://github.com/raysan5) | | [core_input_actions](core/core_input_actions.c) | core_input_actions | ⭐⭐☆☆ | 5.5 | 5.6 | [Jett](https://github.com/JettMonstersGoBoom) | | [core_directory_files](core/core_directory_files.c) | core_directory_files | ⭐☆☆☆ | 5.5 | 5.6 | [Hugo ARNAL](https://github.com/hugoarnal) | -| [core_highdpi_testbed](core/core_highdpi_testbed.c) | core_highdpi_testbed | ⭐☆☆☆ | 5.5 | 5.6 | [](https://github.com/) | -| [core_screen_recording](core/core_screen_recording.c) | core_screen_recording | ⭐☆☆☆ | 5.5 | 5.6 | [](https://github.com/) | +| [core_highdpi_testbed](core/core_highdpi_testbed.c) | core_highdpi_testbed | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) | +| [core_screen_recording](core/core_screen_recording.c) | core_screen_recording | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) | | [core_clipboard_text](core/core_clipboard_text.c) | core_clipboard_text | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Robin](https://github.com/RobinsAviary) | ### category: shapes [31] @@ -101,12 +101,12 @@ Examples using raylib shapes drawing functionality, provided by raylib [shapes]( | [shapes_dashed_line](shapes/shapes_dashed_line.c) | shapes_dashed_line | ⭐☆☆☆ | 5.5 | 5.5 | [Luís Almeida](https://github.com/luis605) | | [shapes_triangle_strip](shapes/shapes_triangle_strip.c) | shapes_triangle_strip | ⭐⭐☆☆ | 5.6-dev | 5.6-dev | [Jopestpe](https://github.com/jopestpe) | | [shapes_vector_angle](shapes/shapes_vector_angle.c) | shapes_vector_angle | ⭐⭐☆☆ | 1.0 | 5.0 | [Ramon Santamaria](https://github.com/raysan5) | -| [shapes_pie_chart](shapes/shapes_pie_chart.c) | shapes_pie_chart | ⭐☆☆☆ | 5.5 | 5.6 | [Gideon Serfontein](https://github.com/GideonSerf) | +| [shapes_pie_chart](shapes/shapes_pie_chart.c) | shapes_pie_chart | ⭐⭐⭐☆ | 5.5 | 5.6 | [Gideon Serfontein](https://github.com/GideonSerf) | | [shapes_kaleidoscope](shapes/shapes_kaleidoscope.c) | shapes_kaleidoscope | ⭐⭐☆☆ | 5.5 | 5.6 | [Hugo ARNAL](https://github.com/hugoarnal) | | [shapes_clock_of_clocks](shapes/shapes_clock_of_clocks.c) | shapes_clock_of_clocks | ⭐⭐☆☆ | 5.5 | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) | | [shapes_mouse_trail](shapes/shapes_mouse_trail.c) | shapes_mouse_trail | ⭐☆☆☆ | 5.6 | 5.6-dev | [[Balamurugan R]](https://github.com/[Bala050814]) | -| [shapes_simple_particles](shapes/shapes_simple_particles.c) | shapes_simple_particles | ⭐☆☆☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) | -| [shapes_starfield](shapes/shapes_starfield.c) | shapes_starfield | ⭐☆☆☆ | 5.5 | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) | +| [shapes_simple_particles](shapes/shapes_simple_particles.c) | shapes_simple_particles | ⭐⭐☆☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) | +| [shapes_starfield_effect](shapes/shapes_starfield_effect.c) | shapes_starfield_effect | ⭐⭐☆☆ | 5.5 | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) | ### category: textures [26] diff --git a/examples/core/core_highdpi_testbed.c b/examples/core/core_highdpi_testbed.c index b22aa507a..5cd2a7dc7 100644 --- a/examples/core/core_highdpi_testbed.c +++ b/examples/core/core_highdpi_testbed.c @@ -4,14 +4,14 @@ * * Example complexity rating: [★☆☆☆] 1/4 * -* Example originally created with raylib 5.5, last time updated with raylib 5.6 +* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev * -* Example contributed by (@) and reviewed by Ramon Santamaria (@raysan5) +* Example contributed by Ramon Santamaria (@raysan5) and reviewed by Ramon Santamaria (@raysan5) * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 0 (@) +* Copyright (c) 2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/core/core_monitor_change.c b/examples/core/core_monitor_detector.c similarity index 96% rename from examples/core/core_monitor_change.c rename to examples/core/core_monitor_detector.c index 3286ba22d..0e94f6895 100644 --- a/examples/core/core_monitor_change.c +++ b/examples/core/core_monitor_detector.c @@ -1,6 +1,6 @@ /******************************************************************************************* * -* raylib [core] example - monitor change +* raylib [core] example - monitor detector * * Example complexity rating: [★☆☆☆] 1/4 * @@ -19,8 +19,8 @@ #define MAX_MONITORS 10 -// Monitor Details -typedef struct Monitor { +// Monitor info +typedef struct MonitorInfo { Vector2 position; const char *name; int width; @@ -28,7 +28,7 @@ typedef struct Monitor { int physicalWidth; int physicalHeight; int refreshRate; -} Monitor; +} MonitorInfo; //------------------------------------------------------------------------------------ // Program main entry point @@ -40,9 +40,9 @@ int main(void) const int screenWidth = 800; const int screenHeight = 450; - Monitor monitors[MAX_MONITORS] = { 0 }; + MonitorInfo monitors[MAX_MONITORS] = { 0 }; - InitWindow(screenWidth, screenHeight, "raylib [core] example - monitor change"); + InitWindow(screenWidth, screenHeight, "raylib [core] example - monitor detector"); int currentMonitorIndex = GetCurrentMonitor(); int monitorCount = 0; @@ -67,7 +67,7 @@ int main(void) monitorCount = GetMonitorCount(); for (int i = 0; i < monitorCount; i++) { - monitors[i] = (Monitor){ + monitors[i] = (MonitorInfo){ GetMonitorPosition(i), GetMonitorName(i), GetMonitorWidth(i), diff --git a/examples/core/core_monitor_change.png b/examples/core/core_monitor_detector.png similarity index 100% rename from examples/core/core_monitor_change.png rename to examples/core/core_monitor_detector.png diff --git a/examples/core/core_screen_recording.c b/examples/core/core_screen_recording.c index 9d0611bde..43c90eec5 100644 --- a/examples/core/core_screen_recording.c +++ b/examples/core/core_screen_recording.c @@ -4,14 +4,14 @@ * * Example complexity rating: [★☆☆☆] 1/4 * -* Example originally created with raylib 5.5, last time updated with raylib 5.6 +* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev * -* Example contributed by (@) and reviewed by Ramon Santamaria (@raysan5) +* Example contributed by Ramon Santamaria (@raysan5) and reviewed by Ramon Santamaria (@raysan5) * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software * -* Copyright (c) 0 (@) +* Copyright (c) 2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/examples_list.txt b/examples/examples_list.txt index 7abfdd453..6c9d0c3bd 100644 --- a/examples/examples_list.txt +++ b/examples/examples_list.txt @@ -31,7 +31,7 @@ core;core_world_screen;★★☆☆;1.3;1.4;2015;2025;"Ramon Santamaria";@raysan core;core_window_flags;★★★☆;3.5;3.5;2020;2025;"Ramon Santamaria";@raysan5 core;core_window_letterbox;★★☆☆;2.5;4.0;2019;2025;"Anata";@anatagawa core;core_window_should_close;★☆☆☆;4.2;4.2;2013;2025;"Ramon Santamaria";@raysan5 -core;core_monitor_change;★☆☆☆;5.5;5.6;2025;2025;"Maicon Santana";@maiconpintoabreu +core;core_monitor_detector;★☆☆☆;5.5;5.6;2025;2025;"Maicon Santana";@maiconpintoabreu core;core_custom_logging;★★★☆;2.5;2.5;2018;2025;"Pablo Marcos Oltra";@pamarcos core;core_drop_files;★★☆☆;1.3;4.2;2015;2025;"Ramon Santamaria";@raysan5 core;core_random_values;★☆☆☆;1.1;1.1;2014;2025;"Ramon Santamaria";@raysan5 @@ -48,8 +48,9 @@ core;core_render_texture;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Ramon Santamari core;core_undo_redo;★★★☆;5.5;5.6;2025;2025;"Ramon Santamaria";@raysan5 core;core_input_actions;★★☆☆;5.5;5.6;2025;2025;"Jett";@JettMonstersGoBoom core;core_directory_files;★☆☆☆;5.5;5.6;2025;2025;"Hugo ARNAL";@hugoarnal -core;core_highdpi_testbed;★☆☆☆;5.5;5.6;0;0;"";@ -core;core_screen_recording;★☆☆☆;5.5;5.6;0;0;"";@ +core;core_highdpi_testbed;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Ramon Santamaria";@raysan5 +core;core_screen_recording;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Ramon Santamaria";@raysan5 +core;core_clipboard_text;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Robin";@RobinsAviary shapes;shapes_basic_shapes;★☆☆☆;1.0;4.2;2014;2025;"Ramon Santamaria";@raysan5 shapes;shapes_bouncing_ball;★☆☆☆;2.5;2.5;2013;2025;"Ramon Santamaria";@raysan5 shapes;shapes_bullet_hell;★☆☆☆;5.6;5.6;2025;2025;"Zero";@zerohorsepower @@ -75,7 +76,12 @@ shapes;shapes_double_pendulum;★★☆☆;5.5;5.5;2025;2025;"JoeCheong";@Joeche shapes;shapes_dashed_line;★☆☆☆;5.5;5.5;2025;2025;"Luís Almeida";@luis605 shapes;shapes_triangle_strip;★★☆☆;5.6-dev;5.6-dev;2025;2025;"Jopestpe";@jopestpe shapes;shapes_vector_angle;★★☆☆;1.0;5.0;2023;2025;"Ramon Santamaria";@raysan5 -shapes;shapes_pie_chart;★☆☆☆;5.5;5.6;2025;2025;"Gideon Serfontein";@GideonSerf +shapes;shapes_pie_chart;★★★☆;5.5;5.6;2025;2025;"Gideon Serfontein";@GideonSerf +shapes;shapes_kaleidoscope;★★☆☆;5.5;5.6;2025;2025;"Hugo ARNAL";@hugoarnal +shapes;shapes_clock_of_clocks;★★☆☆;5.5;5.6-dev;2025;2025;"JP Mortiboys";@themushroompirates +shapes;shapes_mouse_trail;★☆☆☆;5.6;5.6-dev;2024;2024;"[Balamurugan R]";@[Bala050814] +shapes;shapes_simple_particles;★★☆☆;5.6;5.6;2025;2025;"Jordi Santonja";@JordSant +shapes;shapes_starfield_effect;★★☆☆;5.5;5.6-dev;2025;2025;"JP Mortiboys";@themushroompirates textures;textures_logo_raylib;★☆☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5 textures;textures_srcrec_dstrec;★★★☆;1.3;1.3;2015;2025;"Ramon Santamaria";@raysan5 textures;textures_image_drawing;★★☆☆;1.4;1.4;2016;2025;"Ramon Santamaria";@raysan5 @@ -186,9 +192,3 @@ others;easings_testbed;★★★☆;2.5;3.0;2019;2025;"Juan Miguel López";@flas others;raylib_opengl_interop;★★★★;3.8;4.0;2021;2025;"Stephan Soller";@arkanis others;embedded_files_loading;★★☆☆;3.0;3.5;2020;2025;"Kristian Holmgren";@defutura others;web_basic_window;★☆☆☆;5.6-dev;5.6-dev;2014;2025;"Ramon Santamaria";@raysan5 -shapes;shapes_kaleidoscope;★★☆☆;5.5;5.6;2025;2025;"Hugo ARNAL";@hugoarnal -core;core_clipboard_text;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Robin";@RobinsAviary -shapes;shapes_clock_of_clocks;★★☆☆;5.5;5.6-dev;2025;2025;"JP Mortiboys";@themushroompirates -shapes;shapes_mouse_trail;★☆☆☆;5.6;5.6-dev;2024;2024;"[Balamurugan R]";@[Bala050814] -shapes;shapes_simple_particles;★☆☆☆;5.6;5.6;2025;2025;"Jordi Santonja";@JordSant -shapes;shapes_starfield;★☆☆☆;5.5;5.6-dev;2025;2025;"JP Mortiboys";@themushroompirates diff --git a/examples/shapes/shapes_pie_chart.c b/examples/shapes/shapes_pie_chart.c index e2f6900eb..566e3a4d1 100644 --- a/examples/shapes/shapes_pie_chart.c +++ b/examples/shapes/shapes_pie_chart.c @@ -2,7 +2,7 @@ * * raylib [shapes] example - pie chart * -* Example complexity rating: [★☆☆☆] 1/4 +* Example complexity rating: [★★★☆] 3/4 * * Example originally created with raylib 5.5, last time updated with raylib 5.6 * diff --git a/examples/shapes/shapes_simple_particles.c b/examples/shapes/shapes_simple_particles.c index 5bef0917a..7c2a598c2 100644 --- a/examples/shapes/shapes_simple_particles.c +++ b/examples/shapes/shapes_simple_particles.c @@ -2,7 +2,7 @@ * * raylib [shapes] example - simple particles * -* Example complexity rating: [★☆☆☆] 1/4 +* Example complexity rating: [★★☆☆] 2/4 * * Example originally created with raylib 5.6, last time updated with raylib 5.6 * @@ -20,7 +20,7 @@ #include // Required for: calloc(), free() #include // Required for: cosf(), sinf() -#define MAX_PARTICLES 3000 // Max number particles +#define MAX_PARTICLES 3000 // Max number of particles //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -100,6 +100,7 @@ int main(void) // Update the parameters of each particle UpdateParticles(&circularBuffer, screenWidth, screenHeight); + // Remove dead particles from the circular buffer UpdateCircularBuffer(&circularBuffer); @@ -217,46 +218,53 @@ static void UpdateParticles(CircularBuffer *circularBuffer, int screenWidth, int switch (circularBuffer->buffer[i].type) { case WATER: + { circularBuffer->buffer[i].position.x += circularBuffer->buffer[i].velocity.x; circularBuffer->buffer[i].velocity.y += 0.2f; // Gravity circularBuffer->buffer[i].position.y += circularBuffer->buffer[i].velocity.y; - break; + } break; case SMOKE: + { circularBuffer->buffer[i].position.x += circularBuffer->buffer[i].velocity.x; circularBuffer->buffer[i].velocity.y -= 0.05f; // Upwards circularBuffer->buffer[i].position.y += circularBuffer->buffer[i].velocity.y; circularBuffer->buffer[i].radius += 0.5f; // Increment radius: smoke expands circularBuffer->buffer[i].color.a -= 4; // Decrement alpha: smoke fades - if (circularBuffer->buffer[i].color.a < 4) // If alpha transparent, particle dies - circularBuffer->buffer[i].alive = false; - break; + + // If alpha transparent, particle dies + if (circularBuffer->buffer[i].color.a < 4) circularBuffer->buffer[i].alive = false; + } break; case FIRE: + { // Add a little horizontal oscillation to fire particles circularBuffer->buffer[i].position.x += circularBuffer->buffer[i].velocity.x + cosf(circularBuffer->buffer[i].lifeTime*215.0f); circularBuffer->buffer[i].velocity.y -= 0.05f; // Upwards circularBuffer->buffer[i].position.y += circularBuffer->buffer[i].velocity.y; circularBuffer->buffer[i].radius -= 0.15f; // Decrement radius: fire shrinks circularBuffer->buffer[i].color.g -= 3; // Decrement green: fire turns reddish starting from yellow - if (circularBuffer->buffer[i].radius <= 0.02f) // If radius too small, particle dies - circularBuffer->buffer[i].alive = false; - break; + + // If radius too small, particle dies + if (circularBuffer->buffer[i].radius <= 0.02f) circularBuffer->buffer[i].alive = false; + } break; default: break; } // Disable particle when out of screen Vector2 center = circularBuffer->buffer[i].position; float radius = circularBuffer->buffer[i].radius; - if ((center.x < -radius) || (center.x > screenWidth + radius) || - (center.y < -radius) || (center.y > screenHeight + radius)) + + if ((center.x < -radius) || (center.x > (screenWidth + radius)) || + (center.y < -radius) || (center.y > (screenHeight + radius))) + { circularBuffer->buffer[i].alive = false; + } } } static void UpdateCircularBuffer(CircularBuffer *circularBuffer) { // Update circular buffer: advance tail over dead particles - while ((circularBuffer->tail != circularBuffer->head) && - !circularBuffer->buffer[circularBuffer->tail].alive) + while ((circularBuffer->tail != circularBuffer->head) && !circularBuffer->buffer[circularBuffer->tail].alive) { circularBuffer->tail = (circularBuffer->tail + 1)%MAX_PARTICLES; } diff --git a/examples/shapes/shapes_starfield.c b/examples/shapes/shapes_starfield_effect.c similarity index 66% rename from examples/shapes/shapes_starfield.c rename to examples/shapes/shapes_starfield_effect.c index df543d066..8dd90fe0b 100644 --- a/examples/shapes/shapes_starfield.c +++ b/examples/shapes/shapes_starfield_effect.c @@ -1,8 +1,8 @@ /******************************************************************************************* * -* raylib [shapes] example - starfield +* raylib [shapes] example - starfield effect * -* Example complexity rating: [★☆☆☆] 1/4 +* Example complexity rating: [★★☆☆] 2/4 * * Example originally created with raylib 5.5, last time updated with raylib 5.6-dev * @@ -31,7 +31,7 @@ int main(void) const int screenWidth = 800; const int screenHeight = 450; - InitWindow(screenWidth, screenHeight, "raylib [shapes] example - starfield"); + InitWindow(screenWidth, screenHeight, "raylib [shapes] example - starfield effect"); Color bgColor = ColorLerp(DARKBLUE, BLACK, 0.69f); @@ -45,9 +45,10 @@ int main(void) Vector2 starsScreenPos[STAR_COUNT] = { 0 }; // Setup the stars with a random position - for (int i = 0; i < STAR_COUNT; i++) { - stars[i].x = GetRandomValue(-screenWidth*.5, screenWidth*.5); - stars[i].y = GetRandomValue(-screenHeight*.5, screenHeight*.5); + for (int i = 0; i < STAR_COUNT; i++) + { + stars[i].x = GetRandomValue(-screenWidth*0.5f, screenWidth*0.5f); + stars[i].y = GetRandomValue(-screenHeight*0.5f, screenHeight*0.5f); stars[i].z = 1.0f; } @@ -59,39 +60,36 @@ int main(void) { // Update //---------------------------------------------------------------------------------- - - // Change speed based on number keys - for (int i = 0; i <= 9; i++) { - if (IsKeyPressed(KEY_ZERO + i)) { - speed = 2.0f * (float)i / 9.0f; - } - } + // Change speed based on mouse + float mouseMove = GetMouseWheelMove(); + if ((int)mouseMove != 0) speed += 2.0f*mouseMove/9.0f; + if (speed < 0.0f) speed = 0.1f; + else if (speed > 2.0f) speed = 2.0f; // Toggle lines / points with space bar - if (IsKeyPressed(KEY_SPACE)) { - drawLines = !drawLines; - } + if (IsKeyPressed(KEY_SPACE)) drawLines = !drawLines; float dt = GetFrameTime(); - for (int i = 0; i < STAR_COUNT; i++) { + for (int i = 0; i < STAR_COUNT; i++) + { // Update star's timer - stars[i].z -= dt * speed; + stars[i].z -= dt*speed; + // Calculate the screen position - starsScreenPos[i] = (Vector2) { - screenWidth*.5f + stars[i].x / stars[i].z, - screenHeight*.5f + stars[i].y / stars[i].z, + starsScreenPos[i] = (Vector2){ + screenWidth*0.5f + stars[i].x/stars[i].z, + screenHeight*0.5f + stars[i].y/stars[i].z, }; + // If the star is too old, or offscreen, it dies and we make a new random one - if (stars[i].z < 0.0f - || starsScreenPos[i].x < 0 || starsScreenPos[i].y < 0.0f - || starsScreenPos[i].x > screenWidth || starsScreenPos[i].y > screenHeight) { - stars[i].x = GetRandomValue(-screenWidth*.5, screenWidth*.5); - stars[i].y = GetRandomValue(-screenHeight*.5, screenHeight*.5); + if ((stars[i].z < 0.0f) || (starsScreenPos[i].x < 0) || (starsScreenPos[i].y < 0.0f) || + (starsScreenPos[i].x > screenWidth) || (starsScreenPos[i].y > screenHeight)) + { + stars[i].x = GetRandomValue(-screenWidth*0.5f, screenWidth*0.5f); + stars[i].y = GetRandomValue(-screenHeight*0.5f, screenHeight*0.5f); stars[i].z = 1.0f; } } - - //---------------------------------------------------------------------------------- // Draw @@ -100,42 +98,47 @@ int main(void) ClearBackground(bgColor); - for (int i = 0; i < STAR_COUNT; i++) { - if (drawLines) { + for (int i = 0; i < STAR_COUNT; i++) + { + if (drawLines) + { // Get the time a little while ago for this star, but clamp it float t = Clamp(stars[i].z + 1.0f/32.0f, 0.0f, 1.0f); + // If it's different enough from the current time, we proceed - if (t - stars[i].z > 1e-3) { + if ((t - stars[i].z) > 1e-3) + { // Calculate the screen position of the old point - Vector2 startPos = (Vector2) { - screenWidth*.5f + stars[i].x / t, - screenHeight*.5f + stars[i].y / t, + Vector2 startPos = (Vector2){ + screenWidth*0.5f + stars[i].x/t, + screenHeight*0.5f + stars[i].y/t, }; + // Draw a line connecting the old point to the current point DrawLineV(startPos, starsScreenPos[i], RAYWHITE); } } - else { + else + { // Make the radius grow as the star ages float radius = Lerp(stars[i].z, 1.0f, 5.0f); + // Draw the circle DrawCircleV(starsScreenPos[i], radius, RAYWHITE); } } - DrawFPS(10, 10); + DrawText(TextFormat("[MOUSE WHEEL] Current Speed: %.0f", 9.0f*speed/2.0f), 10, 40, 20, RAYWHITE); + DrawText(TextFormat("[SPACE] Current draw mode: %s", drawLines ? "Lines" : "Circles"), 10, 70, 20, RAYWHITE); - DrawText(TextFormat("Current Speed: %.0f [Number keys to change]", 9.0f * speed / 2.0f), 10, 30, 20, RAYWHITE); - DrawText(TextFormat("Drawing %s [Space to change]", drawLines ? "Lines" : "Circles"), 10, 50, 20, RAYWHITE); + DrawFPS(10, 10); - EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- - CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/shapes/shapes_starfield.png b/examples/shapes/shapes_starfield_effect.png similarity index 100% rename from examples/shapes/shapes_starfield.png rename to examples/shapes/shapes_starfield_effect.png diff --git a/projects/VS2022/examples/core_monitor_change.vcxproj b/projects/VS2022/examples/core_monitor_detector.vcxproj similarity index 99% rename from projects/VS2022/examples/core_monitor_change.vcxproj rename to projects/VS2022/examples/core_monitor_detector.vcxproj index 07921bef3..bafb1b15c 100644 --- a/projects/VS2022/examples/core_monitor_change.vcxproj +++ b/projects/VS2022/examples/core_monitor_detector.vcxproj @@ -53,9 +53,9 @@ {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3} Win32Proj - core_monitor_change + core_monitor_detector 10.0 - core_monitor_change + core_monitor_detector @@ -553,7 +553,7 @@ - + diff --git a/projects/VS2022/examples/shapes_starfield.vcxproj b/projects/VS2022/examples/shapes_starfield_effect.vcxproj similarity index 99% rename from projects/VS2022/examples/shapes_starfield.vcxproj rename to projects/VS2022/examples/shapes_starfield_effect.vcxproj index 5cfc0a6d3..794ec633e 100644 --- a/projects/VS2022/examples/shapes_starfield.vcxproj +++ b/projects/VS2022/examples/shapes_starfield_effect.vcxproj @@ -53,9 +53,9 @@ {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91} Win32Proj - shapes_starfield + shapes_starfield_effect 10.0 - shapes_starfield + shapes_starfield_effect @@ -553,7 +553,7 @@ - + diff --git a/projects/VS2022/raylib.sln b/projects/VS2022/raylib.sln index be06d43a2..c4de89730 100644 --- a/projects/VS2022/raylib.sln +++ b/projects/VS2022/raylib.sln @@ -361,7 +361,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models_rotating_cube", "exa EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shaders_ascii_rendering", "examples\shaders_ascii_rendering.vcxproj", "{5F4B766F-DD52-4B53-B6C3-BC7611E17F20}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_monitor_change", "examples\core_monitor_change.vcxproj", "{FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_monitor_detector", "examples\core_monitor_detector.vcxproj", "{FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "web_basic_window", "examples\web_basic_window.vcxproj", "{A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}" EndProject @@ -385,7 +385,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_clock_of_clocks", "e EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_mouse_trail", "examples\shapes_mouse_trail.vcxproj", "{0835E6BF-0170-4E99-A55C-E06E1EF4C3B2}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_starfield", "examples\shapes_starfield.vcxproj", "{EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_starfield_effect", "examples\shapes_starfield_effect.vcxproj", "{EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_highdpi_testbed", "examples\core_highdpi_testbed.vcxproj", "{1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F}" EndProject diff --git a/tools/rexm/examples_report.md b/tools/rexm/examples_report.md index e55610a30..e058e09a7 100644 --- a/tools/rexm/examples_report.md +++ b/tools/rexm/examples_report.md @@ -44,7 +44,7 @@ Example elements validated: | core_window_flags | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | core_window_letterbox | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | core_window_should_close | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -| core_monitor_change | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| core_monitor_detector | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | core_custom_logging | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | core_drop_files | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | core_random_values | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | @@ -61,6 +61,9 @@ Example elements validated: | core_undo_redo | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | core_input_actions | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | core_directory_files | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| core_highdpi_testbed | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| core_screen_recording | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| core_clipboard_text | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_basic_shapes | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_bouncing_ball | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_bullet_hell | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | @@ -87,6 +90,11 @@ Example elements validated: | shapes_triangle_strip | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_vector_angle | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_pie_chart | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| shapes_kaleidoscope | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| shapes_clock_of_clocks | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| shapes_mouse_trail | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| shapes_simple_particles | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| shapes_starfield_effect | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | textures_logo_raylib | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | textures_srcrec_dstrec | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | textures_image_drawing | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | @@ -152,7 +160,7 @@ Example elements validated: | models_bone_socket | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | models_tesseract_view | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | models_basic_voxel | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -| models_geometry_textures_cube | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| models_rotating_cube | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shaders_ascii_rendering | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shaders_basic_lighting | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shaders_model_shader | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | @@ -197,9 +205,3 @@ Example elements validated: | raylib_opengl_interop | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | | embedded_files_loading | ✔ | ❌ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | web_basic_window | ✔ | ❌ | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -| shapes_kaleidoscope | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -| core_clipboard_text | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -| shapes_clock_of_clocks | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -| shapes_mouse_trail | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -| shapes_simple_particles | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -| shapes_starfield | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | diff --git a/tools/rexm/examples_report_issues.md b/tools/rexm/examples_report_issues.md index 5178dabdd..3136c2709 100644 --- a/tools/rexm/examples_report_issues.md +++ b/tools/rexm/examples_report_issues.md @@ -20,6 +20,8 @@ Example elements validated: ``` | **EXAMPLE NAME** | [C] | [CAT]| [INFO]|[PNG]|[WPNG]| [RES]| [MK] |[MKWEB]| [VCX]| [SOL]|[RDME]|[JS] | [WOUT]|[WMETA]| |:---------------------------------|:---:|:----:|:-----:|:---:|:----:|:----:|:----:|:-----:|:----:|:----:|:----:|:---:|:-----:|:-----:| +| core_highdpi_testbed | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| core_screen_recording | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | rlgl_standalone | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | rlgl_compute_shader | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | easings_testbed | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |