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.
Files changed (620) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.md +7 -0
  3. data/README.md +141 -0
  4. data/USAGE.md +2435 -0
  5. data/assets/Rakefile +637 -0
  6. data/assets/build_support/CMakeLists.txt +94 -0
  7. data/assets/build_support/mruby/build_config.rb +34 -0
  8. data/assets/build_support/mruby/build_config_wasm.rb +30 -0
  9. data/assets/build_support/sdl_test.c +174 -0
  10. data/assets/deps.yaml +16 -0
  11. data/assets/platform/include/SDL3/SDL.h +91 -0
  12. data/assets/platform/include/SDL3/SDL_assert.h +705 -0
  13. data/assets/platform/include/SDL3/SDL_asyncio.h +550 -0
  14. data/assets/platform/include/SDL3/SDL_atomic.h +692 -0
  15. data/assets/platform/include/SDL3/SDL_audio.h +2370 -0
  16. data/assets/platform/include/SDL3/SDL_begin_code.h +553 -0
  17. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_bits.h +47 -27
  18. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_blendmode.h +59 -55
  19. data/assets/platform/include/SDL3/SDL_camera.h +535 -0
  20. data/assets/platform/include/SDL3/SDL_clipboard.h +331 -0
  21. data/assets/{include/SDL2/close_code.h → platform/include/SDL3/SDL_close_code.h} +9 -8
  22. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_copying.h +3 -1
  23. data/assets/platform/include/SDL3/SDL_cpuinfo.h +374 -0
  24. data/assets/platform/include/SDL3/SDL_dialog.h +343 -0
  25. data/assets/platform/include/SDL3/SDL_dlopennote.h +234 -0
  26. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_egl.h +11 -8
  27. data/assets/platform/include/SDL3/SDL_endian.h +645 -0
  28. data/assets/platform/include/SDL3/SDL_error.h +226 -0
  29. data/assets/platform/include/SDL3/SDL_events.h +1645 -0
  30. data/assets/platform/include/SDL3/SDL_filesystem.h +537 -0
  31. data/assets/platform/include/SDL3/SDL_gamepad.h +1656 -0
  32. data/assets/platform/include/SDL3/SDL_gpu.h +4608 -0
  33. data/assets/platform/include/SDL3/SDL_guid.h +106 -0
  34. data/assets/platform/include/SDL3/SDL_haptic.h +1461 -0
  35. data/assets/platform/include/SDL3/SDL_hidapi.h +571 -0
  36. data/assets/platform/include/SDL3/SDL_hints.h +5001 -0
  37. data/assets/platform/include/SDL3/SDL_init.h +507 -0
  38. data/assets/platform/include/SDL3/SDL_intrin.h +410 -0
  39. data/assets/platform/include/SDL3/SDL_iostream.h +1379 -0
  40. data/assets/platform/include/SDL3/SDL_joystick.h +1385 -0
  41. data/assets/platform/include/SDL3/SDL_keyboard.h +608 -0
  42. data/assets/platform/include/SDL3/SDL_keycode.h +347 -0
  43. data/assets/platform/include/SDL3/SDL_loadso.h +145 -0
  44. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_locale.h +40 -24
  45. data/assets/platform/include/SDL3/SDL_log.h +541 -0
  46. data/assets/platform/include/SDL3/SDL_main.h +704 -0
  47. data/assets/platform/include/SDL3/SDL_main_impl.h +151 -0
  48. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_messagebox.h +85 -48
  49. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_metal.h +29 -29
  50. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_misc.h +13 -12
  51. data/assets/platform/include/SDL3/SDL_mouse.h +813 -0
  52. data/assets/platform/include/SDL3/SDL_mutex.h +1117 -0
  53. data/assets/platform/include/SDL3/SDL_oldnames.h +1339 -0
  54. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengl.h +1247 -278
  55. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengl_glext.h +5 -1
  56. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles.h +6 -7
  57. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2.h +10 -11
  58. data/assets/platform/include/SDL3/SDL_pen.h +198 -0
  59. data/assets/platform/include/SDL3/SDL_pixels.h +1441 -0
  60. data/assets/{include/SDL2/SDL_test_log.h → platform/include/SDL3/SDL_platform.h} +25 -26
  61. data/assets/platform/include/SDL3/SDL_platform_defines.h +497 -0
  62. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_power.h +40 -20
  63. data/assets/platform/include/SDL3/SDL_process.h +441 -0
  64. data/assets/platform/include/SDL3/SDL_properties.h +572 -0
  65. data/assets/platform/include/SDL3/SDL_rect.h +528 -0
  66. data/assets/platform/include/SDL3/SDL_render.h +3028 -0
  67. data/assets/platform/include/SDL3/SDL_revision.h +59 -0
  68. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_scancode.h +59 -68
  69. data/assets/platform/include/SDL3/SDL_sensor.h +321 -0
  70. data/assets/platform/include/SDL3/SDL_stdinc.h +6186 -0
  71. data/assets/platform/include/SDL3/SDL_storage.h +686 -0
  72. data/assets/platform/include/SDL3/SDL_surface.h +1769 -0
  73. data/assets/platform/include/SDL3/SDL_system.h +840 -0
  74. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test.h +16 -22
  75. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_assert.h +27 -34
  76. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_common.h +109 -52
  77. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_compare.h +22 -14
  78. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_crc32.h +27 -30
  79. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_font.h +50 -49
  80. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_fuzzer.h +64 -79
  81. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_harness.h +47 -30
  82. data/assets/platform/include/SDL3/SDL_test_log.h +83 -0
  83. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_md5.h +21 -28
  84. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_memory.h +19 -16
  85. data/assets/platform/include/SDL3/SDL_thread.h +602 -0
  86. data/assets/platform/include/SDL3/SDL_time.h +249 -0
  87. data/assets/platform/include/SDL3/SDL_timer.h +454 -0
  88. data/assets/platform/include/SDL3/SDL_touch.h +184 -0
  89. data/assets/platform/include/SDL3/SDL_tray.h +544 -0
  90. data/assets/platform/include/SDL3/SDL_version.h +198 -0
  91. data/assets/platform/include/SDL3/SDL_video.h +3497 -0
  92. data/assets/platform/include/SDL3/SDL_vulkan.h +287 -0
  93. data/assets/platform/include/SDL3_image/SDL_image.h +3328 -0
  94. data/assets/platform/include/SDL3_mixer/SDL_mixer.h +3369 -0
  95. data/assets/platform/include/SDL3_ttf/SDL_textengine.h +181 -0
  96. data/assets/platform/include/SDL3_ttf/SDL_ttf.h +2833 -0
  97. data/assets/{include → platform/include}/mrbconf.h +42 -31
  98. data/assets/{include → platform/include}/mruby/array.h +3 -4
  99. data/assets/{include → platform/include}/mruby/boxing_nan.h +10 -0
  100. data/assets/platform/include/mruby/boxing_no.h +59 -0
  101. data/assets/{include → platform/include}/mruby/boxing_word.h +72 -26
  102. data/assets/platform/include/mruby/class.h +157 -0
  103. data/assets/{include → platform/include}/mruby/common.h +30 -1
  104. data/assets/{include → platform/include}/mruby/compile.h +52 -74
  105. data/assets/{include → platform/include}/mruby/data.h +2 -2
  106. data/assets/{include → platform/include}/mruby/debug.h +12 -5
  107. data/assets/{include → platform/include}/mruby/dump.h +7 -9
  108. data/assets/{include → platform/include}/mruby/endian.h +1 -1
  109. data/assets/platform/include/mruby/error.h +173 -0
  110. data/assets/platform/include/mruby/gc.h +79 -0
  111. data/assets/{include → platform/include}/mruby/hash.h +1 -7
  112. data/assets/platform/include/mruby/internal.h +282 -0
  113. data/assets/platform/include/mruby/irep.h +143 -0
  114. data/assets/{include → platform/include}/mruby/istruct.h +1 -1
  115. data/assets/platform/include/mruby/khash.h +455 -0
  116. data/assets/platform/include/mruby/mempool.h +19 -0
  117. data/assets/{include → platform/include}/mruby/numeric.h +7 -10
  118. data/assets/platform/include/mruby/object.h +51 -0
  119. data/assets/{include → platform/include}/mruby/opcode.h +5 -5
  120. data/assets/{include → platform/include}/mruby/ops.h +19 -6
  121. data/assets/platform/include/mruby/presym/id.h +1447 -0
  122. data/assets/{include → platform/include}/mruby/presym/scanning.h +10 -7
  123. data/assets/platform/include/mruby/presym/table.h +2893 -0
  124. data/assets/platform/include/mruby/presym.h +65 -0
  125. data/assets/platform/include/mruby/proc.h +184 -0
  126. data/assets/{include → platform/include}/mruby/range.h +0 -2
  127. data/assets/{include → platform/include}/mruby/string.h +33 -53
  128. data/assets/platform/include/mruby/throw.h +81 -0
  129. data/assets/{include → platform/include}/mruby/value.h +64 -29
  130. data/assets/{include → platform/include}/mruby/variable.h +6 -23
  131. data/assets/{include → platform/include}/mruby/version.h +7 -7
  132. data/assets/{include → platform/include}/mruby.h +238 -116
  133. data/assets/platform/macos-arm64/bin/mrbc +0 -0
  134. data/assets/platform/macos-arm64/lib/libSDL3.a +0 -0
  135. data/assets/platform/macos-arm64/lib/libSDL3_image.a +0 -0
  136. data/assets/platform/macos-arm64/lib/libSDL3_mixer.a +0 -0
  137. data/assets/platform/macos-arm64/lib/libSDL3_ttf.a +0 -0
  138. data/assets/platform/macos-arm64/lib/libmruby.a +0 -0
  139. data/assets/platform/wasm/lib/libFLAC.a +0 -0
  140. data/assets/platform/wasm/lib/libSDL3.a +0 -0
  141. data/assets/platform/wasm/lib/libSDL3_image.a +0 -0
  142. data/assets/platform/wasm/lib/libSDL3_mixer.a +0 -0
  143. data/assets/platform/wasm/lib/libSDL3_ttf.a +0 -0
  144. data/assets/platform/wasm/lib/libfreetype.a +0 -0
  145. data/assets/platform/wasm/lib/libharfbuzz.a +0 -0
  146. data/assets/platform/wasm/lib/libmruby.a +0 -0
  147. data/assets/platform/wasm/lib/libogg.a +0 -0
  148. data/assets/platform/wasm/lib/libplutosvg.a +0 -0
  149. data/assets/platform/wasm/lib/libplutovg.a +0 -0
  150. data/assets/platform/wasm/lib/libpng.a +0 -0
  151. data/assets/platform/wasm/lib/libpng16.a +0 -0
  152. data/assets/platform/wasm/lib/libvorbis.a +0 -0
  153. data/assets/platform/wasm/lib/libvorbisfile.a +0 -0
  154. data/assets/platform/wasm/lib/libzlibstatic.a +0 -0
  155. data/assets/platform/windows-arm64-mingw-ucrt/bin/mrbc.exe +0 -0
  156. data/assets/platform/windows-arm64-mingw-ucrt/lib/libSDL3.a +0 -0
  157. data/assets/platform/windows-arm64-mingw-ucrt/lib/libSDL3_image.a +0 -0
  158. data/assets/platform/windows-arm64-mingw-ucrt/lib/libSDL3_mixer.a +0 -0
  159. data/assets/platform/windows-arm64-mingw-ucrt/lib/libSDL3_ttf.a +0 -0
  160. data/assets/platform/windows-arm64-mingw-ucrt/lib/libmruby.a +0 -0
  161. data/assets/platform/windows-x86_64-mingw-ucrt/bin/mrbc.exe +0 -0
  162. data/assets/platform/windows-x86_64-mingw-ucrt/lib/libSDL3.a +0 -0
  163. data/assets/platform/windows-x86_64-mingw-ucrt/lib/libSDL3_image.a +0 -0
  164. data/assets/platform/windows-x86_64-mingw-ucrt/lib/libSDL3_mixer.a +0 -0
  165. data/assets/platform/windows-x86_64-mingw-ucrt/lib/libSDL3_ttf.a +0 -0
  166. data/assets/platform/windows-x86_64-mingw-ucrt/lib/libmruby.a +0 -0
  167. data/assets/resources/fonts/outfit/OFL.txt +93 -0
  168. data/assets/resources/fonts/outfit/outfit.ttf +0 -0
  169. data/assets/resources/fonts/roboto_mono/OFL.txt +91 -0
  170. data/assets/resources/fonts/roboto_mono/roboto_mono.ttf +0 -0
  171. data/assets/resources/icons/icon.icns +0 -0
  172. data/assets/resources/icons/icon.png +0 -0
  173. data/assets/resources/spritesheets/License.txt +28 -0
  174. data/assets/resources/spritesheets/spritesheet-backgrounds.png +0 -0
  175. data/assets/resources/spritesheets/spritesheet-backgrounds.xml +16 -0
  176. data/assets/resources/spritesheets/spritesheet-characters.png +0 -0
  177. data/assets/resources/spritesheets/spritesheet-characters.xml +47 -0
  178. data/assets/resources/spritesheets/spritesheet-enemies.png +0 -0
  179. data/assets/resources/spritesheets/spritesheet-enemies.xml +62 -0
  180. data/assets/resources/spritesheets/spritesheet-tiles.png +0 -0
  181. data/assets/resources/spritesheets/spritesheet-tiles.xml +316 -0
  182. data/assets/{wasm → resources/web}/template.html +1 -1
  183. data/assets/target.rb +131 -0
  184. data/bin/ruby2d +281 -82
  185. data/examples/astar.rb +269 -0
  186. data/examples/asteroids.rb +403 -0
  187. data/examples/bezier_editor.rb +96 -0
  188. data/examples/boids.rb +191 -0
  189. data/examples/bouncing_balls.rb +119 -0
  190. data/examples/breakout.rb +186 -0
  191. data/examples/constellations.rb +100 -0
  192. data/examples/dashboard.rb +133 -0
  193. data/examples/double_pendulum.rb +254 -0
  194. data/examples/falling_sand.rb +291 -0
  195. data/examples/fireworks.rb +110 -0
  196. data/examples/fluid_dynamics.rb +340 -0
  197. data/examples/fourier_epicycles.rb +142 -0
  198. data/examples/fractal_tree.rb +326 -0
  199. data/examples/game_of_life.rb +148 -0
  200. data/examples/gamepads.rb +333 -0
  201. data/examples/hill_driver.rb +613 -0
  202. data/examples/logo_animation.rb +251 -0
  203. data/examples/lorenz_attractor.rb +115 -0
  204. data/examples/mandelbrot.rb +207 -0
  205. data/examples/marching_squares.rb +200 -0
  206. data/examples/maze.rb +323 -0
  207. data/examples/nbody.rb +338 -0
  208. data/examples/outrun.rb +391 -0
  209. data/examples/pixel_paint.rb +313 -0
  210. data/examples/platformer.rb +335 -0
  211. data/examples/ray_casting_maze.rb +175 -0
  212. data/examples/shadow_casting.rb +151 -0
  213. data/examples/shape_recognizer.rb +908 -0
  214. data/examples/snake.rb +144 -0
  215. data/examples/sprite_sheets.rb +246 -0
  216. data/examples/swarm.rb +206 -0
  217. data/examples/tsp_annealing.rb +104 -0
  218. data/examples/ui_controls.rb +163 -0
  219. data/examples/wireframe_3d.rb +139 -0
  220. data/ext/ruby2d/audio.c +324 -0
  221. data/ext/ruby2d/canvas.c +1715 -494
  222. data/ext/ruby2d/ext.c +541 -0
  223. data/ext/ruby2d/extconf.rb +122 -145
  224. data/ext/ruby2d/font.c +566 -20
  225. data/ext/ruby2d/fps.c +92 -0
  226. data/ext/ruby2d/image.c +466 -41
  227. data/ext/ruby2d/ruby2d.c +374 -1890
  228. data/ext/ruby2d/ruby2d.h +840 -460
  229. data/ext/ruby2d/shapes.c +931 -101
  230. data/ext/ruby2d/text.c +586 -21
  231. data/ext/ruby2d/window.c +1693 -283
  232. data/lib/ruby2d/atlas_parser.rb +194 -0
  233. data/lib/ruby2d/audio.rb +73 -0
  234. data/lib/ruby2d/benchmark.rb +259 -0
  235. data/lib/ruby2d/bitmap_text.rb +155 -0
  236. data/lib/ruby2d/button.rb +402 -0
  237. data/lib/ruby2d/canvas.rb +703 -279
  238. data/lib/ruby2d/circle.rb +206 -29
  239. data/lib/ruby2d/cli/browser.rb +314 -0
  240. data/lib/ruby2d/cli/build.rb +471 -257
  241. data/lib/ruby2d/cli/colorize.rb +7 -5
  242. data/lib/ruby2d/cli/examples.rb +127 -0
  243. data/lib/ruby2d/cli/launch.rb +24 -39
  244. data/lib/ruby2d/cli/lib_files.rb +48 -0
  245. data/lib/ruby2d/cli/messages.rb +40 -0
  246. data/lib/ruby2d/cli/setup.rb +273 -0
  247. data/lib/ruby2d/cli/static_server.rb +160 -0
  248. data/lib/ruby2d/cli/usage.rb +255 -0
  249. data/lib/ruby2d/color.rb +191 -69
  250. data/lib/ruby2d/core.rb +37 -19
  251. data/lib/ruby2d/deps_help.rb +89 -0
  252. data/lib/ruby2d/dsl.rb +51 -12
  253. data/lib/ruby2d/ellipse.rb +228 -0
  254. data/lib/ruby2d/exceptions.rb +0 -2
  255. data/lib/ruby2d/font.rb +34 -74
  256. data/lib/ruby2d/gamepad.rb +323 -0
  257. data/lib/ruby2d/gem_paths.rb +19 -0
  258. data/lib/ruby2d/image.rb +155 -52
  259. data/lib/ruby2d/interactive.rb +103 -0
  260. data/lib/ruby2d/json_parser.rb +268 -0
  261. data/lib/ruby2d/line.rb +194 -85
  262. data/lib/ruby2d/mruby_compat.rb +12 -0
  263. data/lib/ruby2d/polygon.rb +297 -0
  264. data/lib/ruby2d/polyline.rb +368 -0
  265. data/lib/ruby2d/quad.rb +358 -94
  266. data/lib/ruby2d/rectangle.rb +77 -19
  267. data/lib/ruby2d/renderable.rb +411 -11
  268. data/lib/ruby2d/sprite.rb +471 -180
  269. data/lib/ruby2d/sprite_sheet.rb +64 -0
  270. data/lib/ruby2d/square.rb +29 -17
  271. data/lib/ruby2d/text.rb +196 -65
  272. data/lib/ruby2d/tileset.rb +139 -81
  273. data/lib/ruby2d/triangle.rb +324 -89
  274. data/lib/ruby2d/version.rb +1 -3
  275. data/lib/ruby2d/vertices.rb +62 -85
  276. data/lib/ruby2d/warnings.rb +29 -0
  277. data/lib/ruby2d/window/class_methods.rb +218 -0
  278. data/lib/ruby2d/window/gamepad_events.rb +141 -0
  279. data/lib/ruby2d/window/key_events.rb +74 -0
  280. data/lib/ruby2d/window/mouse_events.rb +171 -0
  281. data/lib/ruby2d/window/object_events.rb +168 -0
  282. data/lib/ruby2d/window.rb +632 -585
  283. data/lib/ruby2d.rb +14 -19
  284. metadata +275 -443
  285. data/assets/app.icns +0 -0
  286. data/assets/include/GL/glew.h +0 -26427
  287. data/assets/include/GLES2/gl2.h +0 -656
  288. data/assets/include/GLES2/gl2ext.h +0 -3949
  289. data/assets/include/GLES2/gl2ext_angle.h +0 -701
  290. data/assets/include/GLES2/gl2platform.h +0 -27
  291. data/assets/include/GLES3/gl3.h +0 -1192
  292. data/assets/include/GLES3/gl31.h +0 -1507
  293. data/assets/include/GLES3/gl32.h +0 -1808
  294. data/assets/include/GLES3/gl3platform.h +0 -27
  295. data/assets/include/KHR/khrplatform.h +0 -290
  296. data/assets/include/SDL2/SDL.h +0 -233
  297. data/assets/include/SDL2/SDL_assert.h +0 -326
  298. data/assets/include/SDL2/SDL_atomic.h +0 -415
  299. data/assets/include/SDL2/SDL_audio.h +0 -1500
  300. data/assets/include/SDL2/SDL_clipboard.h +0 -141
  301. data/assets/include/SDL2/SDL_config.h +0 -61
  302. data/assets/include/SDL2/SDL_config_android.h +0 -194
  303. data/assets/include/SDL2/SDL_config_emscripten.h +0 -218
  304. data/assets/include/SDL2/SDL_config_iphoneos.h +0 -217
  305. data/assets/include/SDL2/SDL_config_macosx.h +0 -277
  306. data/assets/include/SDL2/SDL_config_minimal.h +0 -95
  307. data/assets/include/SDL2/SDL_config_ngage.h +0 -89
  308. data/assets/include/SDL2/SDL_config_os2.h +0 -207
  309. data/assets/include/SDL2/SDL_config_pandora.h +0 -141
  310. data/assets/include/SDL2/SDL_config_windows.h +0 -331
  311. data/assets/include/SDL2/SDL_config_wingdk.h +0 -253
  312. data/assets/include/SDL2/SDL_config_winrt.h +0 -220
  313. data/assets/include/SDL2/SDL_config_xbox.h +0 -235
  314. data/assets/include/SDL2/SDL_cpuinfo.h +0 -594
  315. data/assets/include/SDL2/SDL_endian.h +0 -348
  316. data/assets/include/SDL2/SDL_error.h +0 -163
  317. data/assets/include/SDL2/SDL_events.h +0 -1166
  318. data/assets/include/SDL2/SDL_filesystem.h +0 -149
  319. data/assets/include/SDL2/SDL_gamecontroller.h +0 -1074
  320. data/assets/include/SDL2/SDL_gesture.h +0 -117
  321. data/assets/include/SDL2/SDL_guid.h +0 -100
  322. data/assets/include/SDL2/SDL_haptic.h +0 -1341
  323. data/assets/include/SDL2/SDL_hidapi.h +0 -451
  324. data/assets/include/SDL2/SDL_hints.h +0 -2569
  325. data/assets/include/SDL2/SDL_image.h +0 -2173
  326. data/assets/include/SDL2/SDL_joystick.h +0 -1066
  327. data/assets/include/SDL2/SDL_keyboard.h +0 -353
  328. data/assets/include/SDL2/SDL_keycode.h +0 -358
  329. data/assets/include/SDL2/SDL_loadso.h +0 -115
  330. data/assets/include/SDL2/SDL_log.h +0 -404
  331. data/assets/include/SDL2/SDL_main.h +0 -275
  332. data/assets/include/SDL2/SDL_mixer.h +0 -2784
  333. data/assets/include/SDL2/SDL_mouse.h +0 -465
  334. data/assets/include/SDL2/SDL_mutex.h +0 -471
  335. data/assets/include/SDL2/SDL_name.h +0 -33
  336. data/assets/include/SDL2/SDL_pixels.h +0 -644
  337. data/assets/include/SDL2/SDL_platform.h +0 -261
  338. data/assets/include/SDL2/SDL_quit.h +0 -58
  339. data/assets/include/SDL2/SDL_rect.h +0 -376
  340. data/assets/include/SDL2/SDL_render.h +0 -1919
  341. data/assets/include/SDL2/SDL_revision.h +0 -6
  342. data/assets/include/SDL2/SDL_rwops.h +0 -841
  343. data/assets/include/SDL2/SDL_sensor.h +0 -322
  344. data/assets/include/SDL2/SDL_shape.h +0 -155
  345. data/assets/include/SDL2/SDL_stdinc.h +0 -830
  346. data/assets/include/SDL2/SDL_surface.h +0 -997
  347. data/assets/include/SDL2/SDL_system.h +0 -623
  348. data/assets/include/SDL2/SDL_syswm.h +0 -386
  349. data/assets/include/SDL2/SDL_test_images.h +0 -78
  350. data/assets/include/SDL2/SDL_test_random.h +0 -115
  351. data/assets/include/SDL2/SDL_thread.h +0 -464
  352. data/assets/include/SDL2/SDL_timer.h +0 -222
  353. data/assets/include/SDL2/SDL_touch.h +0 -150
  354. data/assets/include/SDL2/SDL_ttf.h +0 -2316
  355. data/assets/include/SDL2/SDL_types.h +0 -29
  356. data/assets/include/SDL2/SDL_version.h +0 -204
  357. data/assets/include/SDL2/SDL_video.h +0 -2150
  358. data/assets/include/SDL2/SDL_vulkan.h +0 -215
  359. data/assets/include/SDL2/begin_code.h +0 -187
  360. data/assets/include/mruby/boxing_no.h +0 -58
  361. data/assets/include/mruby/class.h +0 -108
  362. data/assets/include/mruby/error.h +0 -147
  363. data/assets/include/mruby/gc.h +0 -94
  364. data/assets/include/mruby/irep.h +0 -147
  365. data/assets/include/mruby/khash.h +0 -284
  366. data/assets/include/mruby/object.h +0 -43
  367. data/assets/include/mruby/presym/disable.h +0 -70
  368. data/assets/include/mruby/presym/enable.h +0 -37
  369. data/assets/include/mruby/presym.h +0 -40
  370. data/assets/include/mruby/proc.h +0 -211
  371. data/assets/include/mruby/throw.h +0 -66
  372. data/assets/macos/universal/bin/mrbc +0 -0
  373. data/assets/macos/universal/lib/libFLAC.a +0 -0
  374. data/assets/macos/universal/lib/libSDL2.a +0 -0
  375. data/assets/macos/universal/lib/libSDL2_image.a +0 -0
  376. data/assets/macos/universal/lib/libSDL2_mixer.a +0 -0
  377. data/assets/macos/universal/lib/libSDL2_ttf.a +0 -0
  378. data/assets/macos/universal/lib/libavif.a +0 -0
  379. data/assets/macos/universal/lib/libbrotlicommon-static.a +0 -0
  380. data/assets/macos/universal/lib/libbrotlidec-static.a +0 -0
  381. data/assets/macos/universal/lib/libfreetype.a +0 -0
  382. data/assets/macos/universal/lib/libgraphite2.a +0 -0
  383. data/assets/macos/universal/lib/libharfbuzz.a +0 -0
  384. data/assets/macos/universal/lib/libhwy.a +0 -0
  385. data/assets/macos/universal/lib/libjpeg.a +0 -0
  386. data/assets/macos/universal/lib/libjxl.a +0 -0
  387. data/assets/macos/universal/lib/libmodplug.a +0 -0
  388. data/assets/macos/universal/lib/libmpg123.a +0 -0
  389. data/assets/macos/universal/lib/libmruby.a +0 -0
  390. data/assets/macos/universal/lib/libogg.a +0 -0
  391. data/assets/macos/universal/lib/libpng.a +0 -0
  392. data/assets/macos/universal/lib/libtiff.a +0 -0
  393. data/assets/macos/universal/lib/libvorbis.a +0 -0
  394. data/assets/macos/universal/lib/libvorbisfile.a +0 -0
  395. data/assets/macos/universal/lib/libwebp.a +0 -0
  396. data/assets/macos/universal/lib/libzstd.a +0 -0
  397. data/assets/test_media/README.md +0 -3
  398. data/assets/test_media/bitstream_vera/COPYRIGHT.txt +0 -124
  399. data/assets/test_media/bitstream_vera/vera.ttf +0 -0
  400. data/assets/test_media/boom.png +0 -0
  401. data/assets/test_media/coin.png +0 -0
  402. data/assets/test_media/colors.png +0 -0
  403. data/assets/test_media/controller.png +0 -0
  404. data/assets/test_media/dial.wav +0 -0
  405. data/assets/test_media/hero.png +0 -0
  406. data/assets/test_media/image.bmp +0 -0
  407. data/assets/test_media/image.jpg +0 -0
  408. data/assets/test_media/image.png +0 -0
  409. data/assets/test_media/music.flac +0 -0
  410. data/assets/test_media/music.mp3 +0 -0
  411. data/assets/test_media/music.ogg +0 -0
  412. data/assets/test_media/music.wav +0 -0
  413. data/assets/test_media/originals/boom.pxm +0 -0
  414. data/assets/test_media/originals/coin.pxm +0 -0
  415. data/assets/test_media/originals/controller.sketch +0 -0
  416. data/assets/test_media/originals/hero.pxm +0 -0
  417. data/assets/test_media/originals/image.pxm +0 -0
  418. data/assets/test_media/originals/music.caf +0 -0
  419. data/assets/test_media/originals/texture_atlas.pxm +0 -0
  420. data/assets/test_media/rondo_alla_turka.ogg +0 -0
  421. data/assets/test_media/sound.flac +0 -0
  422. data/assets/test_media/sound.mp3 +0 -0
  423. data/assets/test_media/sound.ogg +0 -0
  424. data/assets/test_media/sound.wav +0 -0
  425. data/assets/test_media/sprite_sheet.png +0 -0
  426. data/assets/test_media/texture_atlas.png +0 -0
  427. data/assets/wasm/libmruby.a +0 -0
  428. data/assets/windows/mingw-w64-ucrt-x86_64/bin/mrbc.exe +0 -0
  429. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libFLAC.a +0 -0
  430. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libLerc.a +0 -0
  431. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2.a +0 -0
  432. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_image.a +0 -0
  433. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_mixer.a +0 -0
  434. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_ttf.a +0 -0
  435. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libbrotlicommon.a +0 -0
  436. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libbrotlidec.a +0 -0
  437. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libbz2.a +0 -0
  438. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libdeflate.a +0 -0
  439. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libfreetype.a +0 -0
  440. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libglew32.a +0 -0
  441. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libgraphite2.a +0 -0
  442. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libharfbuzz.a +0 -0
  443. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libhwy.a +0 -0
  444. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libjbig.a +0 -0
  445. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libjpeg.a +0 -0
  446. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libjxl.a +0 -0
  447. data/assets/windows/mingw-w64-ucrt-x86_64/lib/liblzma.a +0 -0
  448. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libmodplug.a +0 -0
  449. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libmpg123.a +0 -0
  450. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libmruby.a +0 -0
  451. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libogg.a +0 -0
  452. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libopus.a +0 -0
  453. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libopusfile.a +0 -0
  454. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libpng.a +0 -0
  455. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libsndfile.a +0 -0
  456. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libssp.a +0 -1
  457. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libstdc++.a +0 -0
  458. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libtiff.a +0 -0
  459. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libvorbis.a +0 -0
  460. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libvorbisfile.a +0 -0
  461. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libwebp.a +0 -0
  462. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libz.a +0 -0
  463. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libzstd.a +0 -0
  464. data/assets/windows/mingw-w64-x86_64/bin/mrbc.exe +0 -0
  465. data/assets/windows/mingw-w64-x86_64/lib/libFLAC.a +0 -0
  466. data/assets/windows/mingw-w64-x86_64/lib/libLerc.a +0 -0
  467. data/assets/windows/mingw-w64-x86_64/lib/libSDL2.a +0 -0
  468. data/assets/windows/mingw-w64-x86_64/lib/libSDL2_image.a +0 -0
  469. data/assets/windows/mingw-w64-x86_64/lib/libSDL2_mixer.a +0 -0
  470. data/assets/windows/mingw-w64-x86_64/lib/libSDL2_ttf.a +0 -0
  471. data/assets/windows/mingw-w64-x86_64/lib/libbrotlicommon.a +0 -0
  472. data/assets/windows/mingw-w64-x86_64/lib/libbrotlidec.a +0 -0
  473. data/assets/windows/mingw-w64-x86_64/lib/libbz2.a +0 -0
  474. data/assets/windows/mingw-w64-x86_64/lib/libdeflate.a +0 -0
  475. data/assets/windows/mingw-w64-x86_64/lib/libfreetype.a +0 -0
  476. data/assets/windows/mingw-w64-x86_64/lib/libglew32.a +0 -0
  477. data/assets/windows/mingw-w64-x86_64/lib/libgraphite2.a +0 -0
  478. data/assets/windows/mingw-w64-x86_64/lib/libharfbuzz.a +0 -0
  479. data/assets/windows/mingw-w64-x86_64/lib/libhwy.a +0 -0
  480. data/assets/windows/mingw-w64-x86_64/lib/libjbig.a +0 -0
  481. data/assets/windows/mingw-w64-x86_64/lib/libjpeg.a +0 -0
  482. data/assets/windows/mingw-w64-x86_64/lib/libjxl.a +0 -0
  483. data/assets/windows/mingw-w64-x86_64/lib/liblzma.a +0 -0
  484. data/assets/windows/mingw-w64-x86_64/lib/libmodplug.a +0 -0
  485. data/assets/windows/mingw-w64-x86_64/lib/libmpg123.a +0 -0
  486. data/assets/windows/mingw-w64-x86_64/lib/libmruby.a +0 -0
  487. data/assets/windows/mingw-w64-x86_64/lib/libogg.a +0 -0
  488. data/assets/windows/mingw-w64-x86_64/lib/libopus.a +0 -0
  489. data/assets/windows/mingw-w64-x86_64/lib/libopusfile.a +0 -0
  490. data/assets/windows/mingw-w64-x86_64/lib/libpng.a +0 -0
  491. data/assets/windows/mingw-w64-x86_64/lib/libsndfile.a +0 -0
  492. data/assets/windows/mingw-w64-x86_64/lib/libssp.a +0 -1
  493. data/assets/windows/mingw-w64-x86_64/lib/libstdc++.a +0 -0
  494. data/assets/windows/mingw-w64-x86_64/lib/libtiff.a +0 -0
  495. data/assets/windows/mingw-w64-x86_64/lib/libvorbis.a +0 -0
  496. data/assets/windows/mingw-w64-x86_64/lib/libvorbisfile.a +0 -0
  497. data/assets/windows/mingw-w64-x86_64/lib/libwebp.a +0 -0
  498. data/assets/windows/mingw-w64-x86_64/lib/libz.a +0 -0
  499. data/assets/windows/mingw-w64-x86_64/lib/libzstd.a +0 -0
  500. data/assets/xcode/ios/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -98
  501. data/assets/xcode/ios/Assets.xcassets/Contents.json +0 -6
  502. data/assets/xcode/ios/Base.lproj/LaunchScreen.storyboard +0 -27
  503. data/assets/xcode/ios/Info.plist +0 -43
  504. data/assets/xcode/ios/MRuby.framework/Headers/mrbconf.h +0 -143
  505. data/assets/xcode/ios/MRuby.framework/Headers/mruby/array.h +0 -280
  506. data/assets/xcode/ios/MRuby.framework/Headers/mruby/boxing_nan.h +0 -102
  507. data/assets/xcode/ios/MRuby.framework/Headers/mruby/boxing_no.h +0 -56
  508. data/assets/xcode/ios/MRuby.framework/Headers/mruby/boxing_word.h +0 -144
  509. data/assets/xcode/ios/MRuby.framework/Headers/mruby/class.h +0 -97
  510. data/assets/xcode/ios/MRuby.framework/Headers/mruby/common.h +0 -77
  511. data/assets/xcode/ios/MRuby.framework/Headers/mruby/compile.h +0 -195
  512. data/assets/xcode/ios/MRuby.framework/Headers/mruby/data.h +0 -75
  513. data/assets/xcode/ios/MRuby.framework/Headers/mruby/debug.h +0 -67
  514. data/assets/xcode/ios/MRuby.framework/Headers/mruby/dump.h +0 -196
  515. data/assets/xcode/ios/MRuby.framework/Headers/mruby/error.h +0 -75
  516. data/assets/xcode/ios/MRuby.framework/Headers/mruby/gc.h +0 -91
  517. data/assets/xcode/ios/MRuby.framework/Headers/mruby/hash.h +0 -215
  518. data/assets/xcode/ios/MRuby.framework/Headers/mruby/irep.h +0 -75
  519. data/assets/xcode/ios/MRuby.framework/Headers/mruby/istruct.h +0 -47
  520. data/assets/xcode/ios/MRuby.framework/Headers/mruby/khash.h +0 -274
  521. data/assets/xcode/ios/MRuby.framework/Headers/mruby/numeric.h +0 -161
  522. data/assets/xcode/ios/MRuby.framework/Headers/mruby/object.h +0 -44
  523. data/assets/xcode/ios/MRuby.framework/Headers/mruby/opcode.h +0 -69
  524. data/assets/xcode/ios/MRuby.framework/Headers/mruby/ops.h +0 -117
  525. data/assets/xcode/ios/MRuby.framework/Headers/mruby/proc.h +0 -131
  526. data/assets/xcode/ios/MRuby.framework/Headers/mruby/range.h +0 -49
  527. data/assets/xcode/ios/MRuby.framework/Headers/mruby/re.h +0 -16
  528. data/assets/xcode/ios/MRuby.framework/Headers/mruby/string.h +0 -444
  529. data/assets/xcode/ios/MRuby.framework/Headers/mruby/throw.h +0 -55
  530. data/assets/xcode/ios/MRuby.framework/Headers/mruby/value.h +0 -309
  531. data/assets/xcode/ios/MRuby.framework/Headers/mruby/variable.h +0 -136
  532. data/assets/xcode/ios/MRuby.framework/Headers/mruby/version.h +0 -110
  533. data/assets/xcode/ios/MRuby.framework/Headers/mruby.h +0 -1282
  534. data/assets/xcode/ios/MRuby.framework/Info.plist +0 -20
  535. data/assets/xcode/ios/MRuby.framework/MRuby +0 -0
  536. data/assets/xcode/ios/MyApp.xcodeproj/project.pbxproj +0 -368
  537. data/assets/xcode/ios/MyApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
  538. data/assets/xcode/ios/MyApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
  539. data/assets/xcode/ios/MyApp.xcodeproj/project.xcworkspace/xcshareddata/MyApp.xcscmblueprint +0 -30
  540. data/assets/xcode/ios/main.c +0 -1
  541. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Content.imageset/Contents.json +0 -16
  542. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Contents.json +0 -6
  543. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Contents.json +0 -17
  544. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Content.imageset/Contents.json +0 -16
  545. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Contents.json +0 -6
  546. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json +0 -16
  547. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Contents.json +0 -6
  548. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Content.imageset/Contents.json +0 -16
  549. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Contents.json +0 -6
  550. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Contents.json +0 -17
  551. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/Contents.json +0 -16
  552. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Contents.json +0 -6
  553. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json +0 -16
  554. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Contents.json +0 -6
  555. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json +0 -32
  556. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json +0 -16
  557. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json +0 -16
  558. data/assets/xcode/tvos/Assets.xcassets/Contents.json +0 -6
  559. data/assets/xcode/tvos/Assets.xcassets/LaunchImage.launchimage/Contents.json +0 -22
  560. data/assets/xcode/tvos/Info.plist +0 -30
  561. data/assets/xcode/tvos/MRuby.framework/Headers/mrbconf.h +0 -143
  562. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/array.h +0 -280
  563. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/boxing_nan.h +0 -102
  564. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/boxing_no.h +0 -56
  565. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/boxing_word.h +0 -144
  566. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/class.h +0 -97
  567. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/common.h +0 -77
  568. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/compile.h +0 -195
  569. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/data.h +0 -75
  570. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/debug.h +0 -67
  571. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/dump.h +0 -196
  572. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/error.h +0 -75
  573. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/gc.h +0 -91
  574. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/hash.h +0 -215
  575. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/irep.h +0 -75
  576. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/istruct.h +0 -47
  577. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/khash.h +0 -274
  578. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/numeric.h +0 -161
  579. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/object.h +0 -44
  580. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/opcode.h +0 -69
  581. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/ops.h +0 -117
  582. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/proc.h +0 -131
  583. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/range.h +0 -49
  584. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/re.h +0 -16
  585. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/string.h +0 -444
  586. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/throw.h +0 -55
  587. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/value.h +0 -309
  588. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/variable.h +0 -136
  589. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/version.h +0 -110
  590. data/assets/xcode/tvos/MRuby.framework/Headers/mruby.h +0 -1282
  591. data/assets/xcode/tvos/MRuby.framework/Info.plist +0 -20
  592. data/assets/xcode/tvos/MRuby.framework/MRuby +0 -0
  593. data/assets/xcode/tvos/MyApp.xcodeproj/project.pbxproj +0 -350
  594. data/assets/xcode/tvos/MyApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
  595. data/assets/xcode/tvos/MyApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
  596. data/assets/xcode/tvos/MyApp.xcodeproj/project.xcworkspace/xcshareddata/MyApp.xcscmblueprint +0 -30
  597. data/assets/xcode/tvos/main.c +0 -1
  598. data/ext/ruby2d/common.c +0 -185
  599. data/ext/ruby2d/controllers.c +0 -110
  600. data/ext/ruby2d/gl.c +0 -398
  601. data/ext/ruby2d/gl2.c +0 -86
  602. data/ext/ruby2d/gl3.c +0 -304
  603. data/ext/ruby2d/gles.c +0 -302
  604. data/ext/ruby2d/input.c +0 -48
  605. data/ext/ruby2d/music.c +0 -127
  606. data/ext/ruby2d/sound.c +0 -132
  607. data/lib/ruby2d/cli/console.rb +0 -65
  608. data/lib/ruby2d/cli/enable_console.rb +0 -7
  609. data/lib/ruby2d/cli/platform.rb +0 -17
  610. data/lib/ruby2d/music.rb +0 -77
  611. data/lib/ruby2d/pixel.rb +0 -18
  612. data/lib/ruby2d/pixmap.rb +0 -39
  613. data/lib/ruby2d/pixmap_atlas.rb +0 -56
  614. data/lib/ruby2d/sound.rb +0 -61
  615. data/lib/ruby2d/texture.rb +0 -38
  616. /data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2_gl2.h +0 -0
  617. /data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2_gl2ext.h +0 -0
  618. /data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2_gl2platform.h +0 -0
  619. /data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2_khrplatform.h +0 -0
  620. /data/assets/{include → platform/include}/mruby/re.h +0 -0
