ruby2d 0.12.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE.md +7 -0
- data/README.md +141 -0
- data/USAGE.md +2435 -0
- data/assets/Rakefile +637 -0
- data/assets/build_support/CMakeLists.txt +94 -0
- data/assets/build_support/mruby/build_config.rb +34 -0
- data/assets/build_support/mruby/build_config_wasm.rb +30 -0
- data/assets/build_support/sdl_test.c +174 -0
- data/assets/deps.yaml +16 -0
- data/assets/platform/include/SDL3/SDL.h +91 -0
- data/assets/platform/include/SDL3/SDL_assert.h +705 -0
- data/assets/platform/include/SDL3/SDL_asyncio.h +550 -0
- data/assets/platform/include/SDL3/SDL_atomic.h +692 -0
- data/assets/platform/include/SDL3/SDL_audio.h +2370 -0
- data/assets/platform/include/SDL3/SDL_begin_code.h +553 -0
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_bits.h +47 -27
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_blendmode.h +59 -55
- data/assets/platform/include/SDL3/SDL_camera.h +535 -0
- data/assets/platform/include/SDL3/SDL_clipboard.h +331 -0
- data/assets/{include/SDL2/close_code.h → platform/include/SDL3/SDL_close_code.h} +9 -8
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_copying.h +3 -1
- data/assets/platform/include/SDL3/SDL_cpuinfo.h +374 -0
- data/assets/platform/include/SDL3/SDL_dialog.h +343 -0
- data/assets/platform/include/SDL3/SDL_dlopennote.h +234 -0
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_egl.h +11 -8
- data/assets/platform/include/SDL3/SDL_endian.h +645 -0
- data/assets/platform/include/SDL3/SDL_error.h +226 -0
- data/assets/platform/include/SDL3/SDL_events.h +1645 -0
- data/assets/platform/include/SDL3/SDL_filesystem.h +537 -0
- data/assets/platform/include/SDL3/SDL_gamepad.h +1656 -0
- data/assets/platform/include/SDL3/SDL_gpu.h +4608 -0
- data/assets/platform/include/SDL3/SDL_guid.h +106 -0
- data/assets/platform/include/SDL3/SDL_haptic.h +1461 -0
- data/assets/platform/include/SDL3/SDL_hidapi.h +571 -0
- data/assets/platform/include/SDL3/SDL_hints.h +5001 -0
- data/assets/platform/include/SDL3/SDL_init.h +507 -0
- data/assets/platform/include/SDL3/SDL_intrin.h +410 -0
- data/assets/platform/include/SDL3/SDL_iostream.h +1379 -0
- data/assets/platform/include/SDL3/SDL_joystick.h +1385 -0
- data/assets/platform/include/SDL3/SDL_keyboard.h +608 -0
- data/assets/platform/include/SDL3/SDL_keycode.h +347 -0
- data/assets/platform/include/SDL3/SDL_loadso.h +145 -0
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_locale.h +40 -24
- data/assets/platform/include/SDL3/SDL_log.h +541 -0
- data/assets/platform/include/SDL3/SDL_main.h +704 -0
- data/assets/platform/include/SDL3/SDL_main_impl.h +151 -0
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_messagebox.h +85 -48
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_metal.h +29 -29
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_misc.h +13 -12
- data/assets/platform/include/SDL3/SDL_mouse.h +813 -0
- data/assets/platform/include/SDL3/SDL_mutex.h +1117 -0
- data/assets/platform/include/SDL3/SDL_oldnames.h +1339 -0
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengl.h +1247 -278
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengl_glext.h +5 -1
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles.h +6 -7
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2.h +10 -11
- data/assets/platform/include/SDL3/SDL_pen.h +198 -0
- data/assets/platform/include/SDL3/SDL_pixels.h +1441 -0
- data/assets/{include/SDL2/SDL_test_log.h → platform/include/SDL3/SDL_platform.h} +25 -26
- data/assets/platform/include/SDL3/SDL_platform_defines.h +497 -0
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_power.h +40 -20
- data/assets/platform/include/SDL3/SDL_process.h +441 -0
- data/assets/platform/include/SDL3/SDL_properties.h +572 -0
- data/assets/platform/include/SDL3/SDL_rect.h +528 -0
- data/assets/platform/include/SDL3/SDL_render.h +3028 -0
- data/assets/platform/include/SDL3/SDL_revision.h +59 -0
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_scancode.h +59 -68
- data/assets/platform/include/SDL3/SDL_sensor.h +321 -0
- data/assets/platform/include/SDL3/SDL_stdinc.h +6186 -0
- data/assets/platform/include/SDL3/SDL_storage.h +686 -0
- data/assets/platform/include/SDL3/SDL_surface.h +1769 -0
- data/assets/platform/include/SDL3/SDL_system.h +840 -0
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test.h +16 -22
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_assert.h +27 -34
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_common.h +109 -52
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_compare.h +22 -14
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_crc32.h +27 -30
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_font.h +50 -49
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_fuzzer.h +64 -79
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_harness.h +47 -30
- data/assets/platform/include/SDL3/SDL_test_log.h +83 -0
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_md5.h +21 -28
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_memory.h +19 -16
- data/assets/platform/include/SDL3/SDL_thread.h +602 -0
- data/assets/platform/include/SDL3/SDL_time.h +249 -0
- data/assets/platform/include/SDL3/SDL_timer.h +454 -0
- data/assets/platform/include/SDL3/SDL_touch.h +184 -0
- data/assets/platform/include/SDL3/SDL_tray.h +544 -0
- data/assets/platform/include/SDL3/SDL_version.h +198 -0
- data/assets/platform/include/SDL3/SDL_video.h +3497 -0
- data/assets/platform/include/SDL3/SDL_vulkan.h +287 -0
- data/assets/platform/include/SDL3_image/SDL_image.h +3328 -0
- data/assets/platform/include/SDL3_mixer/SDL_mixer.h +3369 -0
- data/assets/platform/include/SDL3_ttf/SDL_textengine.h +181 -0
- data/assets/platform/include/SDL3_ttf/SDL_ttf.h +2833 -0
- data/assets/{include → platform/include}/mrbconf.h +42 -31
- data/assets/{include → platform/include}/mruby/array.h +3 -4
- data/assets/{include → platform/include}/mruby/boxing_nan.h +10 -0
- data/assets/platform/include/mruby/boxing_no.h +59 -0
- data/assets/{include → platform/include}/mruby/boxing_word.h +72 -26
- data/assets/platform/include/mruby/class.h +157 -0
- data/assets/{include → platform/include}/mruby/common.h +30 -1
- data/assets/{include → platform/include}/mruby/compile.h +52 -74
- data/assets/{include → platform/include}/mruby/data.h +2 -2
- data/assets/{include → platform/include}/mruby/debug.h +12 -5
- data/assets/{include → platform/include}/mruby/dump.h +7 -9
- data/assets/{include → platform/include}/mruby/endian.h +1 -1
- data/assets/platform/include/mruby/error.h +173 -0
- data/assets/platform/include/mruby/gc.h +79 -0
- data/assets/{include → platform/include}/mruby/hash.h +1 -7
- data/assets/platform/include/mruby/internal.h +282 -0
- data/assets/platform/include/mruby/irep.h +143 -0
- data/assets/{include → platform/include}/mruby/istruct.h +1 -1
- data/assets/platform/include/mruby/khash.h +455 -0
- data/assets/platform/include/mruby/mempool.h +19 -0
- data/assets/{include → platform/include}/mruby/numeric.h +7 -10
- data/assets/platform/include/mruby/object.h +51 -0
- data/assets/{include → platform/include}/mruby/opcode.h +5 -5
- data/assets/{include → platform/include}/mruby/ops.h +19 -6
- data/assets/platform/include/mruby/presym/id.h +1447 -0
- data/assets/{include → platform/include}/mruby/presym/scanning.h +10 -7
- data/assets/platform/include/mruby/presym/table.h +2893 -0
- data/assets/platform/include/mruby/presym.h +65 -0
- data/assets/platform/include/mruby/proc.h +184 -0
- data/assets/{include → platform/include}/mruby/range.h +0 -2
- data/assets/{include → platform/include}/mruby/string.h +33 -53
- data/assets/platform/include/mruby/throw.h +81 -0
- data/assets/{include → platform/include}/mruby/value.h +64 -29
- data/assets/{include → platform/include}/mruby/variable.h +6 -23
- data/assets/{include → platform/include}/mruby/version.h +7 -7
- data/assets/{include → platform/include}/mruby.h +238 -116
- data/assets/platform/macos-arm64/bin/mrbc +0 -0
- data/assets/platform/macos-arm64/lib/libSDL3.a +0 -0
- data/assets/platform/macos-arm64/lib/libSDL3_image.a +0 -0
- data/assets/platform/macos-arm64/lib/libSDL3_mixer.a +0 -0
- data/assets/platform/macos-arm64/lib/libSDL3_ttf.a +0 -0
- data/assets/platform/macos-arm64/lib/libmruby.a +0 -0
- data/assets/platform/wasm/lib/libFLAC.a +0 -0
- data/assets/platform/wasm/lib/libSDL3.a +0 -0
- data/assets/platform/wasm/lib/libSDL3_image.a +0 -0
- data/assets/platform/wasm/lib/libSDL3_mixer.a +0 -0
- data/assets/platform/wasm/lib/libSDL3_ttf.a +0 -0
- data/assets/platform/wasm/lib/libfreetype.a +0 -0
- data/assets/platform/wasm/lib/libharfbuzz.a +0 -0
- data/assets/platform/wasm/lib/libmruby.a +0 -0
- data/assets/platform/wasm/lib/libogg.a +0 -0
- data/assets/platform/wasm/lib/libplutosvg.a +0 -0
- data/assets/platform/wasm/lib/libplutovg.a +0 -0
- data/assets/platform/wasm/lib/libpng.a +0 -0
- data/assets/platform/wasm/lib/libpng16.a +0 -0
- data/assets/platform/wasm/lib/libvorbis.a +0 -0
- data/assets/platform/wasm/lib/libvorbisfile.a +0 -0
- data/assets/platform/wasm/lib/libzlibstatic.a +0 -0
- data/assets/platform/windows-arm64-mingw-ucrt/bin/mrbc.exe +0 -0
- data/assets/platform/windows-arm64-mingw-ucrt/lib/libSDL3.a +0 -0
- data/assets/platform/windows-arm64-mingw-ucrt/lib/libSDL3_image.a +0 -0
- data/assets/platform/windows-arm64-mingw-ucrt/lib/libSDL3_mixer.a +0 -0
- data/assets/platform/windows-arm64-mingw-ucrt/lib/libSDL3_ttf.a +0 -0
- data/assets/platform/windows-arm64-mingw-ucrt/lib/libmruby.a +0 -0
- data/assets/platform/windows-x86_64-mingw-ucrt/bin/mrbc.exe +0 -0
- data/assets/platform/windows-x86_64-mingw-ucrt/lib/libSDL3.a +0 -0
- data/assets/platform/windows-x86_64-mingw-ucrt/lib/libSDL3_image.a +0 -0
- data/assets/platform/windows-x86_64-mingw-ucrt/lib/libSDL3_mixer.a +0 -0
- data/assets/platform/windows-x86_64-mingw-ucrt/lib/libSDL3_ttf.a +0 -0
- data/assets/platform/windows-x86_64-mingw-ucrt/lib/libmruby.a +0 -0
- data/assets/resources/fonts/outfit/OFL.txt +93 -0
- data/assets/resources/fonts/outfit/outfit.ttf +0 -0
- data/assets/resources/fonts/roboto_mono/OFL.txt +91 -0
- data/assets/resources/fonts/roboto_mono/roboto_mono.ttf +0 -0
- data/assets/resources/icons/icon.icns +0 -0
- data/assets/resources/icons/icon.png +0 -0
- data/assets/resources/spritesheets/License.txt +28 -0
- data/assets/resources/spritesheets/spritesheet-backgrounds.png +0 -0
- data/assets/resources/spritesheets/spritesheet-backgrounds.xml +16 -0
- data/assets/resources/spritesheets/spritesheet-characters.png +0 -0
- data/assets/resources/spritesheets/spritesheet-characters.xml +47 -0
- data/assets/resources/spritesheets/spritesheet-enemies.png +0 -0
- data/assets/resources/spritesheets/spritesheet-enemies.xml +62 -0
- data/assets/resources/spritesheets/spritesheet-tiles.png +0 -0
- data/assets/resources/spritesheets/spritesheet-tiles.xml +316 -0
- data/assets/{wasm → resources/web}/template.html +1 -1
- data/assets/target.rb +131 -0
- data/bin/ruby2d +281 -82
- data/examples/astar.rb +269 -0
- data/examples/asteroids.rb +403 -0
- data/examples/bezier_editor.rb +96 -0
- data/examples/boids.rb +191 -0
- data/examples/bouncing_balls.rb +119 -0
- data/examples/breakout.rb +186 -0
- data/examples/constellations.rb +100 -0
- data/examples/dashboard.rb +133 -0
- data/examples/double_pendulum.rb +254 -0
- data/examples/falling_sand.rb +291 -0
- data/examples/fireworks.rb +110 -0
- data/examples/fluid_dynamics.rb +340 -0
- data/examples/fourier_epicycles.rb +142 -0
- data/examples/fractal_tree.rb +326 -0
- data/examples/game_of_life.rb +148 -0
- data/examples/gamepads.rb +333 -0
- data/examples/hill_driver.rb +613 -0
- data/examples/logo_animation.rb +251 -0
- data/examples/lorenz_attractor.rb +115 -0
- data/examples/mandelbrot.rb +207 -0
- data/examples/marching_squares.rb +200 -0
- data/examples/maze.rb +323 -0
- data/examples/nbody.rb +338 -0
- data/examples/outrun.rb +391 -0
- data/examples/pixel_paint.rb +313 -0
- data/examples/platformer.rb +335 -0
- data/examples/ray_casting_maze.rb +175 -0
- data/examples/shadow_casting.rb +151 -0
- data/examples/shape_recognizer.rb +908 -0
- data/examples/snake.rb +144 -0
- data/examples/sprite_sheets.rb +246 -0
- data/examples/swarm.rb +206 -0
- data/examples/tsp_annealing.rb +104 -0
- data/examples/ui_controls.rb +163 -0
- data/examples/wireframe_3d.rb +139 -0
- data/ext/ruby2d/audio.c +324 -0
- data/ext/ruby2d/canvas.c +1715 -494
- data/ext/ruby2d/ext.c +541 -0
- data/ext/ruby2d/extconf.rb +122 -145
- data/ext/ruby2d/font.c +566 -20
- data/ext/ruby2d/fps.c +92 -0
- data/ext/ruby2d/image.c +466 -41
- data/ext/ruby2d/ruby2d.c +374 -1890
- data/ext/ruby2d/ruby2d.h +840 -460
- data/ext/ruby2d/shapes.c +931 -101
- data/ext/ruby2d/text.c +586 -21
- data/ext/ruby2d/window.c +1693 -283
- data/lib/ruby2d/atlas_parser.rb +194 -0
- data/lib/ruby2d/audio.rb +73 -0
- data/lib/ruby2d/benchmark.rb +259 -0
- data/lib/ruby2d/bitmap_text.rb +155 -0
- data/lib/ruby2d/button.rb +402 -0
- data/lib/ruby2d/canvas.rb +703 -279
- data/lib/ruby2d/circle.rb +206 -29
- data/lib/ruby2d/cli/browser.rb +314 -0
- data/lib/ruby2d/cli/build.rb +471 -257
- data/lib/ruby2d/cli/colorize.rb +7 -5
- data/lib/ruby2d/cli/examples.rb +127 -0
- data/lib/ruby2d/cli/launch.rb +24 -39
- data/lib/ruby2d/cli/lib_files.rb +48 -0
- data/lib/ruby2d/cli/messages.rb +40 -0
- data/lib/ruby2d/cli/setup.rb +273 -0
- data/lib/ruby2d/cli/static_server.rb +160 -0
- data/lib/ruby2d/cli/usage.rb +255 -0
- data/lib/ruby2d/color.rb +191 -69
- data/lib/ruby2d/core.rb +37 -19
- data/lib/ruby2d/deps_help.rb +89 -0
- data/lib/ruby2d/dsl.rb +51 -12
- data/lib/ruby2d/ellipse.rb +228 -0
- data/lib/ruby2d/exceptions.rb +0 -2
- data/lib/ruby2d/font.rb +34 -74
- data/lib/ruby2d/gamepad.rb +323 -0
- data/lib/ruby2d/gem_paths.rb +19 -0
- data/lib/ruby2d/image.rb +155 -52
- data/lib/ruby2d/interactive.rb +103 -0
- data/lib/ruby2d/json_parser.rb +268 -0
- data/lib/ruby2d/line.rb +194 -85
- data/lib/ruby2d/mruby_compat.rb +12 -0
- data/lib/ruby2d/polygon.rb +297 -0
- data/lib/ruby2d/polyline.rb +368 -0
- data/lib/ruby2d/quad.rb +358 -94
- data/lib/ruby2d/rectangle.rb +77 -19
- data/lib/ruby2d/renderable.rb +411 -11
- data/lib/ruby2d/sprite.rb +471 -180
- data/lib/ruby2d/sprite_sheet.rb +64 -0
- data/lib/ruby2d/square.rb +29 -17
- data/lib/ruby2d/text.rb +196 -65
- data/lib/ruby2d/tileset.rb +139 -81
- data/lib/ruby2d/triangle.rb +324 -89
- data/lib/ruby2d/version.rb +1 -3
- data/lib/ruby2d/vertices.rb +62 -85
- data/lib/ruby2d/warnings.rb +29 -0
- data/lib/ruby2d/window/class_methods.rb +218 -0
- data/lib/ruby2d/window/gamepad_events.rb +141 -0
- data/lib/ruby2d/window/key_events.rb +74 -0
- data/lib/ruby2d/window/mouse_events.rb +171 -0
- data/lib/ruby2d/window/object_events.rb +168 -0
- data/lib/ruby2d/window.rb +632 -585
- data/lib/ruby2d.rb +14 -19
- metadata +275 -443
- data/assets/app.icns +0 -0
- data/assets/include/GL/glew.h +0 -26427
- data/assets/include/GLES2/gl2.h +0 -656
- data/assets/include/GLES2/gl2ext.h +0 -3949
- data/assets/include/GLES2/gl2ext_angle.h +0 -701
- data/assets/include/GLES2/gl2platform.h +0 -27
- data/assets/include/GLES3/gl3.h +0 -1192
- data/assets/include/GLES3/gl31.h +0 -1507
- data/assets/include/GLES3/gl32.h +0 -1808
- data/assets/include/GLES3/gl3platform.h +0 -27
- data/assets/include/KHR/khrplatform.h +0 -290
- data/assets/include/SDL2/SDL.h +0 -233
- data/assets/include/SDL2/SDL_assert.h +0 -326
- data/assets/include/SDL2/SDL_atomic.h +0 -415
- data/assets/include/SDL2/SDL_audio.h +0 -1500
- data/assets/include/SDL2/SDL_clipboard.h +0 -141
- data/assets/include/SDL2/SDL_config.h +0 -61
- data/assets/include/SDL2/SDL_config_android.h +0 -194
- data/assets/include/SDL2/SDL_config_emscripten.h +0 -218
- data/assets/include/SDL2/SDL_config_iphoneos.h +0 -217
- data/assets/include/SDL2/SDL_config_macosx.h +0 -277
- data/assets/include/SDL2/SDL_config_minimal.h +0 -95
- data/assets/include/SDL2/SDL_config_ngage.h +0 -89
- data/assets/include/SDL2/SDL_config_os2.h +0 -207
- data/assets/include/SDL2/SDL_config_pandora.h +0 -141
- data/assets/include/SDL2/SDL_config_windows.h +0 -331
- data/assets/include/SDL2/SDL_config_wingdk.h +0 -253
- data/assets/include/SDL2/SDL_config_winrt.h +0 -220
- data/assets/include/SDL2/SDL_config_xbox.h +0 -235
- data/assets/include/SDL2/SDL_cpuinfo.h +0 -594
- data/assets/include/SDL2/SDL_endian.h +0 -348
- data/assets/include/SDL2/SDL_error.h +0 -163
- data/assets/include/SDL2/SDL_events.h +0 -1166
- data/assets/include/SDL2/SDL_filesystem.h +0 -149
- data/assets/include/SDL2/SDL_gamecontroller.h +0 -1074
- data/assets/include/SDL2/SDL_gesture.h +0 -117
- data/assets/include/SDL2/SDL_guid.h +0 -100
- data/assets/include/SDL2/SDL_haptic.h +0 -1341
- data/assets/include/SDL2/SDL_hidapi.h +0 -451
- data/assets/include/SDL2/SDL_hints.h +0 -2569
- data/assets/include/SDL2/SDL_image.h +0 -2173
- data/assets/include/SDL2/SDL_joystick.h +0 -1066
- data/assets/include/SDL2/SDL_keyboard.h +0 -353
- data/assets/include/SDL2/SDL_keycode.h +0 -358
- data/assets/include/SDL2/SDL_loadso.h +0 -115
- data/assets/include/SDL2/SDL_log.h +0 -404
- data/assets/include/SDL2/SDL_main.h +0 -275
- data/assets/include/SDL2/SDL_mixer.h +0 -2784
- data/assets/include/SDL2/SDL_mouse.h +0 -465
- data/assets/include/SDL2/SDL_mutex.h +0 -471
- data/assets/include/SDL2/SDL_name.h +0 -33
- data/assets/include/SDL2/SDL_pixels.h +0 -644
- data/assets/include/SDL2/SDL_platform.h +0 -261
- data/assets/include/SDL2/SDL_quit.h +0 -58
- data/assets/include/SDL2/SDL_rect.h +0 -376
- data/assets/include/SDL2/SDL_render.h +0 -1919
- data/assets/include/SDL2/SDL_revision.h +0 -6
- data/assets/include/SDL2/SDL_rwops.h +0 -841
- data/assets/include/SDL2/SDL_sensor.h +0 -322
- data/assets/include/SDL2/SDL_shape.h +0 -155
- data/assets/include/SDL2/SDL_stdinc.h +0 -830
- data/assets/include/SDL2/SDL_surface.h +0 -997
- data/assets/include/SDL2/SDL_system.h +0 -623
- data/assets/include/SDL2/SDL_syswm.h +0 -386
- data/assets/include/SDL2/SDL_test_images.h +0 -78
- data/assets/include/SDL2/SDL_test_random.h +0 -115
- data/assets/include/SDL2/SDL_thread.h +0 -464
- data/assets/include/SDL2/SDL_timer.h +0 -222
- data/assets/include/SDL2/SDL_touch.h +0 -150
- data/assets/include/SDL2/SDL_ttf.h +0 -2316
- data/assets/include/SDL2/SDL_types.h +0 -29
- data/assets/include/SDL2/SDL_version.h +0 -204
- data/assets/include/SDL2/SDL_video.h +0 -2150
- data/assets/include/SDL2/SDL_vulkan.h +0 -215
- data/assets/include/SDL2/begin_code.h +0 -187
- data/assets/include/mruby/boxing_no.h +0 -58
- data/assets/include/mruby/class.h +0 -108
- data/assets/include/mruby/error.h +0 -147
- data/assets/include/mruby/gc.h +0 -94
- data/assets/include/mruby/irep.h +0 -147
- data/assets/include/mruby/khash.h +0 -284
- data/assets/include/mruby/object.h +0 -43
- data/assets/include/mruby/presym/disable.h +0 -70
- data/assets/include/mruby/presym/enable.h +0 -37
- data/assets/include/mruby/presym.h +0 -40
- data/assets/include/mruby/proc.h +0 -211
- data/assets/include/mruby/throw.h +0 -66
- data/assets/macos/universal/bin/mrbc +0 -0
- data/assets/macos/universal/lib/libFLAC.a +0 -0
- data/assets/macos/universal/lib/libSDL2.a +0 -0
- data/assets/macos/universal/lib/libSDL2_image.a +0 -0
- data/assets/macos/universal/lib/libSDL2_mixer.a +0 -0
- data/assets/macos/universal/lib/libSDL2_ttf.a +0 -0
- data/assets/macos/universal/lib/libavif.a +0 -0
- data/assets/macos/universal/lib/libbrotlicommon-static.a +0 -0
- data/assets/macos/universal/lib/libbrotlidec-static.a +0 -0
- data/assets/macos/universal/lib/libfreetype.a +0 -0
- data/assets/macos/universal/lib/libgraphite2.a +0 -0
- data/assets/macos/universal/lib/libharfbuzz.a +0 -0
- data/assets/macos/universal/lib/libhwy.a +0 -0
- data/assets/macos/universal/lib/libjpeg.a +0 -0
- data/assets/macos/universal/lib/libjxl.a +0 -0
- data/assets/macos/universal/lib/libmodplug.a +0 -0
- data/assets/macos/universal/lib/libmpg123.a +0 -0
- data/assets/macos/universal/lib/libmruby.a +0 -0
- data/assets/macos/universal/lib/libogg.a +0 -0
- data/assets/macos/universal/lib/libpng.a +0 -0
- data/assets/macos/universal/lib/libtiff.a +0 -0
- data/assets/macos/universal/lib/libvorbis.a +0 -0
- data/assets/macos/universal/lib/libvorbisfile.a +0 -0
- data/assets/macos/universal/lib/libwebp.a +0 -0
- data/assets/macos/universal/lib/libzstd.a +0 -0
- data/assets/test_media/README.md +0 -3
- data/assets/test_media/bitstream_vera/COPYRIGHT.txt +0 -124
- data/assets/test_media/bitstream_vera/vera.ttf +0 -0
- data/assets/test_media/boom.png +0 -0
- data/assets/test_media/coin.png +0 -0
- data/assets/test_media/colors.png +0 -0
- data/assets/test_media/controller.png +0 -0
- data/assets/test_media/dial.wav +0 -0
- data/assets/test_media/hero.png +0 -0
- data/assets/test_media/image.bmp +0 -0
- data/assets/test_media/image.jpg +0 -0
- data/assets/test_media/image.png +0 -0
- data/assets/test_media/music.flac +0 -0
- data/assets/test_media/music.mp3 +0 -0
- data/assets/test_media/music.ogg +0 -0
- data/assets/test_media/music.wav +0 -0
- data/assets/test_media/originals/boom.pxm +0 -0
- data/assets/test_media/originals/coin.pxm +0 -0
- data/assets/test_media/originals/controller.sketch +0 -0
- data/assets/test_media/originals/hero.pxm +0 -0
- data/assets/test_media/originals/image.pxm +0 -0
- data/assets/test_media/originals/music.caf +0 -0
- data/assets/test_media/originals/texture_atlas.pxm +0 -0
- data/assets/test_media/rondo_alla_turka.ogg +0 -0
- data/assets/test_media/sound.flac +0 -0
- data/assets/test_media/sound.mp3 +0 -0
- data/assets/test_media/sound.ogg +0 -0
- data/assets/test_media/sound.wav +0 -0
- data/assets/test_media/sprite_sheet.png +0 -0
- data/assets/test_media/texture_atlas.png +0 -0
- data/assets/wasm/libmruby.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/bin/mrbc.exe +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libFLAC.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libLerc.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_image.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_mixer.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_ttf.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libbrotlicommon.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libbrotlidec.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libbz2.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libdeflate.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libfreetype.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libglew32.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libgraphite2.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libharfbuzz.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libhwy.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libjbig.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libjpeg.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libjxl.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/liblzma.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libmodplug.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libmpg123.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libmruby.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libogg.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libopus.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libopusfile.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libpng.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libsndfile.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libssp.a +0 -1
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libstdc++.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libtiff.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libvorbis.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libvorbisfile.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libwebp.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libz.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libzstd.a +0 -0
- data/assets/windows/mingw-w64-x86_64/bin/mrbc.exe +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libFLAC.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libLerc.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libSDL2.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libSDL2_image.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libSDL2_mixer.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libSDL2_ttf.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libbrotlicommon.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libbrotlidec.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libbz2.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libdeflate.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libfreetype.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libglew32.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libgraphite2.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libharfbuzz.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libhwy.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libjbig.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libjpeg.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libjxl.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/liblzma.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libmodplug.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libmpg123.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libmruby.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libogg.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libopus.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libopusfile.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libpng.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libsndfile.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libssp.a +0 -1
- data/assets/windows/mingw-w64-x86_64/lib/libstdc++.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libtiff.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libvorbis.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libvorbisfile.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libwebp.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libz.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libzstd.a +0 -0
- data/assets/xcode/ios/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -98
- data/assets/xcode/ios/Assets.xcassets/Contents.json +0 -6
- data/assets/xcode/ios/Base.lproj/LaunchScreen.storyboard +0 -27
- data/assets/xcode/ios/Info.plist +0 -43
- data/assets/xcode/ios/MRuby.framework/Headers/mrbconf.h +0 -143
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/array.h +0 -280
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/boxing_nan.h +0 -102
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/boxing_no.h +0 -56
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/boxing_word.h +0 -144
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/class.h +0 -97
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/common.h +0 -77
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/compile.h +0 -195
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/data.h +0 -75
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/debug.h +0 -67
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/dump.h +0 -196
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/error.h +0 -75
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/gc.h +0 -91
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/hash.h +0 -215
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/irep.h +0 -75
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/istruct.h +0 -47
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/khash.h +0 -274
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/numeric.h +0 -161
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/object.h +0 -44
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/opcode.h +0 -69
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/ops.h +0 -117
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/proc.h +0 -131
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/range.h +0 -49
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/re.h +0 -16
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/string.h +0 -444
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/throw.h +0 -55
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/value.h +0 -309
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/variable.h +0 -136
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/version.h +0 -110
- data/assets/xcode/ios/MRuby.framework/Headers/mruby.h +0 -1282
- data/assets/xcode/ios/MRuby.framework/Info.plist +0 -20
- data/assets/xcode/ios/MRuby.framework/MRuby +0 -0
- data/assets/xcode/ios/MyApp.xcodeproj/project.pbxproj +0 -368
- data/assets/xcode/ios/MyApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
- data/assets/xcode/ios/MyApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
- data/assets/xcode/ios/MyApp.xcodeproj/project.xcworkspace/xcshareddata/MyApp.xcscmblueprint +0 -30
- data/assets/xcode/ios/main.c +0 -1
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Content.imageset/Contents.json +0 -16
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Contents.json +0 -6
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Contents.json +0 -17
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Content.imageset/Contents.json +0 -16
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Contents.json +0 -6
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json +0 -16
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Contents.json +0 -6
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Content.imageset/Contents.json +0 -16
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Contents.json +0 -6
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Contents.json +0 -17
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/Contents.json +0 -16
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Contents.json +0 -6
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json +0 -16
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Contents.json +0 -6
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json +0 -32
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json +0 -16
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json +0 -16
- data/assets/xcode/tvos/Assets.xcassets/Contents.json +0 -6
- data/assets/xcode/tvos/Assets.xcassets/LaunchImage.launchimage/Contents.json +0 -22
- data/assets/xcode/tvos/Info.plist +0 -30
- data/assets/xcode/tvos/MRuby.framework/Headers/mrbconf.h +0 -143
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/array.h +0 -280
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/boxing_nan.h +0 -102
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/boxing_no.h +0 -56
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/boxing_word.h +0 -144
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/class.h +0 -97
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/common.h +0 -77
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/compile.h +0 -195
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/data.h +0 -75
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/debug.h +0 -67
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/dump.h +0 -196
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/error.h +0 -75
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/gc.h +0 -91
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/hash.h +0 -215
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/irep.h +0 -75
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/istruct.h +0 -47
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/khash.h +0 -274
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/numeric.h +0 -161
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/object.h +0 -44
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/opcode.h +0 -69
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/ops.h +0 -117
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/proc.h +0 -131
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/range.h +0 -49
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/re.h +0 -16
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/string.h +0 -444
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/throw.h +0 -55
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/value.h +0 -309
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/variable.h +0 -136
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/version.h +0 -110
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby.h +0 -1282
- data/assets/xcode/tvos/MRuby.framework/Info.plist +0 -20
- data/assets/xcode/tvos/MRuby.framework/MRuby +0 -0
- data/assets/xcode/tvos/MyApp.xcodeproj/project.pbxproj +0 -350
- data/assets/xcode/tvos/MyApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
- data/assets/xcode/tvos/MyApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
- data/assets/xcode/tvos/MyApp.xcodeproj/project.xcworkspace/xcshareddata/MyApp.xcscmblueprint +0 -30
- data/assets/xcode/tvos/main.c +0 -1
- data/ext/ruby2d/common.c +0 -185
- data/ext/ruby2d/controllers.c +0 -110
- data/ext/ruby2d/gl.c +0 -398
- data/ext/ruby2d/gl2.c +0 -86
- data/ext/ruby2d/gl3.c +0 -304
- data/ext/ruby2d/gles.c +0 -302
- data/ext/ruby2d/input.c +0 -48
- data/ext/ruby2d/music.c +0 -127
- data/ext/ruby2d/sound.c +0 -132
- data/lib/ruby2d/cli/console.rb +0 -65
- data/lib/ruby2d/cli/enable_console.rb +0 -7
- data/lib/ruby2d/cli/platform.rb +0 -17
- data/lib/ruby2d/music.rb +0 -77
- data/lib/ruby2d/pixel.rb +0 -18
- data/lib/ruby2d/pixmap.rb +0 -39
- data/lib/ruby2d/pixmap_atlas.rb +0 -56
- data/lib/ruby2d/sound.rb +0 -61
- data/lib/ruby2d/texture.rb +0 -38
- /data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2_gl2.h +0 -0
- /data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2_gl2ext.h +0 -0
- /data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2_gl2platform.h +0 -0
- /data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2_khrplatform.h +0 -0
- /data/assets/{include → platform/include}/mruby/re.h +0 -0
data/ext/ruby2d/shapes.c
CHANGED
|
@@ -1,154 +1,984 @@
|
|
|
1
1
|
// shapes.c
|
|
2
|
+
//
|
|
3
|
+
// Pure C primitives for shape rendering — no Ruby in this file. Ruby-callable
|
|
4
|
+
// wrappers live in ext.c and dispatch into these via Ruby2D::Ext class methods.
|
|
2
5
|
|
|
3
6
|
#include "ruby2d.h"
|
|
4
7
|
|
|
5
8
|
|
|
6
9
|
/*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* Compute outer and inner outline points for a polyline or polygon stroke.
|
|
11
|
+
* See ruby2d.h for parameter documentation.
|
|
12
|
+
*
|
|
13
|
+
* Interior vertices (and all vertices in closed mode) use miter joins;
|
|
14
|
+
* endpoints in open mode get butt caps using the perpendicular of the single
|
|
15
|
+
* adjacent edge. Sharp miters are clamped to `miter_limit * half_width` so
|
|
16
|
+
* very acute corners don't shoot off into space (SVG's miterlimit behavior,
|
|
17
|
+
* though implemented here as a clamp rather than a bevel fallback).
|
|
13
18
|
*/
|
|
14
|
-
|
|
19
|
+
void R2D_ComputeStrokeOutline(const float *verts, int n, int closed,
|
|
20
|
+
float stroke_width, float miter_limit,
|
|
21
|
+
float *outer, float *inner) {
|
|
22
|
+
|
|
23
|
+
if (n < 2) return;
|
|
24
|
+
|
|
25
|
+
float hw = stroke_width / 2.0f;
|
|
26
|
+
float max_ml = miter_limit * hw;
|
|
27
|
+
|
|
28
|
+
for (int i = 0; i < n; i++) {
|
|
29
|
+
int is_endpoint = !closed && (i == 0 || i == n - 1);
|
|
30
|
+
|
|
31
|
+
if (is_endpoint) {
|
|
32
|
+
// Butt cap: perpendicular of the single adjacent edge
|
|
33
|
+
int other = (i == 0) ? 1 : n - 2;
|
|
34
|
+
float dx = verts[i*2] - verts[other*2];
|
|
35
|
+
float dy = verts[i*2+1] - verts[other*2+1];
|
|
36
|
+
if (i == 0) { dx = -dx; dy = -dy; }
|
|
37
|
+
float len = sqrtf(dx * dx + dy * dy);
|
|
38
|
+
|
|
39
|
+
if (len < 0.0001f) {
|
|
40
|
+
outer[i*2] = verts[i*2]; outer[i*2+1] = verts[i*2+1];
|
|
41
|
+
inner[i*2] = verts[i*2]; inner[i*2+1] = verts[i*2+1];
|
|
42
|
+
} else {
|
|
43
|
+
float nx = -dy / len, ny = dx / len;
|
|
44
|
+
outer[i*2] = verts[i*2] + nx * hw;
|
|
45
|
+
outer[i*2+1] = verts[i*2+1] + ny * hw;
|
|
46
|
+
inner[i*2] = verts[i*2] - nx * hw;
|
|
47
|
+
inner[i*2+1] = verts[i*2+1] - ny * hw;
|
|
48
|
+
}
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Interior (or any vertex in closed mode): compute miter
|
|
53
|
+
int prev = (i - 1 + n) % n;
|
|
54
|
+
int next = (i + 1) % n;
|
|
55
|
+
|
|
56
|
+
float d1x = verts[i*2] - verts[prev*2];
|
|
57
|
+
float d1y = verts[i*2+1] - verts[prev*2+1];
|
|
58
|
+
float d2x = verts[next*2] - verts[i*2];
|
|
59
|
+
float d2y = verts[next*2+1] - verts[i*2+1];
|
|
60
|
+
|
|
61
|
+
float len1 = sqrtf(d1x * d1x + d1y * d1y);
|
|
62
|
+
float len2 = sqrtf(d2x * d2x + d2y * d2y);
|
|
63
|
+
|
|
64
|
+
if (len1 < 0.0001f || len2 < 0.0001f) {
|
|
65
|
+
outer[i*2] = verts[i*2]; outer[i*2+1] = verts[i*2+1];
|
|
66
|
+
inner[i*2] = verts[i*2]; inner[i*2+1] = verts[i*2+1];
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
d1x /= len1; d1y /= len1;
|
|
71
|
+
d2x /= len2; d2y /= len2;
|
|
72
|
+
|
|
73
|
+
float n1x = -d1y, n1y = d1x;
|
|
74
|
+
float n2x = -d2y, n2y = d2x;
|
|
75
|
+
|
|
76
|
+
float mx = n1x + n2x;
|
|
77
|
+
float my = n1y + n2y;
|
|
78
|
+
float mlen = sqrtf(mx * mx + my * my);
|
|
79
|
+
|
|
80
|
+
if (mlen < 0.0001f) {
|
|
81
|
+
// 180° turn — degenerate; use the perpendicular of edge 1
|
|
82
|
+
outer[i*2] = verts[i*2] + n1x * hw;
|
|
83
|
+
outer[i*2+1] = verts[i*2+1] + n1y * hw;
|
|
84
|
+
inner[i*2] = verts[i*2] - n1x * hw;
|
|
85
|
+
inner[i*2+1] = verts[i*2+1] - n1y * hw;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
mx /= mlen; my /= mlen;
|
|
90
|
+
|
|
91
|
+
float dot = mx * n1x + my * n1y;
|
|
92
|
+
if (fabsf(dot) < 0.0001f) dot = 0.0001f;
|
|
93
|
+
float ml = hw / dot;
|
|
94
|
+
|
|
95
|
+
// Clamp miter length for sharp corners
|
|
96
|
+
if (ml > max_ml) ml = max_ml;
|
|
97
|
+
else if (ml < -max_ml) ml = -max_ml;
|
|
98
|
+
|
|
99
|
+
outer[i*2] = verts[i*2] + mx * ml;
|
|
100
|
+
outer[i*2+1] = verts[i*2+1] + my * ml;
|
|
101
|
+
inner[i*2] = verts[i*2] - mx * ml;
|
|
102
|
+
inner[i*2+1] = verts[i*2+1] - my * ml;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
15
105
|
|
|
16
|
-
// Convert from degrees to radians
|
|
17
|
-
angle = angle * M_PI / 180.0;
|
|
18
106
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
107
|
+
/*
|
|
108
|
+
* Stroke a polyline or closed polygon outline via SDL_RenderGeometry.
|
|
109
|
+
* See ruby2d.h for parameter documentation.
|
|
110
|
+
*/
|
|
111
|
+
void R2D_StrokePath(const float *verts, int n, int closed,
|
|
112
|
+
float stroke_width, float miter_limit,
|
|
113
|
+
const float *colors) {
|
|
114
|
+
|
|
115
|
+
if (n < 2 || stroke_width <= 0.0f) return;
|
|
116
|
+
|
|
117
|
+
// 2n vertices (outer[0], inner[0], outer[1], inner[1], ...); 6 indices per
|
|
118
|
+
// edge, with n edges when closed and n-1 when open.
|
|
119
|
+
int num_vertices = n * 2;
|
|
120
|
+
int edges = closed ? n : n - 1;
|
|
121
|
+
int num_indices = edges * 6;
|
|
122
|
+
|
|
123
|
+
// Most stroked shapes are small (triangles, quads, short polylines), so serve
|
|
124
|
+
// the four scratch buffers from the stack and fall back to the heap only for
|
|
125
|
+
// large vertex counts. Avoids four malloc/free pairs per call on the
|
|
126
|
+
// per-frame stroke path.
|
|
127
|
+
float outer_stack[R2D_STROKE_STACK_N * 2];
|
|
128
|
+
float inner_stack[R2D_STROKE_STACK_N * 2];
|
|
129
|
+
SDL_Vertex vertices_stack[R2D_STROKE_STACK_N * 2];
|
|
130
|
+
int indices_stack[R2D_STROKE_STACK_N * 6];
|
|
131
|
+
|
|
132
|
+
float *outer, *inner;
|
|
133
|
+
SDL_Vertex *vertices;
|
|
134
|
+
int *indices;
|
|
135
|
+
bool heap = n > R2D_STROKE_STACK_N;
|
|
136
|
+
|
|
137
|
+
if (heap) {
|
|
138
|
+
outer = (float *)malloc(n * 2 * sizeof(float));
|
|
139
|
+
inner = (float *)malloc(n * 2 * sizeof(float));
|
|
140
|
+
vertices = (SDL_Vertex *)malloc(num_vertices * sizeof(SDL_Vertex));
|
|
141
|
+
indices = (int *)malloc(num_indices * sizeof(int));
|
|
142
|
+
if (!outer || !inner || !vertices || !indices) {
|
|
143
|
+
free(outer); free(inner); free(vertices); free(indices);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
} else {
|
|
147
|
+
outer = outer_stack;
|
|
148
|
+
inner = inner_stack;
|
|
149
|
+
vertices = vertices_stack;
|
|
150
|
+
indices = indices_stack;
|
|
151
|
+
}
|
|
22
152
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
153
|
+
R2D_ComputeStrokeOutline(verts, n, closed, stroke_width, miter_limit, outer, inner);
|
|
154
|
+
|
|
155
|
+
for (int i = 0; i < n; i++) {
|
|
156
|
+
float r = colors[i * 4];
|
|
157
|
+
float g = colors[i * 4 + 1];
|
|
158
|
+
float b = colors[i * 4 + 2];
|
|
159
|
+
float a = colors[i * 4 + 3];
|
|
160
|
+
|
|
161
|
+
vertices[i * 2].position.x = outer[i * 2];
|
|
162
|
+
vertices[i * 2].position.y = outer[i * 2 + 1];
|
|
163
|
+
vertices[i * 2].color.r = r;
|
|
164
|
+
vertices[i * 2].color.g = g;
|
|
165
|
+
vertices[i * 2].color.b = b;
|
|
166
|
+
vertices[i * 2].color.a = a;
|
|
167
|
+
vertices[i * 2].tex_coord.x = 0.0f;
|
|
168
|
+
vertices[i * 2].tex_coord.y = 0.0f;
|
|
169
|
+
|
|
170
|
+
vertices[i * 2 + 1].position.x = inner[i * 2];
|
|
171
|
+
vertices[i * 2 + 1].position.y = inner[i * 2 + 1];
|
|
172
|
+
vertices[i * 2 + 1].color.r = r;
|
|
173
|
+
vertices[i * 2 + 1].color.g = g;
|
|
174
|
+
vertices[i * 2 + 1].color.b = b;
|
|
175
|
+
vertices[i * 2 + 1].color.a = a;
|
|
176
|
+
vertices[i * 2 + 1].tex_coord.x = 0.0f;
|
|
177
|
+
vertices[i * 2 + 1].tex_coord.y = 0.0f;
|
|
178
|
+
}
|
|
26
179
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
180
|
+
for (int i = 0; i < edges; i++) {
|
|
181
|
+
int j = (i + 1) % n;
|
|
182
|
+
int oi = i * 2, ii = i * 2 + 1;
|
|
183
|
+
int oj = j * 2, ij = j * 2 + 1;
|
|
184
|
+
|
|
185
|
+
indices[i * 6] = oi;
|
|
186
|
+
indices[i * 6 + 1] = ii;
|
|
187
|
+
indices[i * 6 + 2] = ij;
|
|
188
|
+
indices[i * 6 + 3] = oi;
|
|
189
|
+
indices[i * 6 + 4] = ij;
|
|
190
|
+
indices[i * 6 + 5] = oj;
|
|
191
|
+
}
|
|
30
192
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
193
|
+
R2D_CheckSDL(SDL_RenderGeometry(R2D_GetRenderer(), NULL,
|
|
194
|
+
vertices, num_vertices, indices, num_indices),
|
|
195
|
+
"SDL_RenderGeometry");
|
|
34
196
|
|
|
35
|
-
|
|
197
|
+
if (heap) {
|
|
198
|
+
free(indices);
|
|
199
|
+
free(vertices);
|
|
200
|
+
free(outer);
|
|
201
|
+
free(inner);
|
|
202
|
+
}
|
|
36
203
|
}
|
|
37
204
|
|
|
38
205
|
|
|
39
206
|
/*
|
|
40
|
-
*
|
|
207
|
+
* Unit-circle lookup cache, keyed by sector count.
|
|
208
|
+
*
|
|
209
|
+
* The cos/sin of each sector angle depend only on the sector count — not on
|
|
210
|
+
* position, radius, or color — so they are identical every frame and across
|
|
211
|
+
* every circle/ellipse drawn with the same sector count. Build each table once
|
|
212
|
+
* on first use and reuse it, turning the per-vertex fill into a multiply-add
|
|
213
|
+
* with no trig. Rendering is single-threaded, so the file-static cache needs no
|
|
214
|
+
* locking; tables live for the process lifetime and slots for unused sector
|
|
215
|
+
* counts stay NULL.
|
|
41
216
|
*/
|
|
42
|
-
|
|
217
|
+
#define R2D_MAX_SECTORS 360
|
|
218
|
+
#define R2D_MIN_SECTORS 3
|
|
219
|
+
static float *unit_cos_table[R2D_MAX_SECTORS + 1];
|
|
220
|
+
static float *unit_sin_table[R2D_MAX_SECTORS + 1];
|
|
43
221
|
|
|
44
|
-
|
|
222
|
+
/*
|
|
223
|
+
* Fetch the cached unit-circle cos/sin tables for `sectors` (in [3, 360]),
|
|
224
|
+
* building them on first use. On success points *cos_out / *sin_out at tables
|
|
225
|
+
* of `sectors` floats — cosf/sinf of i*(2*PI/sectors) for i in [0, sectors) —
|
|
226
|
+
* and returns true; on a bad sector count or allocation failure returns false
|
|
227
|
+
* so the caller computes the trig inline. The build expression matches the draw
|
|
228
|
+
* loops' former inline math exactly, so the geometry is bit-identical.
|
|
229
|
+
*/
|
|
230
|
+
static bool R2D_UnitCircle(int sectors, const float **cos_out, const float **sin_out) {
|
|
231
|
+
if (sectors < 3 || sectors > R2D_MAX_SECTORS) return false;
|
|
232
|
+
|
|
233
|
+
if (!unit_cos_table[sectors]) {
|
|
234
|
+
float *cos_t = (float *)malloc(sectors * sizeof(float));
|
|
235
|
+
float *sin_t = (float *)malloc(sectors * sizeof(float));
|
|
236
|
+
if (!cos_t || !sin_t) { free(cos_t); free(sin_t); return false; }
|
|
237
|
+
|
|
238
|
+
float angle_step = (2.0f * M_PI) / sectors;
|
|
239
|
+
for (int i = 0; i < sectors; i++) {
|
|
240
|
+
float angle = i * angle_step;
|
|
241
|
+
cos_t[i] = cosf(angle);
|
|
242
|
+
sin_t[i] = sinf(angle);
|
|
243
|
+
}
|
|
244
|
+
unit_cos_table[sectors] = cos_t;
|
|
245
|
+
unit_sin_table[sectors] = sin_t;
|
|
246
|
+
}
|
|
45
247
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
248
|
+
*cos_out = unit_cos_table[sectors];
|
|
249
|
+
*sin_out = unit_sin_table[sectors];
|
|
250
|
+
return true;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
/*
|
|
255
|
+
* Draw a filled ellipse via a triangle fan.
|
|
256
|
+
* See ruby2d.h for parameter documentation.
|
|
257
|
+
*/
|
|
258
|
+
void R2D_DrawEllipse(float cx, float cy, float rx, float ry, float angle,
|
|
259
|
+
int sectors, float r, float g, float b, float a) {
|
|
260
|
+
|
|
261
|
+
if (sectors < R2D_MIN_SECTORS) sectors = R2D_MIN_SECTORS;
|
|
262
|
+
if (sectors > R2D_MAX_SECTORS) sectors = R2D_MAX_SECTORS;
|
|
263
|
+
|
|
264
|
+
// 1 center + one vertex per sector. The fan's last triangle wraps its index
|
|
265
|
+
// back to the first rim vertex (% sectors), so there's no duplicate rim point
|
|
266
|
+
// at angle 0 / 2π — matching R2D_StrokeEllipse.
|
|
267
|
+
int num_vertices = sectors + 1;
|
|
268
|
+
int num_indices = sectors * 3;
|
|
269
|
+
|
|
270
|
+
// Most ellipses use the default 30 sectors, so serve the vertex and index
|
|
271
|
+
// scratch from the stack and fall back to the heap only past the threshold.
|
|
272
|
+
// Avoids two malloc/free pairs per fill on the per-frame round-shape path.
|
|
273
|
+
SDL_Vertex vertices_stack[R2D_STROKE_STACK_N + 1];
|
|
274
|
+
int indices_stack[R2D_STROKE_STACK_N * 3];
|
|
275
|
+
|
|
276
|
+
SDL_Vertex *vertices;
|
|
277
|
+
int *indices;
|
|
278
|
+
bool heap = sectors > R2D_STROKE_STACK_N;
|
|
279
|
+
|
|
280
|
+
if (heap) {
|
|
281
|
+
vertices = (SDL_Vertex *)malloc(num_vertices * sizeof(SDL_Vertex));
|
|
282
|
+
indices = (int *)malloc(num_indices * sizeof(int));
|
|
283
|
+
if (!vertices || !indices) {
|
|
284
|
+
free(vertices); free(indices);
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
} else {
|
|
288
|
+
vertices = vertices_stack;
|
|
289
|
+
indices = indices_stack;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Center
|
|
293
|
+
vertices[0].position.x = cx;
|
|
294
|
+
vertices[0].position.y = cy;
|
|
295
|
+
vertices[0].color.r = r;
|
|
296
|
+
vertices[0].color.g = g;
|
|
297
|
+
vertices[0].color.b = b;
|
|
298
|
+
vertices[0].color.a = a;
|
|
299
|
+
vertices[0].tex_coord.x = 0.0f;
|
|
300
|
+
vertices[0].tex_coord.y = 0.0f;
|
|
301
|
+
|
|
302
|
+
// Unit-circle cos/sin come from the cached table (no per-vertex trig); only a
|
|
303
|
+
// table-build failure falls back to computing them inline.
|
|
304
|
+
const float *uc, *us;
|
|
305
|
+
bool cached = R2D_UnitCircle(sectors, &uc, &us);
|
|
306
|
+
float angle_step = cached ? 0.0f : (2.0f * M_PI) / sectors;
|
|
307
|
+
// Tilt the whole rim by `angle` (radians) so the ellipse can sit off-axis;
|
|
308
|
+
// when angle is 0 this is the identity, so skip the extra trig.
|
|
309
|
+
float rot_c = 1.0f, rot_s = 0.0f;
|
|
310
|
+
if (angle != 0.0f) { rot_c = cosf(angle); rot_s = sinf(angle); }
|
|
311
|
+
for (int i = 0; i < sectors; i++) {
|
|
312
|
+
float cv = cached ? uc[i] : cosf(i * angle_step);
|
|
313
|
+
float sv = cached ? us[i] : sinf(i * angle_step);
|
|
314
|
+
float ox = rx * cv, oy = ry * sv;
|
|
315
|
+
vertices[i + 1].position.x = cx + ox * rot_c - oy * rot_s;
|
|
316
|
+
vertices[i + 1].position.y = cy + ox * rot_s + oy * rot_c;
|
|
317
|
+
vertices[i + 1].color.r = r;
|
|
318
|
+
vertices[i + 1].color.g = g;
|
|
319
|
+
vertices[i + 1].color.b = b;
|
|
320
|
+
vertices[i + 1].color.a = a;
|
|
321
|
+
vertices[i + 1].tex_coord.x = 0.0f;
|
|
322
|
+
vertices[i + 1].tex_coord.y = 0.0f;
|
|
67
323
|
}
|
|
68
324
|
|
|
69
|
-
|
|
325
|
+
for (int i = 0; i < sectors; i++) {
|
|
326
|
+
indices[i * 3] = 0;
|
|
327
|
+
indices[i * 3 + 1] = i + 1;
|
|
328
|
+
indices[i * 3 + 2] = (i + 1) % sectors + 1;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
R2D_CheckSDL(SDL_RenderGeometry(R2D_GetRenderer(), NULL,
|
|
332
|
+
vertices, num_vertices, indices, num_indices),
|
|
333
|
+
"SDL_RenderGeometry");
|
|
334
|
+
|
|
335
|
+
if (heap) {
|
|
336
|
+
free(indices);
|
|
337
|
+
free(vertices);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
/*
|
|
343
|
+
* Signed area (×2) of a polygon. Positive for CCW, negative for CW
|
|
344
|
+
* winding in screen coordinates (y-down). Used to normalize winding
|
|
345
|
+
* before ear clipping.
|
|
346
|
+
*/
|
|
347
|
+
static float shapes_polygon_signed_area2(const float *verts, int n) {
|
|
348
|
+
float sum = 0.0f;
|
|
349
|
+
for (int i = 0; i < n; i++) {
|
|
350
|
+
int j = (i + 1) % n;
|
|
351
|
+
sum += verts[i * 2] * verts[j * 2 + 1] - verts[j * 2] * verts[i * 2 + 1];
|
|
352
|
+
}
|
|
353
|
+
return sum;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
/*
|
|
358
|
+
* Triangle area sign helper (uses cross product). >0 is CCW, <0 is CW.
|
|
359
|
+
*/
|
|
360
|
+
static float shapes_tri_cross(float ax, float ay, float bx, float by,
|
|
361
|
+
float cx, float cy) {
|
|
362
|
+
return (bx - ax) * (cy - ay) - (by - ay) * (cx - ax);
|
|
70
363
|
}
|
|
71
364
|
|
|
72
365
|
|
|
73
366
|
/*
|
|
74
|
-
*
|
|
367
|
+
* Point-in-triangle test using barycentric sign comparisons.
|
|
368
|
+
* Returns 1 if (px, py) is strictly inside triangle (a, b, c) with the
|
|
369
|
+
* given winding (assumed CCW); points exactly on an edge are excluded.
|
|
75
370
|
*/
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
371
|
+
static int shapes_point_in_tri(float px, float py,
|
|
372
|
+
float ax, float ay,
|
|
373
|
+
float bx, float by,
|
|
374
|
+
float cx, float cy) {
|
|
375
|
+
float d1 = shapes_tri_cross(ax, ay, bx, by, px, py);
|
|
376
|
+
float d2 = shapes_tri_cross(bx, by, cx, cy, px, py);
|
|
377
|
+
float d3 = shapes_tri_cross(cx, cy, ax, ay, px, py);
|
|
378
|
+
// For CCW triangles, all three should be > 0 for strict interior.
|
|
379
|
+
return (d1 > 0.0f && d2 > 0.0f && d3 > 0.0f);
|
|
380
|
+
}
|
|
381
|
+
|
|
82
382
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
383
|
+
/*
|
|
384
|
+
* Is the working polygon convex? (CCW winding assumed.) A blind triangle fan
|
|
385
|
+
* from poly[0] is only correct for a convex polygon — over a concave remainder
|
|
386
|
+
* it emits triangles that spill outside the outline. Used to guard the
|
|
387
|
+
* ear-clipping fan-tail fallback.
|
|
388
|
+
*/
|
|
389
|
+
static bool shapes_remaining_is_convex(const float *verts, const int *poly, int remaining) {
|
|
390
|
+
for (int i = 0; i < remaining; i++) {
|
|
391
|
+
int a = poly[(i + remaining - 1) % remaining];
|
|
392
|
+
int b = poly[i];
|
|
393
|
+
int c = poly[(i + 1) % remaining];
|
|
394
|
+
float cross = shapes_tri_cross(verts[a * 2], verts[a * 2 + 1],
|
|
395
|
+
verts[b * 2], verts[b * 2 + 1],
|
|
396
|
+
verts[c * 2], verts[c * 2 + 1]);
|
|
397
|
+
if (cross < 0.0f) return false; // reflex corner — not convex
|
|
398
|
+
}
|
|
399
|
+
return true;
|
|
86
400
|
}
|
|
87
401
|
|
|
88
402
|
|
|
89
403
|
/*
|
|
90
|
-
*
|
|
404
|
+
* Ear-clipping triangulation of a simple polygon.
|
|
405
|
+
* See ruby2d.h for parameter documentation.
|
|
91
406
|
*/
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
407
|
+
int *R2D_TriangulatePolygon(const float *verts, int n, int *out_tri_count) {
|
|
408
|
+
if (out_tri_count) *out_tri_count = 0;
|
|
409
|
+
if (n < 3) return NULL;
|
|
410
|
+
|
|
411
|
+
int tri_count = n - 2;
|
|
412
|
+
int *indices = (int *)malloc(tri_count * 3 * sizeof(int));
|
|
413
|
+
if (!indices) return NULL;
|
|
414
|
+
|
|
415
|
+
// Fast path for triangles
|
|
416
|
+
if (n == 3) {
|
|
417
|
+
indices[0] = 0;
|
|
418
|
+
indices[1] = 1;
|
|
419
|
+
indices[2] = 2;
|
|
420
|
+
if (out_tri_count) *out_tri_count = 1;
|
|
421
|
+
return indices;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// Build a working list of original-vertex indices ordered CCW.
|
|
425
|
+
// If the input polygon is CW, reverse it so the rest of the algorithm
|
|
426
|
+
// can assume CCW (= "convex corner has positive cross product").
|
|
427
|
+
// poly is internal scratch (freed before return), so serve it from the stack
|
|
428
|
+
// for the common small-n case; only the largest polygons fall to the heap.
|
|
429
|
+
int poly_stack[R2D_STROKE_STACK_N];
|
|
430
|
+
bool poly_heap = n > R2D_STROKE_STACK_N;
|
|
431
|
+
int *poly = poly_heap ? (int *)malloc(n * sizeof(int)) : poly_stack;
|
|
432
|
+
if (!poly) { free(indices); return NULL; }
|
|
433
|
+
|
|
434
|
+
float area2 = shapes_polygon_signed_area2(verts, n);
|
|
435
|
+
if (area2 < 0.0f) {
|
|
436
|
+
// CW input — reverse so we work in CCW order. Output indices still
|
|
437
|
+
// refer to the caller's original vertex array.
|
|
438
|
+
for (int i = 0; i < n; i++) poly[i] = n - 1 - i;
|
|
439
|
+
} else {
|
|
440
|
+
for (int i = 0; i < n; i++) poly[i] = i;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
int remaining = n;
|
|
444
|
+
int out = 0;
|
|
445
|
+
// Guard against pathological inputs (e.g. self-intersecting polygons
|
|
446
|
+
// where no ear can ever be found): cap total iterations.
|
|
447
|
+
int safety = 0;
|
|
448
|
+
int safety_limit = n * n + 4;
|
|
449
|
+
|
|
450
|
+
while (remaining > 3 && safety++ < safety_limit) {
|
|
451
|
+
int found_ear = 0;
|
|
452
|
+
|
|
453
|
+
for (int i = 0; i < remaining; i++) {
|
|
454
|
+
int i_prev = (i + remaining - 1) % remaining;
|
|
455
|
+
int i_next = (i + 1) % remaining;
|
|
456
|
+
|
|
457
|
+
int a = poly[i_prev];
|
|
458
|
+
int b = poly[i];
|
|
459
|
+
int c = poly[i_next];
|
|
460
|
+
|
|
461
|
+
float ax = verts[a * 2], ay = verts[a * 2 + 1];
|
|
462
|
+
float bx = verts[b * 2], by = verts[b * 2 + 1];
|
|
463
|
+
float cx = verts[c * 2], cy = verts[c * 2 + 1];
|
|
464
|
+
|
|
465
|
+
// Corner test (CCW => positive cross). Reject only reflex corners
|
|
466
|
+
// (cross < 0). A collinear corner (cross == 0) is clipped as a
|
|
467
|
+
// zero-area ear: it renders nothing but removes the vertex, keeping
|
|
468
|
+
// the algorithm progressing so polygons with collinear vertex runs
|
|
469
|
+
// don't stall into the fan-tail fallback.
|
|
470
|
+
float cross = shapes_tri_cross(ax, ay, bx, by, cx, cy);
|
|
471
|
+
if (cross < 0.0f) continue;
|
|
472
|
+
|
|
473
|
+
// Ear test: no other polygon vertex lies inside (a, b, c).
|
|
474
|
+
int contains = 0;
|
|
475
|
+
for (int k = 0; k < remaining; k++) {
|
|
476
|
+
if (k == i_prev || k == i || k == i_next) continue;
|
|
477
|
+
int v = poly[k];
|
|
478
|
+
float px = verts[v * 2], py = verts[v * 2 + 1];
|
|
479
|
+
if (shapes_point_in_tri(px, py, ax, ay, bx, by, cx, cy)) {
|
|
480
|
+
contains = 1;
|
|
481
|
+
break;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
if (contains) continue;
|
|
485
|
+
|
|
486
|
+
// Emit the ear and remove vertex b from the working list.
|
|
487
|
+
indices[out++] = a;
|
|
488
|
+
indices[out++] = b;
|
|
489
|
+
indices[out++] = c;
|
|
490
|
+
|
|
491
|
+
for (int k = i; k < remaining - 1; k++) poly[k] = poly[k + 1];
|
|
492
|
+
remaining--;
|
|
493
|
+
found_ear = 1;
|
|
494
|
+
break;
|
|
495
|
+
}
|
|
100
496
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
497
|
+
if (!found_ear) {
|
|
498
|
+
// Degenerate / self-intersecting input. Fall back to a fan over
|
|
499
|
+
// whatever remains so we still emit something defined.
|
|
500
|
+
break;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
104
503
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
504
|
+
// Final triangle (or fan tail on fallback). A blind fan from poly[0] is only
|
|
505
|
+
// correct when the remainder is convex; over a concave remainder (genuinely
|
|
506
|
+
// degenerate / self-intersecting input, documented as unsupported) it would
|
|
507
|
+
// spill triangles outside the shape. In that case emit nothing for the
|
|
508
|
+
// remainder rather than render garbage — the unused slots pad to degenerate
|
|
509
|
+
// triangles below.
|
|
510
|
+
if (remaining == 3 || shapes_remaining_is_convex(verts, poly, remaining)) {
|
|
511
|
+
while (remaining >= 3 && out < tri_count * 3) {
|
|
512
|
+
indices[out++] = poly[0];
|
|
513
|
+
indices[out++] = poly[1];
|
|
514
|
+
indices[out++] = poly[2];
|
|
515
|
+
// Drop poly[1] to continue the fan if any remainder is left.
|
|
516
|
+
for (int k = 1; k < remaining - 1; k++) poly[k] = poly[k + 1];
|
|
517
|
+
remaining--;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
if (poly_heap) free(poly);
|
|
522
|
+
|
|
523
|
+
// Real number of triangles emitted (before any degenerate padding below).
|
|
524
|
+
// Reporting this — not the theoretical n-2 — keeps callers from setting up
|
|
525
|
+
// the zero-area padding triangles when the input was degenerate.
|
|
526
|
+
int real_tri_count = out / 3;
|
|
527
|
+
|
|
528
|
+
// If the loop bailed early, pad unused slots with a degenerate triangle so
|
|
529
|
+
// the buffer stays well-formed even for a caller that ignores the count.
|
|
530
|
+
while (out < tri_count * 3) {
|
|
531
|
+
indices[out++] = 0;
|
|
532
|
+
indices[out++] = 0;
|
|
533
|
+
indices[out++] = 0;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
if (out_tri_count) *out_tri_count = real_tri_count;
|
|
537
|
+
return indices;
|
|
538
|
+
}
|
|
109
539
|
|
|
110
540
|
|
|
111
541
|
/*
|
|
112
|
-
* Draw a
|
|
542
|
+
* Draw a filled polygon. Triangulated via ear clipping so concave
|
|
543
|
+
* polygons fill correctly. See ruby2d.h for parameter documentation.
|
|
113
544
|
*/
|
|
114
|
-
void
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
545
|
+
void R2D_DrawPolygon(const float *verts, int n,
|
|
546
|
+
const float *per_vertex_colors,
|
|
547
|
+
float r, float g, float b, float a) {
|
|
548
|
+
|
|
549
|
+
if (n < 3) return;
|
|
550
|
+
|
|
551
|
+
int tri_count = 0;
|
|
552
|
+
int *indices = R2D_TriangulatePolygon(verts, n, &tri_count);
|
|
553
|
+
if (!indices || tri_count <= 0) { free(indices); return; }
|
|
554
|
+
|
|
555
|
+
// vertices is per-draw scratch; stack-serve it for small n to avoid a
|
|
556
|
+
// per-frame malloc/free. (indices stays heap — it is owned by this path and
|
|
557
|
+
// freed below after the draw.)
|
|
558
|
+
SDL_Vertex vertices_stack[R2D_STROKE_STACK_N];
|
|
559
|
+
bool heap = n > R2D_STROKE_STACK_N;
|
|
560
|
+
SDL_Vertex *vertices = heap ? (SDL_Vertex *)malloc(n * sizeof(SDL_Vertex)) : vertices_stack;
|
|
561
|
+
if (!vertices) { free(indices); return; }
|
|
562
|
+
|
|
563
|
+
for (int i = 0; i < n; i++) {
|
|
564
|
+
vertices[i].position.x = verts[i * 2];
|
|
565
|
+
vertices[i].position.y = verts[i * 2 + 1];
|
|
566
|
+
if (per_vertex_colors) {
|
|
567
|
+
vertices[i].color.r = per_vertex_colors[i * 4];
|
|
568
|
+
vertices[i].color.g = per_vertex_colors[i * 4 + 1];
|
|
569
|
+
vertices[i].color.b = per_vertex_colors[i * 4 + 2];
|
|
570
|
+
vertices[i].color.a = per_vertex_colors[i * 4 + 3];
|
|
571
|
+
} else {
|
|
572
|
+
vertices[i].color.r = r;
|
|
573
|
+
vertices[i].color.g = g;
|
|
574
|
+
vertices[i].color.b = b;
|
|
575
|
+
vertices[i].color.a = a;
|
|
576
|
+
}
|
|
577
|
+
vertices[i].tex_coord.x = 0.0f;
|
|
578
|
+
vertices[i].tex_coord.y = 0.0f;
|
|
579
|
+
}
|
|
120
580
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
581
|
+
R2D_CheckSDL(SDL_RenderGeometry(R2D_GetRenderer(), NULL,
|
|
582
|
+
vertices, n, indices, tri_count * 3),
|
|
583
|
+
"SDL_RenderGeometry");
|
|
124
584
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
x2 + y, y2 - x, r3, g3, b3, a3,
|
|
129
|
-
x2 - y, y2 + x, r4, g4, b4, a4
|
|
130
|
-
);
|
|
131
|
-
};
|
|
585
|
+
free(indices);
|
|
586
|
+
if (heap) free(vertices);
|
|
587
|
+
}
|
|
132
588
|
|
|
133
589
|
|
|
134
590
|
/*
|
|
135
|
-
* Draw a
|
|
591
|
+
* Draw a dashed line from (x1,y1) to (x2,y2) as repeated thick quads.
|
|
592
|
+
* Each of the 4 input colors maps to a corner of the full line quad
|
|
593
|
+
* (c1=start+perp, c2=start-perp, c3=end-perp, c4=end+perp). Per-segment
|
|
594
|
+
* endpoint colors are linearly interpolated along the length.
|
|
595
|
+
* See ruby2d.h for parameter documentation.
|
|
136
596
|
*/
|
|
137
|
-
void
|
|
138
|
-
|
|
597
|
+
void R2D_DrawDashedLine(float x1, float y1, float x2, float y2,
|
|
598
|
+
float stroke_width, float dash, float gap,
|
|
599
|
+
float r1, float g1, float b1, float a1,
|
|
600
|
+
float r2, float g2, float b2, float a2,
|
|
601
|
+
float r3, float g3, float b3, float a3,
|
|
602
|
+
float r4, float g4, float b4, float a4) {
|
|
603
|
+
|
|
604
|
+
if (stroke_width <= 0.0f || dash <= 0.0f) return;
|
|
605
|
+
|
|
606
|
+
float dx = x2 - x1;
|
|
607
|
+
float dy = y2 - y1;
|
|
608
|
+
float length = sqrtf(dx * dx + dy * dy);
|
|
609
|
+
if (length <= 0.0f) return;
|
|
610
|
+
|
|
611
|
+
float ux = dx / length;
|
|
612
|
+
float uy = dy / length;
|
|
613
|
+
float step = dash + (gap > 0.0f ? gap : 0.0f);
|
|
614
|
+
|
|
615
|
+
// Bound the work: a sub-pixel dash/gap on a long line would otherwise issue
|
|
616
|
+
// hundreds of thousands of draw calls and stall the frame. If the segment
|
|
617
|
+
// count blows past a ceiling, scale dash and gap up together (preserving
|
|
618
|
+
// their ratio) so the pattern still reads while the work stays bounded.
|
|
619
|
+
const int max_segments = 10000;
|
|
620
|
+
if (length / step > (float)max_segments) {
|
|
621
|
+
static bool warned = false;
|
|
622
|
+
if (!warned) {
|
|
623
|
+
R2D_Log(R2D_WARN, "Dashed line dash/gap too small; clamping segment count");
|
|
624
|
+
warned = true;
|
|
625
|
+
}
|
|
626
|
+
float f = (length / step) / (float)max_segments;
|
|
627
|
+
dash *= f;
|
|
628
|
+
gap *= f;
|
|
629
|
+
step = dash + (gap > 0.0f ? gap : 0.0f);
|
|
630
|
+
}
|
|
139
631
|
|
|
140
|
-
|
|
632
|
+
// Perpendicular offset, scaled by half the stroke width. Every dash lies
|
|
633
|
+
// along the same line, so this is constant — compute it once instead of
|
|
634
|
+
// re-deriving it per dash inside R2D_DrawLine.
|
|
635
|
+
float half_width = stroke_width / 2.0f;
|
|
636
|
+
float px = -uy * half_width;
|
|
637
|
+
float py = ux * half_width;
|
|
638
|
+
|
|
639
|
+
// Batch every dash into one geometry submission: one quad (4 vertices,
|
|
640
|
+
// 6 indices) per dash. length / step is bounded by max_segments above, so
|
|
641
|
+
// this allocation is bounded; + 2 covers the partial trailing dash.
|
|
642
|
+
int max_dashes = (int)(length / step) + 2;
|
|
643
|
+
SDL_Vertex *vertices = (SDL_Vertex *)malloc((size_t)max_dashes * 4 * sizeof(SDL_Vertex));
|
|
644
|
+
int *indices = (int *)malloc((size_t)max_dashes * 6 * sizeof(int));
|
|
645
|
+
if (!vertices || !indices) {
|
|
646
|
+
free(vertices);
|
|
647
|
+
free(indices);
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
int q = 0;
|
|
652
|
+
float pos = 0.0f;
|
|
653
|
+
while (pos < length) {
|
|
654
|
+
float end = pos + dash;
|
|
655
|
+
if (end > length) end = length;
|
|
656
|
+
|
|
657
|
+
float sx1 = x1 + ux * pos, sy1 = y1 + uy * pos;
|
|
658
|
+
float sx2 = x1 + ux * end, sy2 = y1 + uy * end;
|
|
659
|
+
|
|
660
|
+
float t1 = pos / length;
|
|
661
|
+
float t2 = end / length;
|
|
662
|
+
|
|
663
|
+
// Top edge: lerp c1 -> c4 along length
|
|
664
|
+
float sr1 = r1 + (r4 - r1) * t1, sg1 = g1 + (g4 - g1) * t1;
|
|
665
|
+
float sb1 = b1 + (b4 - b1) * t1, sa1 = a1 + (a4 - a1) * t1;
|
|
666
|
+
float er1 = r1 + (r4 - r1) * t2, eg1 = g1 + (g4 - g1) * t2;
|
|
667
|
+
float eb1 = b1 + (b4 - b1) * t2, ea1 = a1 + (a4 - a1) * t2;
|
|
668
|
+
|
|
669
|
+
// Bottom edge: lerp c2 -> c3 along length
|
|
670
|
+
float sr2 = r2 + (r3 - r2) * t1, sg2 = g2 + (g3 - g2) * t1;
|
|
671
|
+
float sb2 = b2 + (b3 - b2) * t1, sa2 = a2 + (a3 - a2) * t1;
|
|
672
|
+
float er2 = r2 + (r3 - r2) * t2, eg2 = g2 + (g3 - g2) * t2;
|
|
673
|
+
float eb2 = b2 + (b3 - b2) * t2, ea2 = a2 + (a3 - a2) * t2;
|
|
674
|
+
|
|
675
|
+
// Same four corners and winding as R2D_DrawLine, written straight into the
|
|
676
|
+
// batch: start + perp, start - perp, end - perp, end + perp.
|
|
677
|
+
int v = q * 4;
|
|
678
|
+
vertices[v + 0] = (SDL_Vertex){
|
|
679
|
+
.position = { sx1 + px, sy1 + py },
|
|
680
|
+
.color = { sr1, sg1, sb1, sa1 },
|
|
681
|
+
.tex_coord = { 0.0f, 0.0f }
|
|
682
|
+
};
|
|
683
|
+
vertices[v + 1] = (SDL_Vertex){
|
|
684
|
+
.position = { sx1 - px, sy1 - py },
|
|
685
|
+
.color = { sr2, sg2, sb2, sa2 },
|
|
686
|
+
.tex_coord = { 0.0f, 0.0f }
|
|
687
|
+
};
|
|
688
|
+
vertices[v + 2] = (SDL_Vertex){
|
|
689
|
+
.position = { sx2 - px, sy2 - py },
|
|
690
|
+
.color = { er2, eg2, eb2, ea2 },
|
|
691
|
+
.tex_coord = { 0.0f, 0.0f }
|
|
692
|
+
};
|
|
693
|
+
vertices[v + 3] = (SDL_Vertex){
|
|
694
|
+
.position = { sx2 + px, sy2 + py },
|
|
695
|
+
.color = { er1, eg1, eb1, ea1 },
|
|
696
|
+
.tex_coord = { 0.0f, 0.0f }
|
|
697
|
+
};
|
|
698
|
+
|
|
699
|
+
int ix = q * 6;
|
|
700
|
+
indices[ix + 0] = v + 0;
|
|
701
|
+
indices[ix + 1] = v + 1;
|
|
702
|
+
indices[ix + 2] = v + 2;
|
|
703
|
+
indices[ix + 3] = v + 0;
|
|
704
|
+
indices[ix + 4] = v + 2;
|
|
705
|
+
indices[ix + 5] = v + 3;
|
|
706
|
+
|
|
707
|
+
q++;
|
|
708
|
+
pos += step;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
if (q > 0) {
|
|
712
|
+
R2D_CheckSDL(
|
|
713
|
+
SDL_RenderGeometry(R2D_GetRenderer(), NULL, vertices, q * 4, indices, q * 6),
|
|
714
|
+
"SDL_RenderGeometry");
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
free(vertices);
|
|
718
|
+
free(indices);
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
|
|
722
|
+
/*
|
|
723
|
+
* Stroke an ellipse outline as a ring of triangles via SDL_RenderGeometry.
|
|
724
|
+
* Outer radius is (rx + sw/2, ry + sw/2), inner is (rx - sw/2, ry - sw/2),
|
|
725
|
+
* putting the stroke centered on the ellipse line.
|
|
726
|
+
*/
|
|
727
|
+
void R2D_StrokeEllipse(float cx, float cy, float rx, float ry, float angle,
|
|
728
|
+
int sectors, float stroke_width,
|
|
729
|
+
float r, float g, float b, float a) {
|
|
730
|
+
|
|
731
|
+
if (stroke_width <= 0.0f) return;
|
|
732
|
+
if (sectors < R2D_MIN_SECTORS) sectors = R2D_MIN_SECTORS;
|
|
733
|
+
if (sectors > R2D_MAX_SECTORS) sectors = R2D_MAX_SECTORS;
|
|
734
|
+
|
|
735
|
+
float hw = stroke_width / 2.0f;
|
|
736
|
+
float orx = rx + hw, ory = ry + hw;
|
|
737
|
+
float irx = rx - hw, iry = ry - hw;
|
|
738
|
+
if (irx < 0.0f) irx = 0.0f;
|
|
739
|
+
if (iry < 0.0f) iry = 0.0f;
|
|
740
|
+
|
|
741
|
+
int num_vertices = sectors * 2;
|
|
742
|
+
int num_indices = sectors * 6;
|
|
743
|
+
|
|
744
|
+
// Default 30 sectors fits the stack; fall back to the heap only past the
|
|
745
|
+
// threshold. Avoids two malloc/free pairs per stroke on the per-frame path.
|
|
746
|
+
SDL_Vertex vertices_stack[R2D_STROKE_STACK_N * 2];
|
|
747
|
+
int indices_stack[R2D_STROKE_STACK_N * 6];
|
|
748
|
+
|
|
749
|
+
SDL_Vertex *vertices;
|
|
750
|
+
int *indices;
|
|
751
|
+
bool heap = sectors > R2D_STROKE_STACK_N;
|
|
752
|
+
|
|
753
|
+
if (heap) {
|
|
754
|
+
vertices = (SDL_Vertex *)malloc(num_vertices * sizeof(SDL_Vertex));
|
|
755
|
+
indices = (int *)malloc(num_indices * sizeof(int));
|
|
756
|
+
if (!vertices || !indices) {
|
|
757
|
+
free(vertices); free(indices);
|
|
758
|
+
return;
|
|
759
|
+
}
|
|
760
|
+
} else {
|
|
761
|
+
vertices = vertices_stack;
|
|
762
|
+
indices = indices_stack;
|
|
763
|
+
}
|
|
141
764
|
|
|
765
|
+
// Unit-circle cos/sin come from the cached table (no per-vertex trig); only a
|
|
766
|
+
// table-build failure falls back to computing them inline.
|
|
767
|
+
const float *uc, *us;
|
|
768
|
+
bool cached = R2D_UnitCircle(sectors, &uc, &us);
|
|
769
|
+
float angle_step = cached ? 0.0f : (2.0f * M_PI) / sectors;
|
|
770
|
+
// Tilt both rims by `angle` (radians); identity when angle is 0.
|
|
771
|
+
float rot_c = 1.0f, rot_s = 0.0f;
|
|
772
|
+
if (angle != 0.0f) { rot_c = cosf(angle); rot_s = sinf(angle); }
|
|
142
773
|
for (int i = 0; i < sectors; i++) {
|
|
774
|
+
float ca = cached ? uc[i] : cosf(i * angle_step);
|
|
775
|
+
float sa = cached ? us[i] : sinf(i * angle_step);
|
|
776
|
+
|
|
777
|
+
float oox = orx * ca, ooy = ory * sa; // outer rim offset
|
|
778
|
+
float iox = irx * ca, ioy = iry * sa; // inner rim offset
|
|
779
|
+
vertices[i * 2].position.x = cx + oox * rot_c - ooy * rot_s;
|
|
780
|
+
vertices[i * 2].position.y = cy + oox * rot_s + ooy * rot_c;
|
|
781
|
+
vertices[i * 2].color.r = r;
|
|
782
|
+
vertices[i * 2].color.g = g;
|
|
783
|
+
vertices[i * 2].color.b = b;
|
|
784
|
+
vertices[i * 2].color.a = a;
|
|
785
|
+
vertices[i * 2].tex_coord.x = 0.0f;
|
|
786
|
+
vertices[i * 2].tex_coord.y = 0.0f;
|
|
787
|
+
|
|
788
|
+
vertices[i * 2 + 1].position.x = cx + iox * rot_c - ioy * rot_s;
|
|
789
|
+
vertices[i * 2 + 1].position.y = cy + iox * rot_s + ioy * rot_c;
|
|
790
|
+
vertices[i * 2 + 1].color.r = r;
|
|
791
|
+
vertices[i * 2 + 1].color.g = g;
|
|
792
|
+
vertices[i * 2 + 1].color.b = b;
|
|
793
|
+
vertices[i * 2 + 1].color.a = a;
|
|
794
|
+
vertices[i * 2 + 1].tex_coord.x = 0.0f;
|
|
795
|
+
vertices[i * 2 + 1].tex_coord.y = 0.0f;
|
|
796
|
+
}
|
|
143
797
|
|
|
144
|
-
|
|
145
|
-
|
|
798
|
+
for (int i = 0; i < sectors; i++) {
|
|
799
|
+
int j = (i + 1) % sectors;
|
|
800
|
+
int oi = i * 2, ii = i * 2 + 1;
|
|
801
|
+
int oj = j * 2, ij = j * 2 + 1;
|
|
802
|
+
|
|
803
|
+
indices[i * 6] = oi;
|
|
804
|
+
indices[i * 6 + 1] = ii;
|
|
805
|
+
indices[i * 6 + 2] = ij;
|
|
806
|
+
indices[i * 6 + 3] = oi;
|
|
807
|
+
indices[i * 6 + 4] = ij;
|
|
808
|
+
indices[i * 6 + 5] = oj;
|
|
809
|
+
}
|
|
146
810
|
|
|
147
|
-
|
|
148
|
-
|
|
811
|
+
R2D_CheckSDL(SDL_RenderGeometry(R2D_GetRenderer(), NULL,
|
|
812
|
+
vertices, num_vertices, indices, num_indices),
|
|
813
|
+
"SDL_RenderGeometry");
|
|
149
814
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
815
|
+
if (heap) {
|
|
816
|
+
free(indices);
|
|
817
|
+
free(vertices);
|
|
153
818
|
}
|
|
154
819
|
}
|
|
820
|
+
|
|
821
|
+
|
|
822
|
+
/*
|
|
823
|
+
* Draws a filled triangle with per-vertex colors.
|
|
824
|
+
*
|
|
825
|
+
* Parameters:
|
|
826
|
+
* x, y - Vertex position coordinates
|
|
827
|
+
* r, g, b, a - Vertex color values (red, green, blue, alpha)
|
|
828
|
+
* The numbers specify the coordinates and color for each vertex of the triangle
|
|
829
|
+
*
|
|
830
|
+
* The triangle is rendered using the current SDL renderer, and colors are
|
|
831
|
+
* interpolated between vertices.
|
|
832
|
+
*/
|
|
833
|
+
void R2D_DrawTriangle(float x1, float y1,
|
|
834
|
+
float r1, float g1, float b1, float a1,
|
|
835
|
+
float x2, float y2,
|
|
836
|
+
float r2, float g2, float b2, float a2,
|
|
837
|
+
float x3, float y3,
|
|
838
|
+
float r3, float g3, float b3, float a3) {
|
|
839
|
+
|
|
840
|
+
SDL_Vertex vertices[3] = {{
|
|
841
|
+
.position = { x1, y1 },
|
|
842
|
+
.color = { r1, g1, b1, a1 },
|
|
843
|
+
.tex_coord = { 0.0f, 0.0f }
|
|
844
|
+
}, {
|
|
845
|
+
.position = { x2, y2 },
|
|
846
|
+
.color = { r2, g2, b2, a2 },
|
|
847
|
+
.tex_coord = { 0.0f, 0.0f }
|
|
848
|
+
}, {
|
|
849
|
+
.position = { x3, y3 },
|
|
850
|
+
.color = { r3, g3, b3, a3 },
|
|
851
|
+
.tex_coord = { 0.0f, 0.0f }
|
|
852
|
+
}};
|
|
853
|
+
|
|
854
|
+
R2D_CheckSDL(
|
|
855
|
+
SDL_RenderGeometry(R2D_GetRenderer(), NULL, vertices, 3, NULL, 0),
|
|
856
|
+
"SDL_RenderGeometry");
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
|
|
860
|
+
/*
|
|
861
|
+
* Draws a filled quad with per-vertex colors.
|
|
862
|
+
*
|
|
863
|
+
* Parameters:
|
|
864
|
+
* x, y - Vertex position coordinates for each of the 4 corners
|
|
865
|
+
* r, g, b, a - Vertex color values (red, green, blue, alpha) for each corner
|
|
866
|
+
*
|
|
867
|
+
* The quad is rendered as two triangles with interpolated colors.
|
|
868
|
+
*/
|
|
869
|
+
void R2D_DrawQuad(float x1, float y1,
|
|
870
|
+
float r1, float g1, float b1, float a1,
|
|
871
|
+
float x2, float y2,
|
|
872
|
+
float r2, float g2, float b2, float a2,
|
|
873
|
+
float x3, float y3,
|
|
874
|
+
float r3, float g3, float b3, float a3,
|
|
875
|
+
float x4, float y4,
|
|
876
|
+
float r4, float g4, float b4, float a4) {
|
|
877
|
+
|
|
878
|
+
SDL_Vertex vertices[4] = {{
|
|
879
|
+
.position = { x1, y1 },
|
|
880
|
+
.color = { r1, g1, b1, a1 },
|
|
881
|
+
.tex_coord = { 0.0f, 0.0f }
|
|
882
|
+
}, {
|
|
883
|
+
.position = { x2, y2 },
|
|
884
|
+
.color = { r2, g2, b2, a2 },
|
|
885
|
+
.tex_coord = { 0.0f, 0.0f }
|
|
886
|
+
}, {
|
|
887
|
+
.position = { x3, y3 },
|
|
888
|
+
.color = { r3, g3, b3, a3 },
|
|
889
|
+
.tex_coord = { 0.0f, 0.0f }
|
|
890
|
+
}, {
|
|
891
|
+
.position = { x4, y4 },
|
|
892
|
+
.color = { r4, g4, b4, a4 },
|
|
893
|
+
.tex_coord = { 0.0f, 0.0f }
|
|
894
|
+
}};
|
|
895
|
+
|
|
896
|
+
// Indices for two triangles forming the quad
|
|
897
|
+
int indices[6] = { 0, 1, 2, 0, 2, 3 };
|
|
898
|
+
|
|
899
|
+
R2D_CheckSDL(
|
|
900
|
+
SDL_RenderGeometry(R2D_GetRenderer(), NULL, vertices, 4, indices, 6),
|
|
901
|
+
"SDL_RenderGeometry");
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
|
|
905
|
+
/*
|
|
906
|
+
* Draws a line with specified width and per-vertex colors.
|
|
907
|
+
*
|
|
908
|
+
* Parameters:
|
|
909
|
+
* x1, y1 - Start point of the line
|
|
910
|
+
* x2, y2 - End point of the line
|
|
911
|
+
* width - Thickness of the line
|
|
912
|
+
* r, g, b, a - Color values for each of the 4 corners of the line quad
|
|
913
|
+
*
|
|
914
|
+
* The line is rendered as a quad perpendicular to the line direction.
|
|
915
|
+
*/
|
|
916
|
+
void R2D_DrawLine(float x1, float y1, float x2, float y2,
|
|
917
|
+
float width,
|
|
918
|
+
float r1, float g1, float b1, float a1,
|
|
919
|
+
float r2, float g2, float b2, float a2,
|
|
920
|
+
float r3, float g3, float b3, float a3,
|
|
921
|
+
float r4, float g4, float b4, float a4) {
|
|
922
|
+
|
|
923
|
+
// Calculate the direction vector of the line
|
|
924
|
+
float dx = x2 - x1;
|
|
925
|
+
float dy = y2 - y1;
|
|
926
|
+
|
|
927
|
+
// Calculate the length of the line
|
|
928
|
+
float length = sqrtf(dx * dx + dy * dy);
|
|
929
|
+
|
|
930
|
+
// Avoid division by zero for zero-length lines and skip non-positive widths
|
|
931
|
+
// (a negative width would swap the quad sides and still fill a visible band)
|
|
932
|
+
if (length == 0.0f || width <= 0.0f) return;
|
|
933
|
+
|
|
934
|
+
// Calculate the perpendicular unit vector scaled by half width
|
|
935
|
+
float half_width = width / 2.0f;
|
|
936
|
+
float px = (-dy / length) * half_width;
|
|
937
|
+
float py = (dx / length) * half_width;
|
|
938
|
+
|
|
939
|
+
// Calculate the four corners of the line quad
|
|
940
|
+
SDL_Vertex vertices[4] = {{
|
|
941
|
+
.position = { x1 + px, y1 + py },
|
|
942
|
+
.color = { r1, g1, b1, a1 },
|
|
943
|
+
.tex_coord = { 0.0f, 0.0f }
|
|
944
|
+
}, {
|
|
945
|
+
.position = { x1 - px, y1 - py },
|
|
946
|
+
.color = { r2, g2, b2, a2 },
|
|
947
|
+
.tex_coord = { 0.0f, 0.0f }
|
|
948
|
+
}, {
|
|
949
|
+
.position = { x2 - px, y2 - py },
|
|
950
|
+
.color = { r3, g3, b3, a3 },
|
|
951
|
+
.tex_coord = { 0.0f, 0.0f }
|
|
952
|
+
}, {
|
|
953
|
+
.position = { x2 + px, y2 + py },
|
|
954
|
+
.color = { r4, g4, b4, a4 },
|
|
955
|
+
.tex_coord = { 0.0f, 0.0f }
|
|
956
|
+
}};
|
|
957
|
+
|
|
958
|
+
// Indices for two triangles forming the quad
|
|
959
|
+
int indices[6] = { 0, 1, 2, 0, 2, 3 };
|
|
960
|
+
|
|
961
|
+
R2D_CheckSDL(
|
|
962
|
+
SDL_RenderGeometry(R2D_GetRenderer(), NULL, vertices, 4, indices, 6),
|
|
963
|
+
"SDL_RenderGeometry");
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
|
|
967
|
+
/*
|
|
968
|
+
* Draws a filled circle with a solid color.
|
|
969
|
+
*
|
|
970
|
+
* Parameters:
|
|
971
|
+
* x, y - Center position of the circle
|
|
972
|
+
* radius - Radius of the circle
|
|
973
|
+
* sectors - Number of triangular sectors (higher = smoother circle)
|
|
974
|
+
* r, g, b, a - Color values for the circle
|
|
975
|
+
*
|
|
976
|
+
* The circle is rendered as a triangle fan from the center.
|
|
977
|
+
*/
|
|
978
|
+
void R2D_DrawCircle(float x, float y, float radius, int sectors,
|
|
979
|
+
float r, float g, float b, float a) {
|
|
980
|
+
|
|
981
|
+
// A circle is an ellipse with equal radii. Delegating reuses the ellipse
|
|
982
|
+
// rasterizer's heap allocation and NULL checks instead of stack VLAs.
|
|
983
|
+
R2D_DrawEllipse(x, y, radius, radius, 0.0f, sectors, r, g, b, a);
|
|
984
|
+
}
|