data/lib/ruby2d/window.rb CHANGED
@@ -1,30 +1,56 @@
1
- # frozen_string_literal: true
2
-
3
1
  # Ruby2D::Window
4
2
 
5
3
  module Ruby2D
6
- # Represents a window on screen, responsible for storing renderable graphics,
7
- # event handlers, the update loop, showing and closing the window.
8
-
9
- attr_reader :width, :height
10
-
4
+ # The application window
11
5
  class Window
12
6
  # Event structures
13
7
  EventDescriptor = Struct.new(:type, :id)
14
- MouseEvent = Struct.new(:type, :button, :direction, :x, :y, :delta_x, :delta_y)
15
- KeyEvent = Struct.new(:type, :key)
16
- ControllerEvent = Struct.new(:which, :type, :axis, :value, :button)
17
- ControllerAxisEvent = Struct.new(:which, :axis, :value)
18
- ControllerButtonEvent = Struct.new(:which, :button)
8
+ ObjectEventDescriptor = Struct.new(:object, :type, :id)
9
+ MouseEvent = Struct.new(:type, :button, :direction, :x, :y, :delta_x, :delta_y) do
10
+ def button?(name) = button == name
11
+ def position = [x, y]
12
+ def delta = [delta_x, delta_y]
13
+ end
14
+ KeyEvent = Struct.new(:type, :key) do
15
+ def key?(name) = key == name.to_s.downcase
16
+ end
17
+
18
+ include KeyEvents
19
+ include MouseEvents
20
+ include GamepadEvents
21
+ include ObjectEventDispatch
22
+ extend ClassMethods
23
+
24
+ attr_reader :title, :width, :height, :fps_cap, :fps, :frames, :delta_time,
25
+ :background, :icon, :resizable,
26
+ :highdpi, :pixel_scale,
27
+ :viewport_width, :viewport_height, :viewport_mode,
28
+ :render_mode,
29
+ :mouse_x, :mouse_y, :diagnostics, :show_fps, :close_on_esc
30
+
31
+ # Accepted `fps_cap` values, shared by the strict constructor check and the
32
+ # lenient runtime setter so the two messages can't drift apart.
33
+ FPS_CAP_VALUES = 'nil, a positive number, :infinity, or Float::INFINITY'
34
+
35
+ # Recognized `viewport:` modes. The native parser silently falls back to
36
+ # letterbox for anything else, so validate here to surface typos rather than
37
+ # let `viewport_mode` report a value the renderer never applied. Must match
38
+ # R2D_ParseViewportMode in ext/ruby2d/window.c.
39
+ VIEWPORT_MODES = %i[letterbox stretch integer overscan expand fixed].freeze
40
+
41
+ # Create a window
42
+ def initialize(title: 'Ruby 2D', width: 640, height: 480, fps_cap: nil)
43
+ # Ruby 2D is single-window by design: per-object events and the top-level
44
+ # DSL all route through one shared `DSL.window`. A second window would
45
+ # silently steal that pointer and strand the first window's objects and
46
+ # event handlers, so refuse to create one.
47
+ if Ruby2D::DSL.window?
48
+ raise Error,
49
+ 'A window already exists. Ruby 2D supports a single window per ' \
50
+ 'process (it may have been created automatically on first use of ' \
51
+ 'a Window class method or the top-level DSL).'
52
+ end
19
53
 
20
- #
21
- # Create a Window
22
- # @param title [String] Title for the window
23
- # @param width [Numeric] In pixels
24
- # @param height [Numeric] in pixels
25
- # @param fps_cap [Numeric] Over-ride the default (60fps) frames-per-second
26
- # @param vsync [Boolean] Enabled by default, use this to override it (Not recommended)
27
- def initialize(title: 'Ruby 2D', width: 640, height: 480, fps_cap: 60, vsync: true)
28
54
  # Title of the window
29
55
  @title = title
30
56
 
@@ -32,246 +58,128 @@ module Ruby2D
32
58
  @width = width
33
59
  @height = height
34
60
 
35
- # Frames per second upper limit, and the actual FPS
61
+ # Frames per second upper limit, and the actual FPS. Valid: nil (no cap),
62
+ # a positive number, or Float::INFINITY (uncapped). The constructor is
63
+ # strict; the runtime setter (#set) warns and falls back instead.
64
+ fps_cap = normalize_fps_cap(fps_cap)
65
+ unless fps_cap_valid?(fps_cap)
66
+ raise Error, "fps_cap must be #{FPS_CAP_VALUES}, got #{fps_cap.inspect}"
67
+ end
36
68
  @fps_cap = fps_cap
37
- @fps = @fps_cap
38
-
39
- # Vertical synchronization, set to prevent screen tearing (recommended)
40
- @vsync = vsync
69
+ @fps = 0
41
70
 
42
71
  # Total number of frames that have been rendered
43
72
  @frames = 0
44
73
 
74
+ # Whether the frame loop is running, i.e. between `show` and the window
75
+ # closing. Frame-scoped work like `screenshot` needs an end-of-frame to
76
+ # land on, so it consults this rather than doing nothing at all.
77
+ @running = false
78
+
45
79
  # Renderable objects currently in the window, like a linear scene graph
46
80
  @objects = []
81
+ @object_set = {}
47
82
 
48
- _init_window_defaults
49
- _init_event_stores
50
- _init_event_registrations
51
- _init_procs_dsl_console
52
- end
53
-
54
- # Track open window state in a class instance variable
55
- @open_window = false
56
-
57
- # Class methods for convenient access to properties
58
- class << self
59
- def current
60
- get(:window)
61
- end
62
-
63
- def title
64
- get(:title)
65
- end
66
-
67
- def background
68
- get(:background)
69
- end
70
-
71
- def width
72
- get(:width)
73
- end
74
-
75
- def height
76
- get(:height)
77
- end
78
-
79
- def viewport_width
80
- get(:viewport_width)
81
- end
83
+ init_window_defaults
84
+ init_event_stores
85
+ init_event_registrations
86
+ init_procs_and_dsl
82
87
 
83
- def viewport_height
84
- get(:viewport_height)
85
- end
88
+ Ext.window_create(self)
86
89
 
87
- def display_width
88
- get(:display_width)
89
- end
90
-
91
- def display_height
92
- get(:display_height)
93
- end
94
-
95
- def resizable
96
- get(:resizable)
97
- end
98
-
99
- def borderless
100
- get(:borderless)
101
- end
102
-
103
- def fullscreen
104
- get(:fullscreen)
105
- end
106
-
107
- def highdpi
108
- get(:highdpi)
109
- end
110
-
111
- def frames
112
- get(:frames)
113
- end
114
-
115
- def fps
116
- get(:fps)
117
- end
118
-
119
- def fps_cap
120
- get(:fps_cap)
121
- end
122
-
123
- def mouse_x
124
- get(:mouse_x)
125
- end
126
-
127
- def mouse_y
128
- get(:mouse_y)
129
- end
90
+ Ruby2D::DSL.window = self
91
+ end
130
92
 
131
- def diagnostics
132
- get(:diagnostics)
133
- end
93
+ # Track window shown state in a class instance variable
94
+ @shown = false
134
95
 
135
- def screenshot(opts = nil)
136
- get(:screenshot, opts)
137
- end
138
-
139
- def get(sym, opts = nil)
140
- DSL.window.get(sym, opts)
141
- end
96
+ class << self
97
+ attr_reader :shown
98
+ alias_method :shown?, :shown
142
99
 
143
- def set(opts)
144
- DSL.window.set(opts)
145
- end
100
+ attr_writer :shown
101
+ end
146
102
 
147
- def on(event, &proc)
148
- DSL.window.on(event, &proc)
149
- end
103
+ def display_width
104
+ Ext.window_get_display_dimensions(self)
105
+ @display_width
106
+ end
150
107
 
151
- def off(event_descriptor)
152
- DSL.window.off(event_descriptor)
153
- end
108
+ def display_height
109
+ Ext.window_get_display_dimensions(self)
110
+ @display_height
111
+ end
154
112
 
155
- def add(object)
156
- DSL.window.add(object)
157
- end
113
+ def display_pixel_width
114
+ Ext.window_get_display_dimensions(self)
115
+ @display_pixel_width
116
+ end
158
117
 
159
- def remove(object)
160
- DSL.window.remove(object)
161
- end
118
+ def display_pixel_height
119
+ Ext.window_get_display_dimensions(self)
120
+ @display_pixel_height
121
+ end
162
122
 
163
- def clear
164
- DSL.window.clear
123
+ # Get a window attribute by name. `:window` returns the Window itself (the
124
+ # DSL escape hatch to the full API); any other symbol reads that attribute.
125
+ def get(sym)
126
+ case sym
127
+ when :window then self
128
+ else public_send(sym)
165
129
  end
130
+ end
166
131
 
167
- def update(&proc)
168
- DSL.window.update(&proc)
169
- end
132
+ # Set window attributes
133
+ def set(opts)
134
+ # Store new window attributes, or ignore if nil
135
+ set_any_window_properties opts
136
+ set_any_window_dimensions opts
170
137
 
171
- def render(&proc)
172
- DSL.window.render(&proc)
173
- end
138
+ Ext.window_set_size(self) if Window.shown? && (opts[:width] || opts[:height])
174
139
 
175
- def show
176
- DSL.window.show
140
+ if Window.shown? && (opts[:viewport] || opts[:viewport_width] || opts[:viewport_height] || !opts[:pixel_scale].nil?)
141
+ Ext.window_set_viewport_mode(self)
177
142
  end
178
143
 
179
- def close
180
- DSL.window.close
144
+ if opts.key?(:fps_cap)
145
+ cap = normalize_fps_cap(opts[:fps_cap])
146
+ if fps_cap_valid?(cap)
147
+ @fps_cap = cap
148
+ else
149
+ Ruby2D.warn "fps_cap must be #{FPS_CAP_VALUES}, got #{opts[:fps_cap].inspect}; ignoring (no cap)."
150
+ @fps_cap = nil
151
+ end
152
+ Ext.window_set_fps_cap(self, @fps_cap) if Window.shown?
181
153
  end
182
154
 
183
- def render_ready_check
184
- return if opened?
185
-
186
- raise Error,
187
- 'Attempting to draw before the window is ready. Please put calls to draw() inside of a render block.'
155
+ unless opts[:render_mode].nil?
156
+ unless %i[continuous on_demand].include?(opts[:render_mode])
157
+ raise Error, "`render_mode` must be :continuous or :on_demand, got #{opts[:render_mode].inspect}"
158
+ end
159
+ @render_mode = opts[:render_mode]
160
+ Ext.window_set_render_mode(self) if Window.shown?
188
161
  end
189
162
 
190
- def opened?
191
- @open_window
192
- end
163
+ @close_on_esc = opts[:close_on_esc] unless opts[:close_on_esc].nil?
193
164
 
194
- private
165
+ self.cursor = opts[:cursor] unless opts[:cursor].nil?
195
166
 
196
- def opened!
197
- @open_window = true
167
+ unless opts[:show_fps].nil?
168
+ @show_fps = opts[:show_fps]
169
+ Ext.window_show_fps(self, @show_fps)
198
170
  end
199
- end
200
-
201
- # Public instance methods
202
171
 
203
- # --- start exception
204
- # Exception from lint check for the #get method which is what it is. :)
205
- #
206
- # rubocop:disable Metrics/CyclomaticComplexity
207
- # rubocop:disable Metrics/AbcSize
208
-
209
- # Retrieve an attribute of the window
210
- # @param sym [Symbol] The name of an attribute to retrieve.
211
- def get(sym, opts = nil)
212
- case sym
213
- when :window then self
214
- when :title then @title
215
- when :background then @background
216
- when :width then @width
217
- when :height then @height
218
- when :viewport_width then @viewport_width
219
- when :viewport_height then @viewport_height
220
- when :display_width, :display_height
221
- ext_get_display_dimensions
222
- if sym == :display_width
223
- @display_width
224
- else
225
- @display_height
226
- end
227
- when :resizable then @resizable
228
- when :borderless then @borderless
229
- when :fullscreen then @fullscreen
230
- when :highdpi then @highdpi
231
- when :frames then @frames
232
- when :fps then @fps
233
- when :fps_cap then @fps_cap
234
- when :mouse_x then @mouse_x
235
- when :mouse_y then @mouse_y
236
- when :diagnostics then @diagnostics
237
- when :screenshot then screenshot(opts)
172
+ unless opts[:diagnostics].nil?
173
+ @diagnostics = opts[:diagnostics]
174
+ Ext.window_diagnostics(self, @diagnostics)
238
175
  end
239
176
  end
240
- # rubocop:enable Metrics/CyclomaticComplexity
241
- # rubocop:enable Metrics/AbcSize
242
- # --- end exception
243
-
244
- # Set a window attribute
245
- # @param opts [Hash] The attributes to set
246
- # @option opts [Color] :background
247
- # @option opts [String] :title
248
- # @option opts [Numeric] :width
249
- # @option opts [Numeric] :height
250
- # @option opts [Numeric] :viewport_width
251
- # @option opts [Numeric] :viewport_height
252
- # @option opts [Boolean] :highdpi
253
- # @option opts [Boolean] :resizable
254
- # @option opts [Boolean] :borderless
255
- # @option opts [Boolean] :fullscreen
256
- # @option opts [Numeric] :fps_cap
257
- # @option opts [Numeric] :diagnostics
258
- def set(opts)
259
- # Store new window attributes, or ignore if nil
260
- _set_any_window_properties opts
261
- _set_any_window_dimensions opts
262
-
263
- @fps_cap = opts[:fps_cap] if opts[:fps_cap]
264
- return if opts[:diagnostics].nil?
265
-
266
- @diagnostics = opts[:diagnostics]
267
- ext_diagnostics(@diagnostics)
268
- end
269
177
 
270
178
  # Add an object to the window
271
179
  def add(object)
272
180
  case object
273
181
  when nil
274
- raise Error, "Cannot add '#{object.class}' to window!"
182
+ raise Error, "Cannot add `#{object.class}` to window!"
275
183
  when Array
276
184
  object.each { |x| add_object(x) }
277
185
  else
@@ -281,425 +189,556 @@ module Ruby2D
281
189
 
282
190
  # Remove an object from the window
283
191
  def remove(object)
284
- raise Error, "Cannot remove '#{object.class}' from window!" if object.nil?
192
+ raise Error, "Cannot remove `#{object.class}` from window!" if object.nil?
193
+ return false unless @objects.delete(object)
285
194
 
286
- ix = @objects.index(object)
287
- return false if ix.nil?
288
-
289
- @objects.delete_at(ix)
195
+ @object_set.delete(object)
196
+ unregister_interactive(object)
290
197
  true
291
198
  end
292
199
 
293
200
  # Clear all objects from the window
294
201
  def clear
295
202
  @objects.clear
203
+ @object_set.clear
204
+ init_object_event_stores
296
205
  end
297
206
 
298
207
  # Set the update callback
299
208
  def update(&proc)
209
+ raise Error, '`update` requires a block' unless proc
300
210
  @update_proc = proc
211
+ # Cache whether the block takes a delta-time arg; the arity never changes
212
+ # after assignment, so the per-frame loop reads this instead of recomputing.
213
+ @update_wants_dt = !proc.arity.zero?
301
214
  true
302
215
  end
303
216
 
304
- # Set the render callback
305
- def render(&proc)
217
+ # Set the render callback. `z:` places the block in the scene's z-order:
218
+ # `:foreground` (default) draws it on top of every object, `:background`
219
+ # behind them, or a number interleaves it at that depth on the same scale
220
+ # as object `z` (objects with `z` at or below it draw first, then the
221
+ # block, then the rest).
222
+ def render(z: :foreground, &proc)
223
+ raise Error, '`render` requires a block' unless proc
306
224
  @render_proc = proc
225
+ @render_z = render_z_for(z)
307
226
  true
308
227
  end
309
228
 
310
- # Generate a new event key (ID)
311
- def new_event_key
312
- @event_key = @event_key.next
229
+ # Monotonic seconds since engine start — a cross-platform, overflow-safe
230
+ # clock for cooldowns, scheduling, and "time since" math. Unlike `Time.now`
231
+ # it never jumps or jitters, and reads the same on CRuby and mruby/web.
232
+ # For per-frame motion, prefer the `dt` argument to `update`.
233
+ def elapsed
234
+ Ext.now
235
+ end
236
+
237
+ # Maps event types to the predicate used in the kwarg form of `on` —
238
+ # e.g. `on key_down: :escape` filters via `event.key?(:escape)`. For
239
+ # gamepad events the entries map to the *primary* predicate (the one a
240
+ # bare scalar matcher targets); hash matchers like
241
+ # `{ gamepad: pad1, button: :south }` derive the predicate from each key.
242
+ EVENT_FILTER_PREDICATES = {
243
+ key_down: :key?, key_held: :key?, key_up: :key?,
244
+ mouse_down: :button?, mouse_held: :button?, mouse_up: :button?,
245
+ gamepad_button_down: :button?, gamepad_button_held: :button?,
246
+ gamepad_button_up: :button?, gamepad_axis: :axis?
247
+ }.freeze
248
+
249
+ # Gamepad events dispatch an internal data struct, but user blocks
250
+ # receive the unpacked args (gamepad / button / axis / value). This map
251
+ # describes the unpack for each gamepad event type.
252
+ GAMEPAD_EVENT_UNPACK = {
253
+ gamepad_connect: ->(d) { [d.gamepad] },
254
+ gamepad_disconnect: ->(d) { [d.gamepad] },
255
+ gamepad_button_down: ->(d) { [d.gamepad, d.button] },
256
+ gamepad_button_held: ->(d) { [d.gamepad, d.button] },
257
+ gamepad_button_up: ->(d) { [d.gamepad, d.button] },
258
+ gamepad_axis: ->(d) { [d.gamepad, d.axis, d.value] }
259
+ }.freeze
260
+
261
+ # Set an event handler. Forms:
262
+ #
263
+ # on(:key_down) { |event| ... } # all events of type
264
+ # on(key_down: :escape) { ... } # filtered by value
265
+ # on(key_down: [:left, :a]) { ... } # array → match any
266
+ # on(key_down: :left, gamepad_button_down: :dpad_left) { } # multi-event
267
+ # on(gamepad_button_down: { gamepad: pad1, button: :south }) # hash → AND match
268
+ def on(event = nil, **filters, &proc)
269
+ raise Error, '`on` requires a block' unless proc
270
+ if event.is_a?(Symbol) && filters.empty?
271
+ register_event_handler(event, wrap_for_event(event, proc))
272
+ elsif event.nil? && !filters.empty?
273
+ descriptors = filters.map do |type, matcher|
274
+ register_event_handler(type, build_filter_wrapper(type, matcher, proc))
275
+ end
276
+ descriptors.size == 1 ? descriptors.first : descriptors
277
+ else
278
+ raise Error, '`on` requires either an event symbol or event filters'
279
+ end
313
280
  end
314
281
 
315
- # Set an event handler
316
- def on(event, &proc)
282
+ private def register_event_handler(event, proc)
317
283
  raise Error, "`#{event}` is not a valid event type" unless @events.key? event
318
284
 
285
+ # Only one close handler is allowed; registering a new one replaces the old
286
+ @events[:close].clear if event == :close
287
+
319
288
  event_id = new_event_key
320
289
  @events[event][event_id] = proc
321
290
  EventDescriptor.new(event, event_id)
322
291
  end
323
292
 
324
- # Remove an event handler
325
- def off(event_descriptor)
326
- @events[event_descriptor.type].delete(event_descriptor.id)
327
- end
293
+ # Wrap a user proc for direct (no-filter) registration. Gamepad events
294
+ # unpack the dispatch struct into multi-arg form; everything else passes
295
+ # the event struct straight through.
296
+ private def wrap_for_event(type, proc)
297
+ unpack = GAMEPAD_EVENT_UNPACK[type]
298
+ return proc unless unpack
328
299
 
329
- # Key down event method for class pattern
330
- def key_down(key)
331
- @keys_down.include? key
300
+ ->(d) { proc.call(*unpack.call(d)) }
332
301
  end
333
302
 
334
- # Key held event method for class pattern
335
- def key_held(key)
336
- @keys_held.include? key
337
- end
303
+ # Wrap a user proc with a filter matcher. Hash matchers AND every
304
+ # `key?(value)` predicate; scalar/array matchers fall through to the
305
+ # event type's primary predicate. Gamepad event handlers also unpack
306
+ # the dispatch struct into multi-arg form.
307
+ private def build_filter_wrapper(type, matcher, proc)
308
+ unpack = GAMEPAD_EVENT_UNPACK[type]
309
+ args = unpack ? ->(e) { unpack.call(e) } : ->(e) { [e] }
338
310
 
339
- # Key up event method for class pattern
340
- def key_up(key)
341
- @keys_up.include? key
311
+ if matcher.is_a?(Hash)
312
+ unless unpack
313
+ raise Error, "`#{type}` does not support hash filters with `on event: { ... }`"
314
+ end
315
+ ->(e) {
316
+ if matcher.all? { |k, v| e.send(:"#{k}?", v) }
317
+ proc.call(*args.call(e))
318
+ end
319
+ }
320
+ else
321
+ predicate = EVENT_FILTER_PREDICATES[type] or
322
+ raise Error, "`#{type}` does not support filtering with `on event: value`"
323
+ values = Array(matcher)
324
+ ->(e) {
325
+ if values.any? { |v| e.send(predicate, v) }
326
+ proc.call(*args.call(e))
327
+ end
328
+ }
329
+ end
342
330
  end
343
331
 
344
- # Key callback method, called by the native and web extentions
345
- def key_callback(type, key)
346
- key = key.downcase
332
+ # Remove an event handler (or several). Accepts a descriptor returned by
333
+ # `on`, or an array of them (as `on` returns when given multiple filters).
334
+ def off(event_descriptor)
335
+ return event_descriptor.each { |d| off(d) } if event_descriptor.is_a?(Array)
347
336
 
348
- # All key events
349
- @events[:key].each do |_id, e|
350
- e.call(KeyEvent.new(type, key))
337
+ case event_descriptor
338
+ when ObjectEventDescriptor
339
+ event_descriptor.object.off(event_descriptor)
340
+ when EventDescriptor
341
+ @events[event_descriptor.type].delete(event_descriptor.id)
342
+ else
343
+ raise Error,
344
+ "Cannot remove event handler: expected a descriptor returned by `on`, got #{event_descriptor.inspect}"
351
345
  end
346
+ end
352
347
 
353
- case type
354
- # When key is pressed, fired once
355
- when :down
356
- _handle_key_down type, key
357
- # When key is being held down, fired every frame
358
- when :held
359
- _handle_key_held type, key
360
- # When key released, fired once
361
- when :up
362
- _handle_key_up type, key
348
+ # Update callback method, called by the native and web extentions
349
+ def update_callback
350
+ # Monotonic seconds since the previous update. Clamped to 0.1s so a paused
351
+ # window or stalled frame doesn't teleport the simulation when updates
352
+ # resume; zero on the first frame. `Ext.now` (SDL_GetTicksNS, and
353
+ # performance.now on web) is the single clock used on every runtime — the
354
+ # same source as the public `elapsed`. A wall clock like Time.now would
355
+ # jitter and stutter dt-scaled motion.
356
+ now = Ext.now
357
+ if @last_update_time
358
+ dt = now - @last_update_time
359
+ @delta_time = dt > 0.1 ? 0.1 : dt
360
+ else
361
+ @delta_time = 0.0
363
362
  end
364
- end
363
+ @last_update_time = now
365
364
 
366
- # Mouse down event method for class pattern
367
- def mouse_down(btn)
368
- @mouse_buttons_down.include? btn
369
- end
365
+ update if @overrides_update
370
366
 
371
- # Mouse up event method for class pattern
372
- def mouse_up(btn)
373
- @mouse_buttons_up.include? btn
367
+ if @update_wants_dt
368
+ @update_proc.call(@delta_time)
369
+ else
370
+ @update_proc.call
371
+ end
372
+
373
+ # Frame-scoped polling state (pressed/released, axes_moved, scroll/move
374
+ # flags) lives one frame and is cleared here every tick — independent of
375
+ # whether the user is on the DSL or class pattern, so both can poll.
376
+ clear_event_stores
377
+ end
378
+
379
+ # Iterate the z-sorted scene graph and render each visible object, splicing
380
+ # the user's render block into the same z-order at `@render_z`: objects with
381
+ # `z` at or below it draw first, then the block, then the rest. The default
382
+ # `:foreground` (+∞) draws the block last, on top of everything; `:background`
383
+ # (-∞) draws it first. Called from the native extension once per frame via
384
+ # `tick`. Each object draws via its zero-arg `_render_scene` hook, not the
385
+ # public keyword `render`: on wasm mruby a zero-arg call into a
386
+ # keyword-heavy method still pays ~5µs of keyword setup, so 100 sprites
387
+ # would burn half a millisecond per frame on pure dispatch.
388
+ def render_objects
389
+ # Fast paths for the symbolic block positions: with the block pinned at
390
+ # +∞ (`:foreground`, the default) or -∞ (`:background`) no object can
391
+ # ever sort after (resp. before) it, so the per-object `z` read and
392
+ # compare in the interleaving loop below could never fire — skip them.
393
+ if @render_z == Float::INFINITY
394
+ @objects.each { |obj| obj._render_scene if obj.visible? }
395
+ render_callback
396
+ elsif @render_z == -Float::INFINITY
397
+ render_callback
398
+ @objects.each { |obj| obj._render_scene if obj.visible? }
399
+ else
400
+ block_drawn = false
401
+ @objects.each do |obj|
402
+ if !block_drawn && obj.z > @render_z
403
+ render_callback
404
+ block_drawn = true
405
+ end
406
+ obj._render_scene if obj.visible?
407
+ end
408
+ render_callback unless block_drawn
409
+ end
374
410
  end
375
411
 
376
- # Mouse scroll event method for class pattern
377
- def mouse_scroll
378
- @mouse_scroll_event
379
- end
412
+ # Run the user's render block (and the overridden `render` method under the
413
+ # class pattern). Spliced into the scene by `render_objects`.
414
+ def render_callback
415
+ render if @overrides_render
380
416
 
381
- # Mouse move event method for class pattern
382
- def mouse_move
383
- @mouse_move_event
417
+ @render_proc.call
384
418
  end
385
419
 
386
- # Mouse callback method, called by the native and web extentions
387
- def mouse_callback(type, button, direction, x, y, delta_x, delta_y)
388
- # All mouse events
389
- @events[:mouse].each do |_id, e|
390
- e.call(MouseEvent.new(type, button, direction, x, y, delta_x, delta_y))
391
- end
392
-
393
- case type
394
- # When mouse button pressed
395
- when :down
396
- _handle_mouse_down type, button, x, y
397
- # When mouse button released
398
- when :up
399
- _handle_mouse_up type, button, x, y
400
- # When mouse motion / movement
401
- when :scroll
402
- _handle_mouse_scroll type, direction, delta_x, delta_y
403
- # When mouse scrolling, wheel or trackpad
404
- when :move
405
- _handle_mouse_move type, x, y, delta_x, delta_y
406
- end
420
+ # Close callback method, called by the native extension
421
+ def close_callback
422
+ @events[:close].each_value(&:call)
407
423
  end
408
424
 
409
- # Add controller mappings from file
410
- def add_controller_mappings
411
- ext_add_controller_mappings(@controller_mappings) if File.exist? @controller_mappings
412
- end
425
+ # One frame: poll events, update, render.
426
+ def tick
427
+ Ext.poll_events(self)
428
+ # drain_events returns nil (not an empty array) on event-less frames
429
+ raw = Ext.drain_events(self)
430
+ dispatch_events(raw) if raw
413
431
 
414
- # Controller axis event method for class pattern
415
- def controller_axis(axis)
416
- @controller_axes_moved.include? axis
417
- end
432
+ update_callback
418
433
 
419
- # Controller button down event method for class pattern
420
- def controller_button_down(btn)
421
- @controller_buttons_down.include? btn
422
- end
434
+ if Ext.begin_frame(self)
435
+ render_objects
436
+ end
423
437
 
424
- # Controller button up event method for class pattern
425
- def controller_button_up(btn)
426
- @controller_buttons_up.include? btn
438
+ Ext.end_frame(self)
427
439
  end
428
440
 
429
- # Controller callback method, called by the native and web extentions
430
- def controller_callback(which, type, axis, value, button)
431
- # All controller events
432
- @events[:controller].each do |_id, e|
433
- e.call(ControllerEvent.new(which, type, axis, value, button))
441
+ # Show the window
442
+ def show
443
+ raise Error, 'Window#show called multiple times; Ruby 2D supports a single window per process' if Window.shown?
444
+
445
+ @close = false
446
+ load_default_gamepad_mappings
447
+
448
+ if RUBY_ENGINE == 'ruby'
449
+ # CRuby: window_show creates the window and returns — Ruby owns the loop.
450
+ # Mark shown only after it succeeds; on failure it raises, so shown? stays
451
+ # false and no frame dereferences a NULL renderer.
452
+ Ext.window_show(self)
453
+ Window.shown = true
454
+ @running = true
455
+ tick until @close
456
+ else
457
+ # mruby/WASM: window_show creates the window AND runs the loop, blocking
458
+ # until close. Mark shown first so live updates (request_render, set title,
459
+ # etc.) work during the run; a creation failure raises before the loop.
460
+ Window.shown = true
461
+ @running = true
462
+ Ext.window_show(self)
434
463
  end
435
464
 
436
- case type
437
- # When controller axis motion, like analog sticks
438
- when :axis
439
- _handle_controller_axis which, axis, value
440
- # When controller button is pressed
441
- when :button_down
442
- _handle_controller_button_down which, button
443
- # When controller button is released
444
- when :button_up
445
- _handle_controller_button_up which, button
446
- end
465
+ @running = false
447
466
  end
448
467
 
449
- # Update callback method, called by the native and web extentions
450
- def update_callback
451
- update unless @using_dsl
452
-
453
- @update_proc.call
454
-
455
- # Accept and eval commands if in console mode
456
- _handle_console_input if @console && $stdin.ready?
457
-
458
- # Clear inputs if using class pattern
459
- _clear_event_stores unless @using_dsl
460
- end
468
+ # Take a screenshot, saving to `path` (or a timestamped file if omitted).
469
+ #
470
+ # The write is deferred to the end of the current frame, after the scene is
471
+ # drawn but before it is presented, so the capture is this frame rather than
472
+ # the last one. `path` therefore comes back before the file exists; it lands
473
+ # by the time the next `update` runs. Requesting one also forces the frame to
474
+ # render, so a capture in `:on_demand` mode never grabs a parked frame, and
475
+ # capturing and closing in the same tick still writes the file.
476
+ #
477
+ # A closed window has no end-of-frame left to write on, so that raises rather
478
+ # than returning a path to a file that will never appear.
479
+ #
480
+ # A no-op on the web, returning nil: the only filesystem there is Emscripten's
481
+ # in-memory one, so a capture would cost a framebuffer read and a PNG encode
482
+ # to produce a file nobody can open, and that vanishes on reload.
483
+ def screenshot(path = nil)
484
+ return if Ruby2D.web?
461
485
 
462
- # Render callback method, called by the native and web extentions
463
- def render_callback
464
- render unless @using_dsl
486
+ if Window.shown? && !@running
487
+ raise Error, '`screenshot` called after the window closed; the file is ' \
488
+ 'written at the end of a frame, so nothing would be saved'
489
+ end
465
490
 
466
- @render_proc.call
491
+ path ||= "./screenshot-#{Time.now.utc.strftime('%Y-%m-%d--%H-%M-%S')}.png"
492
+ Ext.window_screenshot(self, path)
467
493
  end
468
494
 
469
- # Show the window
470
- def show
471
- raise Error, 'Window#show called multiple times, Ruby2D only supports a single open window' if Window.opened?
495
+ # Get the current cursor state
496
+ def cursor
497
+ return :hidden unless Ext.window_cursor_visible(self)
472
498
 
473
- Window.send(:opened!)
474
- ext_show
499
+ @cursor_style || :default
475
500
  end
476
501
 
477
- # Take screenshot
478
- def screenshot(path)
479
- if path
480
- ext_screenshot(path)
502
+ # Set the cursor: `:visible`, `:hidden`, or a system cursor name
503
+ def cursor=(name)
504
+ case name
505
+ when :visible
506
+ @cursor_style = :default
507
+ Ext.window_show_cursor(self)
508
+ when :hidden
509
+ @cursor_style = nil
510
+ Ext.window_hide_cursor(self)
481
511
  else
482
- time = if RUBY_ENGINE == 'ruby'
483
- Time.now.utc.strftime '%Y-%m-%d--%H-%M-%S'
484
- else
485
- Time.now.utc.to_i
486
- end
487
- ext_screenshot("./screenshot-#{time}.png")
512
+ name = name.to_sym
513
+ @cursor_style = name
514
+ Ext.window_set_system_cursor(self, name.to_s)
488
515
  end
489
516
  end
490
517
 
491
- # Close the window
518
+ # Close the window. A no-op on the web, where a page can't close itself —
519
+ # only the person viewing it can — so there's nothing to shut down: the
520
+ # `:close` handler doesn't fire, the window isn't marked closed, and the
521
+ # loop keeps running. The user's own quit still arrives as a `:close`
522
+ # event, which is handled in the event loop rather than here.
492
523
  def close
493
- ext_close
494
- end
495
-
496
- # Private instance methods
497
-
498
- private
524
+ return if Ruby2D.web?
499
525
 
500
- # An an object to the window, used by the public `add` method
501
- def add_object(object)
502
- if !@objects.include?(object)
503
- index = @objects.index do |obj|
504
- obj.z > object.z
505
- end
506
- if index
507
- @objects.insert(index, object)
508
- else
509
- @objects.push(object)
510
- end
511
- true
512
- else
513
- false
514
- end
526
+ close_callback
527
+ Ext.window_close(self)
528
+ @close = true
515
529
  end
516
530
 
517
- def _set_any_window_properties(opts)
518
- @background = Color.new(opts[:background]) if Color.valid? opts[:background]
519
- @title = opts[:title] if opts[:title]
520
- @icon = opts[:icon] if opts[:icon]
521
- @resizable = opts[:resizable] if opts[:resizable]
522
- @borderless = opts[:borderless] if opts[:borderless]
523
- @fullscreen = opts[:fullscreen] if opts[:fullscreen]
531
+ # Request that the next tick render a frame. No-op in :continuous mode.
532
+ # Safe to call from any thread.
533
+ def request_render
534
+ Ext.window_request_render(self) if Window.shown?
524
535
  end
525
536
 
526
- def _set_any_window_dimensions(opts)
527
- @width = opts[:width] if opts[:width]
528
- @height = opts[:height] if opts[:height]
529
- @viewport_width = opts[:viewport_width] if opts[:viewport_width]
530
- @viewport_height = opts[:viewport_height] if opts[:viewport_height]
531
- @highdpi = opts[:highdpi] unless opts[:highdpi].nil?
532
- end
537
+ # Private instance methods
533
538
 
534
- def _handle_key_down(type, key)
535
- # For class pattern
536
- @keys_down << key if !@using_dsl && !(@keys_down.include? key)
539
+ private
537
540
 
538
- # Call event handler
539
- @events[:key_down].each do |_id, e|
540
- e.call(KeyEvent.new(type, key))
541
+ # Resolve a render-block `z:` to a numeric depth. `:foreground` puts the
542
+ # block on top of every object, `:background` behind them; a number places
543
+ # it at that depth on the same scale as object `z`.
544
+ def render_z_for(z)
545
+ case z
546
+ when :foreground then Float::INFINITY
547
+ when :background then -Float::INFINITY
548
+ when Numeric then z
549
+ else
550
+ raise Error, "render `z:` must be a number, :foreground, or :background, got #{z.inspect}"
551
+ end
552
+ end
553
+
554
+ # Event buffer stride and category/type constants (match C-side defines)
555
+ EVT_STRIDE = 12
556
+ EVT_KEY = 1
557
+ EVT_MOUSE = 2
558
+ EVT_GAMEPAD = 3
559
+ EVT_CLOSE = 4
560
+
561
+ KEY_TYPE_MAP = { 1 => :down, 2 => :held, 3 => :up }.freeze
562
+ MOUSE_TYPE_MAP = { 1 => :down, 2 => :up, 3 => :scroll, 4 => :move,
563
+ 5 => :held, 6 => :enter, 7 => :leave }.freeze
564
+ MOUSE_BTN_MAP = { 1 => :left, 2 => :middle, 3 => :right, 4 => :x1, 5 => :x2 }.freeze
565
+ SCROLL_DIR_MAP = { 0 => :normal, 1 => :inverted }.freeze
566
+ GP_AXIS_MAP = { 0 => :left_x, 1 => :left_y, 2 => :right_x, 3 => :right_y,
567
+ 4 => :left_trigger, 5 => :right_trigger }.freeze
568
+ GP_BUTTON_MAP = { 0 => :south, 1 => :east, 2 => :west, 3 => :north,
569
+ 4 => :back, 5 => :guide, 6 => :start,
570
+ 7 => :left_stick, 8 => :right_stick,
571
+ 9 => :left_shoulder, 10 => :right_shoulder,
572
+ 11 => :dpad_up, 12 => :dpad_down,
573
+ 13 => :dpad_left, 14 => :dpad_right,
574
+ 15 => :misc1, 16 => :paddle1, 17 => :paddle2,
575
+ 18 => :paddle3, 19 => :paddle4, 20 => :touchpad,
576
+ 21 => :misc2, 22 => :misc3, 23 => :misc4,
577
+ 24 => :misc5, 25 => :misc6 }.freeze
578
+
579
+ def dispatch_events(raw)
580
+ i = 0
581
+ while i < raw.size
582
+ cat = raw[i]
583
+ case cat
584
+ when EVT_KEY
585
+ key_callback(KEY_TYPE_MAP[raw[i + 1]], key_name(raw[i + 2]))
586
+ when EVT_MOUSE
587
+ mouse_callback(
588
+ MOUSE_TYPE_MAP[raw[i + 1]], MOUSE_BTN_MAP[raw[i + 3]],
589
+ SCROLL_DIR_MAP[raw[i + 4]],
590
+ raw[i + 6], raw[i + 7], raw[i + 8], raw[i + 9]
591
+ )
592
+ when EVT_GAMEPAD
593
+ gp_type = raw[i + 1]
594
+ gp_id = raw[i + 2]
595
+ case gp_type
596
+ when 1 then gamepad_callback(gp_id, :connect, nil, nil, raw[i + 11])
597
+ when 2 then gamepad_callback(gp_id, :disconnect, nil, nil, nil)
598
+ when 3
599
+ axis_sym = GP_AXIS_MAP[raw[i + 5]]
600
+ raw_val = raw[i + 10]
601
+ value = raw_val > 0 ? raw_val / 32767.0 : raw_val / 32768.0
602
+ gamepad_callback(gp_id, :axis, axis_sym, value, nil)
603
+ when 4 then gamepad_callback(gp_id, :button_down, GP_BUTTON_MAP[raw[i + 3]], nil, nil)
604
+ when 5 then gamepad_callback(gp_id, :button_up, GP_BUTTON_MAP[raw[i + 3]], nil, nil)
605
+ when 6 then gamepad_callback(gp_id, :button_held, GP_BUTTON_MAP[raw[i + 3]], nil, nil)
606
+ end
607
+ when EVT_CLOSE
608
+ close_callback
609
+ Ext.window_close(self)
610
+ @close = true
611
+ end
612
+ i += EVT_STRIDE
541
613
  end
542
614
  end
543
615
 
544
- def _handle_key_held(type, key)
545
- # For class pattern
546
- @keys_held << key if !@using_dsl && !(@keys_held.include? key)
616
+ # Fire every handler registered for `type`, building a fresh event object
617
+ # per handler via the block (a handler may mutate the event it receives, so
618
+ # handlers don't share one). Skips the values-array allocation when no
619
+ # handlers are registered — the common case on per-event hot paths, where
620
+ # it costs ~1µs per empty event type on wasm mruby.
621
+ def fire_event_handlers(type)
622
+ handlers = @events[type]
623
+ return if handlers.empty?
547
624
 
548
- # Call event handler
549
- @events[:key_held].each do |_id, e|
550
- e.call(KeyEvent.new(type, key))
551
- end
625
+ handlers.values.each { |e| e.call(yield) }
552
626
  end
553
627
 
554
- def _handle_key_up(type, key)
555
- # For class pattern
556
- @keys_up << key if !@using_dsl && !(@keys_up.include? key)
557
-
558
- # Call event handler
559
- @events[:key_up].each do |_id, e|
560
- e.call(KeyEvent.new(type, key))
561
- end
628
+ # Resolve an SDL scancode to its cached, frozen, lowercased name. The
629
+ # held-key path sends only the integer scancode each frame; the name is
630
+ # looked up (and downcased + frozen) once per distinct key and reused, so
631
+ # no per-frame key-name string is allocated.
632
+ def key_name(code)
633
+ @key_names[code] ||= Ext.scancode_name(code).downcase.freeze
562
634
  end
563
635
 
564
- def _handle_mouse_down(type, button, x, y)
565
- # For class pattern
566
- @mouse_buttons_down << button if !@using_dsl && !(@mouse_buttons_down.include? button)
567
-
568
- # Call event handler
569
- @events[:mouse_down].each do |_id, e|
570
- e.call(MouseEvent.new(type, button, nil, x, y, nil, nil))
571
- end
636
+ # Generate a new event key (ID)
637
+ def new_event_key
638
+ @event_key += 1
572
639
  end
573
640
 
574
- def _handle_mouse_up(type, button, x, y)
575
- # For class pattern
576
- @mouse_buttons_up << button if !@using_dsl && !(@mouse_buttons_up.include? button)
641
+ # Add an object to the window, used by the public `add` method
642
+ def add_object(object)
643
+ return false if @object_set.key?(object)
577
644
 
578
- # Call event handler
579
- @events[:mouse_up].each do |_id, e|
580
- e.call(MouseEvent.new(type, button, nil, x, y, nil, nil))
581
- end
582
- end
645
+ index = @objects.bsearch_index { |obj| obj.z > object.z }
646
+ @objects.insert(index || @objects.size, object)
647
+ @object_set[object] = true
583
648
 
584
- def _handle_mouse_scroll(type, direction, delta_x, delta_y)
585
- # For class pattern
586
- unless @using_dsl
587
- @mouse_scroll_event = true
588
- @mouse_scroll_direction = direction
589
- @mouse_scroll_delta_x = delta_x
590
- @mouse_scroll_delta_y = delta_y
649
+ # Re-register for correct z-order if the object is interactive
650
+ if object.respond_to?(:interactive?) && object.interactive?
651
+ @interactive_objects.delete(object)
652
+ register_interactive(object)
591
653
  end
592
654
 
593
- # Call event handler
594
- @events[:mouse_scroll].each do |_id, e|
595
- e.call(MouseEvent.new(type, nil, direction, nil, nil, delta_x, delta_y))
596
- end
655
+ true
597
656
  end
598
657
 
599
- def _handle_mouse_move(type, x, y, delta_x, delta_y)
600
- # For class pattern
601
- unless @using_dsl
602
- @mouse_move_event = true
603
- @mouse_move_delta_x = delta_x
604
- @mouse_move_delta_y = delta_y
658
+ def set_any_window_properties(opts)
659
+ @background = Color.new(opts[:background]) if Color.valid? opts[:background]
660
+ if opts[:title]
661
+ @title = opts[:title]
662
+ Ext.window_set_title(self) if Window.shown?
605
663
  end
606
-
607
- # Call event handler
608
- @events[:mouse_move].each do |_id, e|
609
- e.call(MouseEvent.new(type, nil, nil, x, y, delta_x, delta_y))
664
+ if opts[:icon]
665
+ @icon = opts[:icon]
666
+ Ext.window_set_icon(self) if Window.shown?
610
667
  end
611
- end
612
-
613
- def _handle_controller_axis(which, axis, value)
614
- # For class pattern
615
- unless @using_dsl
616
- @controller_id = which
617
- @controller_axes_moved << axis unless @controller_axes_moved.include? axis
618
- _set_controller_axis_value axis, value
619
- end
620
-
621
- # Call event handler
622
- @events[:controller_axis].each do |_id, e|
623
- e.call(ControllerAxisEvent.new(which, axis, value))
668
+ unless opts[:resizable].nil?
669
+ @resizable = opts[:resizable]
670
+ Ext.window_set_resizable(self) if Window.shown?
624
671
  end
625
672
  end
626
673
 
627
- def _set_controller_axis_value(axis, value)
628
- case axis
629
- when :left_x
630
- @controller_axis_left_x = value
631
- when :left_y
632
- @controller_axis_left_y = value
633
- when :right_x
634
- @controller_axis_right_x = value
635
- when :right_y
636
- @controller_axis_right_y = value
674
+ def set_any_window_dimensions(opts)
675
+ # Before `show`, the viewport auto-follows width/height (its documented
676
+ # default of "same as width/height"). After `show`, a bare `set width:` is
677
+ # a live resize: leave the fixed logical viewport alone so it letterboxes
678
+ # into the new window size instead of being silently overwritten. Only
679
+ # `:expand` tracks the window on resize, and that is handled C-side.
680
+ if opts[:width]
681
+ @width = opts[:width]
682
+ @viewport_width = @width unless opts[:viewport_width] || Window.shown?
637
683
  end
638
- end
639
-
640
- def _handle_controller_button_down(which, button)
641
- # For class pattern
642
- unless @using_dsl
643
- @controller_id = which
644
- @controller_buttons_down << button unless @controller_buttons_down.include? button
684
+ if opts[:height]
685
+ @height = opts[:height]
686
+ @viewport_height = @height unless opts[:viewport_height] || Window.shown?
645
687
  end
646
-
647
- # Call event handler
648
- @events[:controller_button_down].each do |_id, e|
649
- e.call(ControllerButtonEvent.new(which, button))
688
+ @viewport_width = opts[:viewport_width] if opts[:viewport_width]
689
+ @viewport_height = opts[:viewport_height] if opts[:viewport_height]
690
+ if opts[:viewport]
691
+ unless VIEWPORT_MODES.include?(opts[:viewport])
692
+ raise Error, "Invalid viewport mode #{opts[:viewport].inspect}; expected one of #{VIEWPORT_MODES.inspect}"
693
+ end
694
+ @viewport_mode = opts[:viewport]
695
+ end
696
+ # highdpi is baked into the native window at creation and re-read once at
697
+ # `show`; it cannot change afterward. Keep the reader honest — never mutate
698
+ # @highdpi post-show — and warn only when the call would actually differ.
699
+ unless opts[:highdpi].nil?
700
+ if Window.shown?
701
+ if opts[:highdpi] != @highdpi
702
+ Ruby2D.warn 'highdpi is fixed when the window is created and cannot change after `show`; ignoring.'
703
+ end
704
+ else
705
+ @highdpi = opts[:highdpi]
706
+ end
650
707
  end
708
+ @pixel_scale = opts[:pixel_scale] unless opts[:pixel_scale].nil?
651
709
  end
652
710
 
653
- def _handle_controller_button_up(which, button)
654
- # For class pattern
655
- unless @using_dsl
656
- @controller_id = which
657
- @controller_buttons_up << button unless @controller_buttons_up.include? button
658
- end
659
-
660
- # Call event handler
661
- @events[:controller_button_up].each do |_id, e|
662
- e.call(ControllerButtonEvent.new(which, button))
663
- end
711
+ # The symbol :infinity is an ergonomic alias for Float::INFINITY (uncapped);
712
+ # normalize it so the rest of the pipeline only sees nil / number / INFINITY.
713
+ def normalize_fps_cap(value)
714
+ value == :infinity ? Float::INFINITY : value
664
715
  end
665
716
 
666
- # --- start exception
667
- # Exception from lint check for this method only
668
- #
669
- # rubocop:disable Lint/RescueException
670
- # rubocop:disable Security/Eval
671
- def _handle_console_input
672
- cmd = $stdin.gets
673
- begin
674
- res = eval(cmd, TOPLEVEL_BINDING)
675
- $stdout.puts "=> #{res.inspect}"
676
- $stdout.flush
677
- rescue SyntaxError => e
678
- $stdout.puts e
679
- $stdout.flush
680
- rescue Exception => e
681
- $stdout.puts e
682
- $stdout.flush
683
- end
717
+ # A valid (normalized) fps_cap is nil (no cap) or a positive number —
718
+ # including Float::INFINITY, which is positive. 0, negatives, NaN, and other
719
+ # types are rejected.
720
+ def fps_cap_valid?(value)
721
+ value.nil? || (value.is_a?(Numeric) && value > 0)
684
722
  end
685
- # rubocop:enable Lint/RescueException
686
- # rubocop:enable Security/Eval
687
- # ---- end exception
688
723
 
689
- def _clear_event_stores
724
+ def clear_event_stores
690
725
  @keys_down.clear
691
726
  @keys_held.clear
692
727
  @keys_up.clear
693
728
  @mouse_buttons_down.clear
694
729
  @mouse_buttons_up.clear
695
- @mouse_scroll_event = false
696
- @mouse_move_event = false
697
- @controller_axes_moved.clear
698
- @controller_buttons_down.clear
699
- @controller_buttons_up.clear
730
+ @mouse_buttons_held.clear
731
+ @mouse_scroll_event = false
732
+ @mouse_scroll_direction = nil
733
+ @mouse_scroll_delta_x = 0
734
+ @mouse_scroll_delta_y = 0
735
+ @mouse_move_event = false
736
+ @mouse_move_delta_x = 0
737
+ @mouse_move_delta_y = 0
738
+ clear_gamepad_frame_state
700
739
  end
701
740
 
702
- def _init_window_defaults
741
+ def init_window_defaults
703
742
  # Window background color
704
743
  @background = Color.new([0.0, 0.0, 0.0, 1.0])
705
744
 
@@ -708,63 +747,39 @@ module Ruby2D
708
747
 
709
748
  # Window characteristics
710
749
  @resizable = false
711
- @borderless = false
712
- @fullscreen = false
713
- @highdpi = false
750
+ @highdpi = true
751
+ @pixel_scale = false
714
752
 
715
753
  # Size of the window's viewport (the drawable area)
716
- @viewport_width = nil
717
- @viewport_height = nil
754
+ @viewport_width = @width
755
+ @viewport_height = @height
756
+
757
+ # Viewport scaling mode for resizable windows
758
+ @viewport_mode = :letterbox
759
+
760
+ # Render mode: :continuous renders every tick up to fps_cap; :on_demand
761
+ # only renders when request_render is called or the OS signals a redraw.
762
+ @render_mode = :continuous
718
763
 
719
764
  # Size of the computer's display
720
765
  @display_width = nil
721
766
  @display_height = nil
767
+ @display_pixel_width = nil
768
+ @display_pixel_height = nil
722
769
  end
723
770
 
724
- def _init_event_stores
725
- _init_key_event_stores
726
- _init_mouse_event_stores
727
- _init_controller_event_stores
771
+ def init_event_stores
772
+ init_key_event_stores
773
+ init_mouse_event_stores
774
+ init_gamepad_event_stores
775
+ init_object_event_stores
728
776
  end
729
777
 
730
- def _init_key_event_stores
731
- # Event stores for class pattern
732
- @keys_down = []
733
- @keys_held = []
734
- @keys_up = []
735
- end
736
-
737
- def _init_mouse_event_stores
738
- @mouse_buttons_down = []
739
- @mouse_buttons_up = []
740
- @mouse_scroll_event = false
741
- @mouse_scroll_direction = nil
742
- @mouse_scroll_delta_x = 0
743
- @mouse_scroll_delta_y = 0
744
- @mouse_move_event = false
745
- @mouse_move_delta_x = 0
746
- @mouse_move_delta_y = 0
747
- end
748
-
749
- def _init_controller_event_stores
750
- @controller_id = nil
751
- @controller_axes_moved = []
752
- @controller_axis_left_x = 0
753
- @controller_axis_left_y = 0
754
- @controller_axis_right_x = 0
755
- @controller_axis_right_y = 0
756
- @controller_buttons_down = []
757
- @controller_buttons_up = []
758
- end
759
-
760
- def _init_event_registrations
778
+ def init_event_registrations
761
779
  # Mouse X and Y position in the window
762
780
  @mouse_x = 0
763
781
  @mouse_y = 0
764
782
 
765
- # Controller axis and button mappings file
766
- @controller_mappings = "#{File.expand_path('~')}/.ruby2d/controllers.txt"
767
-
768
783
  # Unique ID for the input event being registered
769
784
  @event_key = 0
770
785
 
@@ -777,34 +792,66 @@ module Ruby2D
777
792
  mouse: {},
778
793
  mouse_up: {},
779
794
  mouse_down: {},
795
+ mouse_held: {},
780
796
  mouse_scroll: {},
781
797
  mouse_move: {},
782
- controller: {},
783
- controller_axis: {},
784
- controller_button_down: {},
785
- controller_button_up: {}
798
+ mouse_enter: {},
799
+ mouse_leave: {},
800
+ gamepad_connect: {},
801
+ gamepad_disconnect: {},
802
+ gamepad_button_down: {},
803
+ gamepad_button_held: {},
804
+ gamepad_button_up: {},
805
+ gamepad_axis: {},
806
+ close: {}
786
807
  }
787
808
  end
788
809
 
789
- def _init_procs_dsl_console
810
+ def init_procs_and_dsl
790
811
  # The window update block
791
812
  @update_proc = proc {}
813
+ @update_wants_dt = false
792
814
 
793
- # The window render block
815
+ # The window render block, and where it sits in the z-order (see `render`)
794
816
  @render_proc = proc {}
817
+ @render_z = Float::INFINITY
795
818
 
796
- # Detect if window is being used through the DSL or as a class instance
797
- @using_dsl = !(method(:update).parameters.empty? || method(:render).parameters.empty?)
819
+ # Per-frame delta-time state, populated each `update_callback`.
820
+ @last_update_time = nil
821
+ @delta_time = 0.0
822
+
823
+ # Detect the "class pattern": a Window subclass overriding `update` and/or
824
+ # `render`. Each is detected independently so overriding only one still
825
+ # works — an overridden `update` runs even when `render` is left alone, and
826
+ # vice versa. The base `update`/`render` are the DSL setters defined on
827
+ # Ruby2D::Window, so an un-overridden method finds that owner and is
828
+ # skipped in the frame loop (its DSL proc still runs).
829
+ @overrides_update = overrides?(:update)
830
+ @overrides_render = overrides?(:render)
798
831
 
799
832
  # Whether diagnostic messages should be printed
800
833
  @diagnostics = false
834
+ @show_fps = false
835
+ @close_on_esc = false
836
+ end
801
837
 
802
- # Console mode, enabled at command line
803
- @console = if RUBY_ENGINE == 'ruby'
804
- ENV['RUBY2D_ENABLE_CONSOLE'] == 'true'
805
- else
806
- false
807
- end
838
+ # Whether `name` (`:update` or `:render`) is a class-pattern override rather
839
+ # than Ruby 2D's own DSL setter.
840
+ #
841
+ # This asks which *class* in the ancestry defines the method, skipping any
842
+ # module Window itself drags along. A module prepended to Window fronts the
843
+ # setter the same way a subclass override does, so reading the immediate
844
+ # owner would mistake instrumentation — wrapping `update` to count frames or
845
+ # hook a screenshot into someone else's app — for the class pattern, and
846
+ # call the setter with no block every frame, which raises. A module mixed
847
+ # into a subclass still counts: that side of the chain is the user's own
848
+ # code, so an `update` there is an override like any other.
849
+ def overrides?(name)
850
+ wrappers = Window.ancestors - [Window]
851
+ owner = self.class.ancestors.find do |mod|
852
+ !wrappers.include?(mod) && mod.instance_methods(false).include?(name)
853
+ end
854
+ owner != Window
808
855
  end
809
856
  end
810
857
  end