ruby2d 0.11.3 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (221) hide show
  1. checksums.yaml +4 -4
  2. data/assets/include/GLES2/gl2.h +656 -0
  3. data/assets/include/GLES2/gl2ext.h +3949 -0
  4. data/assets/include/GLES2/gl2ext_angle.h +701 -0
  5. data/assets/include/GLES2/gl2platform.h +27 -0
  6. data/assets/include/GLES3/gl3.h +1192 -0
  7. data/assets/include/GLES3/gl31.h +1507 -0
  8. data/assets/include/GLES3/gl32.h +1808 -0
  9. data/assets/include/GLES3/gl3platform.h +27 -0
  10. data/assets/include/KHR/khrplatform.h +290 -0
  11. data/assets/include/SDL2/SDL.h +1 -0
  12. data/assets/include/SDL2/SDL_assert.h +4 -2
  13. data/assets/include/SDL2/SDL_atomic.h +20 -0
  14. data/assets/include/SDL2/SDL_audio.h +40 -4
  15. data/assets/include/SDL2/SDL_blendmode.h +4 -6
  16. data/assets/include/SDL2/SDL_clipboard.h +47 -0
  17. data/assets/include/SDL2/SDL_config.h +6 -2
  18. data/assets/include/SDL2/SDL_config_android.h +2 -0
  19. data/assets/include/SDL2/SDL_config_emscripten.h +2 -0
  20. data/assets/include/SDL2/SDL_config_iphoneos.h +3 -1
  21. data/assets/include/SDL2/SDL_config_macosx.h +3 -6
  22. data/assets/include/SDL2/SDL_config_minimal.h +18 -11
  23. data/assets/include/SDL2/SDL_config_ngage.h +89 -0
  24. data/assets/include/SDL2/SDL_config_os2.h +5 -3
  25. data/assets/include/SDL2/SDL_config_pandora.h +1 -0
  26. data/assets/include/SDL2/SDL_config_windows.h +71 -45
  27. data/assets/include/SDL2/SDL_config_wingdk.h +253 -0
  28. data/assets/include/SDL2/SDL_config_winrt.h +11 -49
  29. data/assets/include/SDL2/SDL_config_xbox.h +235 -0
  30. data/assets/include/SDL2/SDL_cpuinfo.h +39 -4
  31. data/assets/include/SDL2/SDL_egl.h +59 -9
  32. data/assets/include/SDL2/SDL_endian.h +34 -3
  33. data/assets/include/SDL2/SDL_events.h +32 -1
  34. data/assets/include/SDL2/SDL_filesystem.h +5 -1
  35. data/assets/include/SDL2/SDL_gamecontroller.h +78 -5
  36. data/assets/include/SDL2/SDL_guid.h +100 -0
  37. data/assets/include/SDL2/SDL_hints.h +645 -43
  38. data/assets/include/SDL2/SDL_image.h +2045 -33
  39. data/assets/include/SDL2/SDL_joystick.h +127 -7
  40. data/assets/include/SDL2/SDL_keyboard.h +38 -1
  41. data/assets/include/SDL2/SDL_keycode.h +6 -1
  42. data/assets/include/SDL2/SDL_log.h +2 -2
  43. data/assets/include/SDL2/SDL_main.h +42 -2
  44. data/assets/include/SDL2/SDL_metal.h +2 -1
  45. data/assets/include/SDL2/SDL_mixer.h +2529 -396
  46. data/assets/include/SDL2/SDL_mouse.h +12 -1
  47. data/assets/include/SDL2/SDL_opengl.h +0 -51
  48. data/assets/include/SDL2/SDL_opengl_glext.h +2260 -231
  49. data/assets/include/SDL2/SDL_opengles2_gl2.h +374 -339
  50. data/assets/include/SDL2/SDL_opengles2_gl2ext.h +3479 -1496
  51. data/assets/include/SDL2/SDL_opengles2_gl2platform.h +6 -9
  52. data/assets/include/SDL2/SDL_opengles2_khrplatform.h +43 -14
  53. data/assets/include/SDL2/SDL_platform.h +32 -6
  54. data/assets/include/SDL2/SDL_rect.h +154 -2
  55. data/assets/include/SDL2/SDL_render.h +46 -17
  56. data/assets/include/SDL2/SDL_revision.h +4 -0
  57. data/assets/include/SDL2/SDL_rwops.h +1 -15
  58. data/assets/include/SDL2/SDL_scancode.h +46 -21
  59. data/assets/include/SDL2/SDL_sensor.h +24 -3
  60. data/assets/include/SDL2/SDL_stdinc.h +119 -8
  61. data/assets/include/SDL2/SDL_surface.h +3 -1
  62. data/assets/include/SDL2/SDL_system.h +66 -6
  63. data/assets/include/SDL2/SDL_syswm.h +2 -0
  64. data/assets/include/SDL2/SDL_test_common.h +1 -0
  65. data/assets/include/SDL2/SDL_test_font.h +90 -3
  66. data/assets/include/SDL2/SDL_thread.h +3 -3
  67. data/assets/include/SDL2/SDL_touch.h +8 -0
  68. data/assets/include/SDL2/SDL_ttf.h +2084 -155
  69. data/assets/include/SDL2/SDL_version.h +19 -3
  70. data/assets/include/SDL2/SDL_video.h +71 -9
  71. data/assets/include/SDL2/begin_code.h +4 -4
  72. data/assets/include/mrbconf.h +15 -17
  73. data/assets/include/mruby/array.h +8 -21
  74. data/assets/include/mruby/boxing_nan.h +115 -86
  75. data/assets/include/mruby/boxing_word.h +104 -78
  76. data/assets/include/mruby/common.h +6 -0
  77. data/assets/include/mruby/compile.h +3 -4
  78. data/assets/include/mruby/debug.h +4 -2
  79. data/assets/include/mruby/dump.h +5 -2
  80. data/assets/include/mruby/error.h +12 -2
  81. data/assets/include/mruby/gc.h +2 -0
  82. data/assets/include/mruby/hash.h +1 -3
  83. data/assets/include/mruby/irep.h +4 -4
  84. data/assets/include/mruby/numeric.h +21 -13
  85. data/assets/include/mruby/opcode.h +30 -0
  86. data/assets/include/mruby/ops.h +99 -101
  87. data/assets/include/mruby/presym/scanning.h +15 -9
  88. data/assets/include/mruby/proc.h +4 -2
  89. data/assets/include/mruby/string.h +3 -24
  90. data/assets/include/mruby/value.h +80 -40
  91. data/assets/include/mruby/variable.h +0 -15
  92. data/assets/include/mruby/version.h +5 -5
  93. data/assets/include/mruby.h +86 -16
  94. data/assets/macos/universal/bin/mrbc +0 -0
  95. data/assets/macos/universal/lib/libFLAC.a +0 -0
  96. data/assets/macos/universal/lib/libSDL2.a +0 -0
  97. data/assets/macos/universal/lib/libSDL2_image.a +0 -0
  98. data/assets/macos/universal/lib/libSDL2_mixer.a +0 -0
  99. data/assets/macos/universal/lib/libSDL2_ttf.a +0 -0
  100. data/assets/macos/universal/lib/libavif.a +0 -0
  101. data/assets/macos/universal/lib/libbrotlicommon-static.a +0 -0
  102. data/assets/macos/universal/lib/libbrotlidec-static.a +0 -0
  103. data/assets/macos/universal/lib/libfreetype.a +0 -0
  104. data/assets/macos/universal/lib/libgraphite2.a +0 -0
  105. data/assets/macos/universal/lib/libharfbuzz.a +0 -0
  106. data/assets/macos/universal/lib/libhwy.a +0 -0
  107. data/assets/macos/universal/lib/libjpeg.a +0 -0
  108. data/assets/macos/universal/lib/libjxl.a +0 -0
  109. data/assets/macos/universal/lib/libmodplug.a +0 -0
  110. data/assets/macos/universal/lib/libmpg123.a +0 -0
  111. data/assets/macos/universal/lib/libmruby.a +0 -0
  112. data/assets/macos/universal/lib/libogg.a +0 -0
  113. data/assets/macos/universal/lib/libpng.a +0 -0
  114. data/assets/macos/universal/lib/libtiff.a +0 -0
  115. data/assets/macos/universal/lib/libvorbis.a +0 -0
  116. data/assets/macos/universal/lib/libvorbisfile.a +0 -0
  117. data/assets/macos/universal/lib/libwebp.a +0 -0
  118. data/assets/macos/universal/lib/libzstd.a +0 -0
  119. data/assets/wasm/template.html +2 -1
  120. data/assets/windows/mingw-w64-ucrt-x86_64/bin/mrbc.exe +0 -0
  121. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libFLAC.a +0 -0
  122. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libLerc.a +0 -0
  123. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2.a +0 -0
  124. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_image.a +0 -0
  125. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_mixer.a +0 -0
  126. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_ttf.a +0 -0
  127. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libbrotlicommon.a +0 -0
  128. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libbrotlidec.a +0 -0
  129. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libdeflate.a +0 -0
  130. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libfreetype.a +0 -0
  131. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libglew32.a +0 -0
  132. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libharfbuzz.a +0 -0
  133. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libhwy.a +0 -0
  134. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libjpeg.a +0 -0
  135. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libjxl.a +0 -0
  136. data/assets/windows/mingw-w64-ucrt-x86_64/lib/liblzma.a +0 -0
  137. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libmpg123.a +0 -0
  138. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libmruby.a +0 -0
  139. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libopus.a +0 -0
  140. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libpng.a +0 -0
  141. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libsndfile.a +0 -0
  142. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libssp.a +0 -0
  143. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libstdc++.a +0 -0
  144. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libtiff.a +0 -0
  145. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libwebp.a +0 -0
  146. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libz.a +0 -0
  147. data/assets/windows/mingw-w64-x86_64/bin/mrbc.exe +0 -0
  148. data/assets/windows/mingw-w64-x86_64/lib/libFLAC.a +0 -0
  149. data/assets/windows/mingw-w64-x86_64/lib/libLerc.a +0 -0
  150. data/assets/windows/mingw-w64-x86_64/lib/libSDL2.a +0 -0
  151. data/assets/windows/mingw-w64-x86_64/lib/libSDL2_image.a +0 -0
  152. data/assets/windows/mingw-w64-x86_64/lib/libSDL2_mixer.a +0 -0
  153. data/assets/windows/mingw-w64-x86_64/lib/libSDL2_ttf.a +0 -0
  154. data/assets/windows/mingw-w64-x86_64/lib/libbrotlicommon.a +0 -0
  155. data/assets/windows/mingw-w64-x86_64/lib/libbrotlidec.a +0 -0
  156. data/assets/windows/mingw-w64-x86_64/lib/libdeflate.a +0 -0
  157. data/assets/windows/mingw-w64-x86_64/lib/libfreetype.a +0 -0
  158. data/assets/windows/mingw-w64-x86_64/lib/libglew32.a +0 -0
  159. data/assets/windows/mingw-w64-x86_64/lib/libharfbuzz.a +0 -0
  160. data/assets/windows/mingw-w64-x86_64/lib/libhwy.a +0 -0
  161. data/assets/windows/mingw-w64-x86_64/lib/libjpeg.a +0 -0
  162. data/assets/windows/mingw-w64-x86_64/lib/libjxl.a +0 -0
  163. data/assets/windows/mingw-w64-x86_64/lib/liblzma.a +0 -0
  164. data/assets/windows/mingw-w64-x86_64/lib/libmpg123.a +0 -0
  165. data/assets/windows/mingw-w64-x86_64/lib/libmruby.a +0 -0
  166. data/assets/windows/mingw-w64-x86_64/lib/libopus.a +0 -0
  167. data/assets/windows/mingw-w64-x86_64/lib/libpng.a +0 -0
  168. data/assets/windows/mingw-w64-x86_64/lib/libsndfile.a +0 -0
  169. data/assets/windows/mingw-w64-x86_64/lib/libssp.a +0 -0
  170. data/assets/windows/mingw-w64-x86_64/lib/libstdc++.a +0 -0
  171. data/assets/windows/mingw-w64-x86_64/lib/libtiff.a +0 -0
  172. data/assets/windows/mingw-w64-x86_64/lib/libwebp.a +0 -0
  173. data/assets/windows/mingw-w64-x86_64/lib/libz.a +0 -0
  174. data/assets/windows/mingw-w64-x86_64/lib/libzstd.a +0 -0
  175. data/ext/ruby2d/canvas.c +540 -0
  176. data/ext/ruby2d/extconf.rb +33 -20
  177. data/ext/ruby2d/gl.c +3 -3
  178. data/ext/ruby2d/image.c +7 -7
  179. data/ext/ruby2d/ruby2d.c +741 -24
  180. data/ext/ruby2d/ruby2d.h +66 -3
  181. data/ext/ruby2d/sound.c +16 -2
  182. data/lib/ruby2d/canvas.rb +315 -0
  183. data/lib/ruby2d/circle.rb +30 -15
  184. data/lib/ruby2d/cli/build.rb +5 -3
  185. data/lib/ruby2d/cli/enable_console.rb +3 -1
  186. data/lib/ruby2d/color.rb +133 -77
  187. data/lib/ruby2d/core.rb +32 -0
  188. data/lib/ruby2d/dsl.rb +38 -32
  189. data/lib/ruby2d/exceptions.rb +2 -1
  190. data/lib/ruby2d/font.rb +97 -62
  191. data/lib/ruby2d/image.rb +48 -27
  192. data/lib/ruby2d/line.rb +84 -45
  193. data/lib/ruby2d/music.rb +33 -23
  194. data/lib/ruby2d/pixel.rb +10 -9
  195. data/lib/ruby2d/pixmap.rb +39 -0
  196. data/lib/ruby2d/pixmap_atlas.rb +56 -0
  197. data/lib/ruby2d/quad.rb +98 -49
  198. data/lib/ruby2d/rectangle.rb +35 -36
  199. data/lib/ruby2d/renderable.rb +7 -6
  200. data/lib/ruby2d/sound.rb +23 -17
  201. data/lib/ruby2d/sprite.rb +181 -140
  202. data/lib/ruby2d/square.rb +21 -20
  203. data/lib/ruby2d/text.rb +47 -19
  204. data/lib/ruby2d/texture.rb +13 -3
  205. data/lib/ruby2d/tileset.rb +97 -44
  206. data/lib/ruby2d/triangle.rb +91 -42
  207. data/lib/ruby2d/version.rb +3 -1
  208. data/lib/ruby2d/vertices.rb +81 -45
  209. data/lib/ruby2d/window.rb +508 -371
  210. data/lib/ruby2d.rb +11 -29
  211. metadata +51 -16
  212. data/assets/include/SDL2/SDL_config_psp.h +0 -165
  213. data/assets/include/SDL2/SDL_config_wiz.h +0 -154
  214. data/assets/include/glew.h +0 -23686
  215. data/assets/macos/universal/lib/libpng16.a +0 -0
  216. data/assets/windows/glew/README.md +0 -10
  217. data/assets/windows/glew/glew.h +0 -23686
  218. data/assets/windows/glew/libglew32.a +0 -0
  219. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libpng16.a +0 -0
  220. data/assets/windows/mingw-w64-x86_64/lib/libpng16.a +0 -0
  221. data/lib/ruby2d/entity.rb +0 -17
data/ext/ruby2d/ruby2d.c CHANGED
@@ -90,6 +90,7 @@
90
90
  #define r_ary_entry(ary, pos) rb_ary_entry(ary, pos)
91
91
  #define r_ary_new() rb_ary_new()
92
92
  #define r_ary_push(self, val) rb_ary_push(self, val)
93
+ #define r_ary_len(self) rb_ary_len(self)
93
94
  #define r_data_wrap_struct(name, data) Data_Wrap_Struct(rb_cObject, NULL, (free_##name), data)
94
95
  #define r_data_get_struct(self, var, mrb_type, rb_type, data) Data_Get_Struct(r_iv_get(self, var), rb_type, data)
95
96
  #define r_define_module(name) rb_define_module(name)
@@ -132,11 +133,21 @@ static void free_surface(mrb_state *mrb, void *p_);
132
133
  static const struct mrb_data_type surface_data_type = {
133
134
  "surface", free_surface
134
135
  };
136
+ static void free_sdl_texture(mrb_state *mrb, void *p_);
137
+ static const struct mrb_data_type sdl_texture_data_type = {
138
+ "sdl_texture", free_sdl_texture
139
+ };
140
+ static void free_renderer(mrb_state *mrb, void *p_);
141
+ static const struct mrb_data_type renderer_data_type = {
142
+ "renderer", free_renderer
143
+ };
135
144
  #else
136
145
  static void free_sound(R2D_Sound *snd);
137
146
  static void free_music(R2D_Music *mus);
138
147
  static void free_font(TTF_Font *font);
139
148
  static void free_surface(SDL_Surface *surface);
149
+ static void free_sdl_texture(SDL_Texture *surface);
150
+ static void free_renderer(SDL_Renderer *renderer);
140
151
  #endif
141
152
 
142
153
 
@@ -371,31 +382,46 @@ static R_VAL ruby2d_circle_ext_draw(R_VAL self, R_VAL a) {
371
382
 
372
383
 
373
384
  /*
374
- * Ruby2D::Image#ext_load_image
375
- * Create an SDL surface from an image path, return the surface, width, and height
385
+ * Ruby2D::Pixmap#ext_load_pixmap
386
+ * Create an SDL surface from an image path, and ...
387
+ * TODO: store the surface, width, and height in the object
376
388
  */
377
389
  #if MRUBY
378
- static R_VAL ruby2d_image_ext_load_image(mrb_state* mrb, R_VAL self) {
390
+ static R_VAL ruby2d_pixmap_ext_load_pixmap(mrb_state* mrb, R_VAL self) {
379
391
  mrb_value path;
380
392
  mrb_get_args(mrb, "o", &path);
381
393
  #else
382
- static R_VAL ruby2d_image_ext_load_image(R_VAL self, R_VAL path) {
394
+ static R_VAL ruby2d_pixmap_ext_load_pixmap(R_VAL self, R_VAL path) {
383
395
  #endif
384
396
  R2D_Init();
385
397
 
386
- R_VAL result = r_ary_new();
387
-
388
398
  SDL_Surface *surface = R2D_CreateImageSurface(RSTRING_PTR(path));
389
- R2D_ImageConvertToRGB(surface);
390
-
391
- r_ary_push(result, r_data_wrap_struct(surface, surface));
392
- r_ary_push(result, INT2NUM(surface->w));
393
- r_ary_push(result, INT2NUM(surface->h));
399
+ // initialize for later use
400
+ r_iv_set(self, "@ext_sdl_texture", R_NIL);
401
+
402
+ if (surface != NULL) {
403
+ #if GLES
404
+ // OpenGL ES doesn't support BGR color order, so applying the
405
+ // conversion to the pixels. This will however render incorrect colours
406
+ // for BGR images when using Canvas.
407
+ // TODO: A better solution one day?
408
+ R2D_ImageConvertToRGB(surface);
409
+ #endif
394
410
 
395
- return result;
411
+ r_iv_set(self, "@ext_pixel_data", r_data_wrap_struct(surface, surface));
412
+ r_iv_set(self, "@width", INT2NUM(surface->w));
413
+ r_iv_set(self, "@height", INT2NUM(surface->h));
414
+ }
415
+ else {
416
+ // TODO: consider raising an exception?
417
+ // for docs: https://silverhammermba.github.io/emberb/c/#raise
418
+ r_iv_set(self, "@ext_pixel_data", R_NIL);
419
+ r_iv_set(self, "@width", INT2NUM(0));
420
+ r_iv_set(self, "@height", INT2NUM(0));
421
+ }
422
+ return R_NIL;
396
423
  }
397
424
 
398
-
399
425
  /*
400
426
  * Ruby2D::Text#ext_load_text
401
427
  */
@@ -430,6 +456,69 @@ static R_VAL ruby2d_text_ext_load_text(R_VAL self, R_VAL font, R_VAL message) {
430
456
  return result;
431
457
  }
432
458
 
459
+ /*
460
+ * Ruby2D::Canvas#ext_draw_pixmap
461
+ */
462
+ #if MRUBY
463
+ static R_VAL ruby2d_canvas_ext_draw_pixmap(mrb_state* mrb, R_VAL self) {
464
+ mrb_value pixmap, src_rect, x, y, w, h;
465
+ mrb_get_args(mrb, "oooooo", &pixmap, &src_rect, &x, &y, &w, &h);
466
+ #else
467
+ static R_VAL ruby2d_canvas_ext_draw_pixmap(R_VAL self, R_VAL pixmap, R_VAL src_rect, R_VAL x, R_VAL y, R_VAL w, R_VAL h) {
468
+ #endif
469
+
470
+ if (r_test(pixmap)) {
471
+ // Retrieve pixmap's external pixel data (SDL_Surface)
472
+ SDL_Surface *pix_surface;
473
+ r_data_get_struct(pixmap, "@ext_pixel_data", &surface_data_type, SDL_Surface, pix_surface);
474
+
475
+ SDL_Texture *pix_sdl_tex = NULL;
476
+ R_VAL pix_ext_sdl_tex = r_iv_get(pixmap, "@ext_sdl_texture");
477
+ if (r_test(pix_ext_sdl_tex)) {
478
+ r_data_get_struct(pixmap, "@ext_sdl_texture", &sdl_texture_data_type, SDL_Texture, pix_sdl_tex);
479
+ }
480
+
481
+ SDL_Renderer *render;
482
+ r_data_get_struct(self, "@ext_renderer", &renderer_data_type, SDL_Renderer, render);
483
+
484
+ if (pix_sdl_tex == NULL) {
485
+ // create and cache an SDL_Texture for this Pixmap
486
+ pix_sdl_tex = SDL_CreateTextureFromSurface(render, pix_surface);
487
+ if (pix_sdl_tex != NULL) {
488
+ r_iv_set(pixmap, "@ext_sdl_texture", r_data_wrap_struct(sdl_texture, pix_sdl_tex));
489
+ }
490
+ else printf("*** Unable to create SDL_Texture: %s\n", SDL_GetError());
491
+ }
492
+
493
+ // Draw if we have an SDL_Texture
494
+ if (pix_sdl_tex != NULL) {
495
+ SDL_bool src_set = SDL_FALSE;
496
+ SDL_Rect src;
497
+ if (r_test(src_rect)) {
498
+ src_set = SDL_TRUE;
499
+ // portion of pixmap
500
+ src = (SDL_Rect) {
501
+ .x = NUM2INT(r_ary_entry(src_rect, 0)),
502
+ .y = NUM2INT(r_ary_entry(src_rect, 1)),
503
+ .w = NUM2INT(r_ary_entry(src_rect, 2)),
504
+ .h = NUM2INT(r_ary_entry(src_rect, 3))
505
+ };
506
+ }
507
+ else {
508
+ // whole pixmap
509
+ src = (SDL_Rect){ .x = 0, .y = 0, .w = pix_surface->w, .h = pix_surface->h };
510
+ }
511
+ // use incoming size or source size or fallback to pixmap size
512
+ int pix_w = r_test(w) ? NUM2INT(w) : (src_set ? src.w : NUM2INT(r_iv_get(pixmap, "@width")));
513
+ int pix_h = r_test(h) ? NUM2INT(h) : (src_set ? src.h : NUM2INT(r_iv_get(pixmap, "@height")));
514
+
515
+ SDL_Rect dst = { .x = NUM2INT(x), .y = NUM2INT(y), .w = pix_w, .h = pix_h };
516
+ SDL_RenderCopy (render, pix_sdl_tex, &src, &dst);
517
+ }
518
+ }
519
+ return R_NIL;
520
+ }
521
+
433
522
 
434
523
  /*
435
524
  * Ruby2D::Texture#ext_create
@@ -451,19 +540,47 @@ static R_VAL ruby2d_texture_ext_create(R_VAL self, R_VAL rubySurface, R_VAL widt
451
540
  #endif
452
541
 
453
542
  // Detect image mode
454
- GLint format = GL_RGB;
455
- if (surface->format->BytesPerPixel == 4) {
456
- format = GL_RGBA;
457
- }
543
+ GLint gl_internal_format, gl_format;
544
+ GLenum gl_type;
458
545
 
459
- R2D_GL_CreateTexture(&texture_id, format,
546
+ switch (surface->format->BytesPerPixel) {
547
+ case 4:
548
+ #if GLES
549
+ gl_internal_format = gl_format = GL_RGBA;
550
+ #else
551
+ gl_internal_format = GL_RGBA;
552
+ gl_format = (surface->format->Rmask == 0xff0000) ? GL_BGRA : GL_RGBA;
553
+ #endif
554
+ gl_type = GL_UNSIGNED_BYTE;
555
+ break;
556
+ case 3:
557
+ #if GLES
558
+ gl_internal_format = gl_format = GL_RGB;
559
+ #else
560
+ gl_internal_format = GL_RGB;
561
+ gl_format = (surface->format->Rmask == 0xff0000) ? GL_BGR : GL_RGB;
562
+ #endif
563
+ gl_type = GL_UNSIGNED_BYTE;
564
+ break;
565
+ case 2:
566
+ gl_internal_format = gl_format = GL_RGB;
567
+ gl_type = GL_UNSIGNED_SHORT_5_6_5;
568
+ break;
569
+ case 1:
570
+ default:
571
+ // this would be ideal for font glyphs which use luminance + alpha and colour
572
+ // is set when drawing
573
+ gl_internal_format = gl_format = GL_LUMINANCE_ALPHA;
574
+ gl_type = GL_UNSIGNED_BYTE;
575
+ break;
576
+ }
577
+ R2D_GL_CreateTexture(&texture_id, gl_internal_format, gl_format, gl_type,
460
578
  NUM2INT(width), NUM2INT(height),
461
579
  surface->pixels, GL_NEAREST);
462
580
 
463
581
  return INT2NUM(texture_id);
464
582
  }
465
583
 
466
-
467
584
  /*
468
585
  * Ruby2D::Texture#ext_delete
469
586
  */
@@ -482,6 +599,528 @@ static R_VAL ruby2d_texture_ext_delete(R_VAL self, R_VAL rubyTexture_id) {
482
599
  }
483
600
 
484
601
 
602
+ /*
603
+ * Ruby2D::Canvas#ext_create
604
+ */
605
+ #if MRUBY
606
+ static R_VAL ruby2d_canvas_ext_create(mrb_state* mrb, R_VAL self) {
607
+ mrb_value a;
608
+ mrb_get_args(mrb, "o", &a);
609
+ #else
610
+ static R_VAL ruby2d_canvas_ext_create(R_VAL self, R_VAL a) {
611
+ #endif
612
+ SDL_Surface *surf = SDL_CreateRGBSurface(
613
+ 0, NUM2INT(r_ary_entry(a, 0)), NUM2INT(r_ary_entry(a, 1)),
614
+ 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
615
+ );
616
+
617
+ SDL_Renderer *render = SDL_CreateSoftwareRenderer(surf);
618
+
619
+ SDL_SetRenderDrawColor(render,
620
+ NUM2DBL(r_ary_entry(a, 2)) * 255, // r
621
+ NUM2DBL(r_ary_entry(a, 3)) * 255, // g
622
+ NUM2DBL(r_ary_entry(a, 4)) * 255, // b
623
+ NUM2DBL(r_ary_entry(a, 5)) * 255 // a
624
+ );
625
+ SDL_SetRenderDrawBlendMode(render, SDL_BLENDMODE_NONE);
626
+ SDL_RenderClear(render);
627
+
628
+ SDL_SetSurfaceBlendMode(surf, SDL_BLENDMODE_BLEND);
629
+ SDL_SetRenderDrawBlendMode(render, SDL_BLENDMODE_BLEND);
630
+
631
+ r_iv_set(self, "@ext_pixel_data", r_data_wrap_struct(surface, surf));
632
+ r_iv_set(self, "@ext_renderer", r_data_wrap_struct(renderer, render));
633
+ return R_NIL;
634
+ }
635
+
636
+ /*
637
+ * Ruby2D::Canvas#ext_clear
638
+ */
639
+ #if MRUBY
640
+ static R_VAL ruby2d_canvas_ext_clear(mrb_state* mrb, R_VAL self) {
641
+ mrb_value a;
642
+ mrb_get_args(mrb, "o", &a);
643
+ #else
644
+ static R_VAL ruby2d_canvas_ext_clear(R_VAL self, R_VAL a) {
645
+ #endif
646
+ // `a` is the array representing the colour values
647
+
648
+ SDL_Renderer *render;
649
+ r_data_get_struct(self, "@ext_renderer", &renderer_data_type, SDL_Renderer, render);
650
+
651
+ SDL_SetRenderDrawColor(render,
652
+ NUM2DBL(r_ary_entry(a, 0)) * 255, // r
653
+ NUM2DBL(r_ary_entry(a, 1)) * 255, // g
654
+ NUM2DBL(r_ary_entry(a, 2)) * 255, // b
655
+ NUM2DBL(r_ary_entry(a, 3)) * 255 // a
656
+ );
657
+ SDL_SetRenderDrawBlendMode(render, SDL_BLENDMODE_NONE);
658
+ SDL_RenderClear(render);
659
+ SDL_SetRenderDrawBlendMode(render, SDL_BLENDMODE_BLEND);
660
+
661
+ return R_NIL;
662
+ }
663
+
664
+ /*
665
+ * Ruby2D::Canvas#ext_fill_rectangle
666
+ */
667
+ #if MRUBY
668
+ static R_VAL ruby2d_canvas_ext_fill_rectangle(mrb_state* mrb, R_VAL self) {
669
+ mrb_value a;
670
+ mrb_get_args(mrb, "o", &a);
671
+ #else
672
+ static R_VAL ruby2d_canvas_ext_fill_rectangle(R_VAL self, R_VAL a) {
673
+ #endif
674
+ // `a` is the array representing the rectangle
675
+
676
+ SDL_Renderer *render;
677
+ r_data_get_struct(self, "@ext_renderer", &renderer_data_type, SDL_Renderer, render);
678
+
679
+ SDL_SetRenderDrawBlendMode(render, SDL_BLENDMODE_BLEND);
680
+
681
+ SDL_Rect rect = { .x = NUM2INT(r_ary_entry(a, 0)),
682
+ .y = NUM2INT(r_ary_entry(a, 1)),
683
+ .w = NUM2INT(r_ary_entry(a, 2)),
684
+ .h = NUM2INT(r_ary_entry(a, 3))
685
+ };
686
+
687
+ SDL_SetRenderDrawColor(render,
688
+ NUM2DBL(r_ary_entry(a, 4)) * 255, // r
689
+ NUM2DBL(r_ary_entry(a, 5)) * 255, // g
690
+ NUM2DBL(r_ary_entry(a, 6)) * 255, // b
691
+ NUM2DBL(r_ary_entry(a, 7)) * 255 // a
692
+ );
693
+ SDL_RenderFillRect(render, &rect);
694
+
695
+ return R_NIL;
696
+ }
697
+
698
+ /*
699
+ * Ruby2D::Canvas#ext_draw_rectangle
700
+ */
701
+ #if MRUBY
702
+ static R_VAL ruby2d_canvas_ext_draw_rectangle(mrb_state* mrb, R_VAL self) {
703
+ mrb_value a;
704
+ mrb_get_args(mrb, "o", &a);
705
+ #else
706
+ static R_VAL ruby2d_canvas_ext_draw_rectangle(R_VAL self, R_VAL a) {
707
+ #endif
708
+ // `a` is the array representing the rectangle
709
+ // 0, 1, 2, 3, 4, 5, 6, 7, 8
710
+ // [ x, y, width, height, thickness, r, g, b, a]
711
+
712
+ SDL_Renderer *render;
713
+ r_data_get_struct(self, "@ext_renderer", &renderer_data_type, SDL_Renderer, render);
714
+
715
+ int thickness = NUM2INT(r_ary_entry(a, 4));
716
+ if (thickness == 1) {
717
+ SDL_Rect rect = { .x = NUM2INT(r_ary_entry(a, 0)),
718
+ .y = NUM2INT(r_ary_entry(a, 1)),
719
+ .w = NUM2INT(r_ary_entry(a, 2)),
720
+ .h = NUM2INT(r_ary_entry(a, 3))
721
+ };
722
+
723
+ SDL_SetRenderDrawColor(render,
724
+ NUM2DBL(r_ary_entry(a, 5)) * 255, // r
725
+ NUM2DBL(r_ary_entry(a, 6)) * 255, // g
726
+ NUM2DBL(r_ary_entry(a, 7)) * 255, // b
727
+ NUM2DBL(r_ary_entry(a, 8)) * 255 // a
728
+ );
729
+ SDL_RenderDrawRect(render, &rect);
730
+ }
731
+ else if (thickness > 1) {
732
+ R2D_Canvas_DrawThickRect(render,
733
+ NUM2INT(r_ary_entry(a, 0)), // x
734
+ NUM2INT(r_ary_entry(a, 1)), // y
735
+ NUM2INT(r_ary_entry(a, 2)), // width
736
+ NUM2INT(r_ary_entry(a, 3)), // height
737
+ thickness,
738
+ NUM2DBL(r_ary_entry(a, 5)) * 255, // r
739
+ NUM2DBL(r_ary_entry(a, 6)) * 255, // g
740
+ NUM2DBL(r_ary_entry(a, 7)) * 255, // b
741
+ NUM2DBL(r_ary_entry(a, 8)) * 255 // a
742
+ );
743
+ }
744
+ return R_NIL;
745
+ }
746
+
747
+ /*
748
+ * Ruby2D::Canvas#ext_draw_line
749
+ */
750
+ #if MRUBY
751
+ static R_VAL ruby2d_canvas_ext_draw_line(mrb_state* mrb, R_VAL self) {
752
+ mrb_value a;
753
+ mrb_get_args(mrb, "o", &a);
754
+ #else
755
+ static R_VAL ruby2d_canvas_ext_draw_line(R_VAL self, R_VAL a) {
756
+ #endif
757
+ // `a` is the array representing the line
758
+
759
+ SDL_Renderer *render;
760
+ r_data_get_struct(self, "@ext_renderer", &renderer_data_type, SDL_Renderer, render);
761
+
762
+ int thickness = NUM2INT(r_ary_entry(a, 4));
763
+ if (thickness == 1) {
764
+ // use the SDL_Renderer's draw line for single pixel lines
765
+ SDL_SetRenderDrawColor(render,
766
+ NUM2DBL(r_ary_entry(a, 5)) * 255, // r
767
+ NUM2DBL(r_ary_entry(a, 6)) * 255, // g
768
+ NUM2DBL(r_ary_entry(a, 7)) * 255, // b
769
+ NUM2DBL(r_ary_entry(a, 8)) * 255 // a
770
+ );
771
+ SDL_RenderDrawLine(render,
772
+ NUM2INT(r_ary_entry(a, 0)), // x1
773
+ NUM2INT(r_ary_entry(a, 1)), // y1
774
+ NUM2INT(r_ary_entry(a, 2)), // x2
775
+ NUM2INT(r_ary_entry(a, 3)) // y2
776
+ );
777
+ }
778
+ else if (thickness > 1) {
779
+ // use a custom handler to convert a thick line into a
780
+ // quad and draw using SDL_Renderer's geometry renderer
781
+ R2D_Canvas_DrawThickLine(render,
782
+ NUM2INT(r_ary_entry(a, 0)), // x1
783
+ NUM2INT(r_ary_entry(a, 1)), // y1
784
+ NUM2INT(r_ary_entry(a, 2)), // x2
785
+ NUM2INT(r_ary_entry(a, 3)), // y2
786
+ thickness,
787
+ NUM2DBL(r_ary_entry(a, 5)) * 255, // r
788
+ NUM2DBL(r_ary_entry(a, 6)) * 255, // g
789
+ NUM2DBL(r_ary_entry(a, 7)) * 255, // b
790
+ NUM2DBL(r_ary_entry(a, 8)) * 255 // a
791
+ );
792
+ }
793
+
794
+ return R_NIL;
795
+ }
796
+
797
+ #define MAX_POLY_POINTS 64
798
+
799
+ /*
800
+ * Ruby2D::Canvas#ext_draw_polyline
801
+ */
802
+ #if MRUBY
803
+ static R_VAL ruby2d_canvas_ext_draw_polyline(mrb_state* mrb, R_VAL self) {
804
+ mrb_value config, coords;
805
+ mrb_get_args(mrb, "oo", &config, &coords);
806
+ #else
807
+ static R_VAL ruby2d_canvas_ext_draw_polyline(R_VAL self, R_VAL config, R_VAL coords) {
808
+ #endif
809
+ // `config` is an array
810
+ // 0, 1, 2, 3, 4
811
+ // [ thickness, r, g, b, a ]
812
+ //
813
+ // `coords` is an array of x, y values
814
+ // 0, 1, 2, 3, ...
815
+ // [ x1, y1, x2, y2, ... ]
816
+
817
+ SDL_Renderer *render;
818
+ r_data_get_struct(self, "@ext_renderer", &renderer_data_type, SDL_Renderer, render);
819
+
820
+ long coord_count = RARRAY_LEN(coords);
821
+ int thickness = NUM2INT(r_ary_entry(config, 0));
822
+ if (thickness == 1) {
823
+ // use the SDL_Renderer's draw line for single pixel lines
824
+ SDL_SetRenderDrawColor(render,
825
+ NUM2DBL(r_ary_entry(config, 1)) * 255, // r
826
+ NUM2DBL(r_ary_entry(config, 2)) * 255, // g
827
+ NUM2DBL(r_ary_entry(config, 3)) * 255, // b
828
+ NUM2DBL(r_ary_entry(config, 4)) * 255 // a
829
+ );
830
+ int x1 = NUM2INT(r_ary_entry(coords, 0));
831
+ int y1 = NUM2INT(r_ary_entry(coords, 1));
832
+ for (int i = 2; i < coord_count; i+= 2) {
833
+ int x2 = NUM2INT(r_ary_entry(coords, i));
834
+ int y2 = NUM2INT(r_ary_entry(coords, i+1));
835
+ SDL_RenderDrawLine(render, x1, y1, x2, y2);
836
+ x1 = x2;
837
+ y1 = y2;
838
+ }
839
+ }
840
+ else if (thickness > 1) {
841
+ // use a custom handler to convert a thick line into a
842
+ // quad and draw using SDL_Renderer's geometry renderer
843
+
844
+ SDL_FPoint points[MAX_POLY_POINTS];
845
+ int num_points = 0;
846
+
847
+ points[num_points++] = (SDL_FPoint) {
848
+ .x = NUM2INT(r_ary_entry(coords, 0)),
849
+ .y = NUM2INT(r_ary_entry(coords, 1))
850
+ };
851
+ for (int i = 2; i < coord_count && num_points < MAX_POLY_POINTS; i+= 2) {
852
+ points[num_points++] = (SDL_FPoint) {
853
+ .x = NUM2INT(r_ary_entry(coords, i)),
854
+ .y = NUM2INT(r_ary_entry(coords, i+1)) };
855
+ }
856
+ R2D_Canvas_DrawThickPolyline(render,
857
+ points, num_points,
858
+ thickness,
859
+ NUM2DBL(r_ary_entry(config, 1)) * 255, // r
860
+ NUM2DBL(r_ary_entry(config, 2)) * 255, // g
861
+ NUM2DBL(r_ary_entry(config, 3)) * 255, // b
862
+ NUM2DBL(r_ary_entry(config, 4)) * 255, // a
863
+ false // don't skip first/last
864
+ );
865
+ }
866
+
867
+ return R_NIL;
868
+ }
869
+
870
+ /*
871
+ * Ruby2D::Canvas#ext_draw_polygon
872
+ */
873
+ #if MRUBY
874
+ static R_VAL ruby2d_canvas_ext_draw_polygon(mrb_state* mrb, R_VAL self) {
875
+ mrb_value config, coords;
876
+ mrb_get_args(mrb, "oo", &config, &coords);
877
+ #else
878
+ static R_VAL ruby2d_canvas_ext_draw_polygon(R_VAL self, R_VAL config, R_VAL coords) {
879
+ #endif
880
+ // `config` is an array
881
+ // 0, 1, 2, 3, 4
882
+ // [ thickness, r, g, b, a ]
883
+ //
884
+ // `coords` is an array of x, y values
885
+ // 0, 1, 2, 3, ...
886
+ // [ x1, y1, x2, y2, ... ]
887
+
888
+ SDL_Renderer *render;
889
+ r_data_get_struct(self, "@ext_renderer", &renderer_data_type, SDL_Renderer, render);
890
+
891
+ long coord_count = RARRAY_LEN(coords);
892
+ int thickness = NUM2INT(r_ary_entry(config, 0));
893
+ if (thickness == 1) {
894
+ // use the SDL_Renderer's draw line for single pixel lines
895
+ SDL_SetRenderDrawColor(render,
896
+ NUM2DBL(r_ary_entry(config, 1)) * 255, // r
897
+ NUM2DBL(r_ary_entry(config, 2)) * 255, // g
898
+ NUM2DBL(r_ary_entry(config, 3)) * 255, // b
899
+ NUM2DBL(r_ary_entry(config, 4)) * 255 // a
900
+ );
901
+ int x1 = NUM2INT(r_ary_entry(coords, 0));
902
+ int y1 = NUM2INT(r_ary_entry(coords, 1));
903
+ for (int i = 2; i < coord_count; i+= 2) {
904
+ int x2 = NUM2INT(r_ary_entry(coords, i));
905
+ int y2 = NUM2INT(r_ary_entry(coords, i+1));
906
+ SDL_RenderDrawLine(render, x1, y1, x2, y2);
907
+ x1 = x2;
908
+ y1 = y2;
909
+ }
910
+ // connect back to first point to close the shape
911
+ int x2 = NUM2INT(r_ary_entry(coords, 0));
912
+ int y2 = NUM2INT(r_ary_entry(coords, 1));
913
+ SDL_RenderDrawLine(render, x1, y1, x2, y2);
914
+ }
915
+ else if (thickness > 1) {
916
+ // use a custom handler to convert a thick line into a
917
+ // quad and draw using SDL_Renderer's geometry renderer
918
+
919
+ SDL_FPoint points[MAX_POLY_POINTS+3]; // three extra slots to points 0, 1, 2
920
+ int num_points = 0;
921
+
922
+ points[num_points++] = (SDL_FPoint) {
923
+ .x = NUM2INT(r_ary_entry(coords, 0)),
924
+ .y = NUM2INT(r_ary_entry(coords, 1))
925
+ };
926
+ for (int i = 2; i < coord_count && num_points < MAX_POLY_POINTS; i+= 2) {
927
+ points[num_points++] = (SDL_FPoint) {
928
+ .x = NUM2INT(r_ary_entry(coords, i)),
929
+ .y = NUM2INT(r_ary_entry(coords, i+1)) };
930
+ }
931
+ // repeat first three coordinates at the end
932
+ points[num_points++] = points[0];
933
+ points[num_points++] = points[1];
934
+ points[num_points++] = points[2];
935
+ // use polyline draw but ask it to skip first and last segments
936
+ // since we added three more points at the end, these produce the
937
+ // missing segments with proper joins
938
+ R2D_Canvas_DrawThickPolyline(render,
939
+ points, num_points,
940
+ thickness,
941
+ NUM2DBL(r_ary_entry(config, 1)) * 255, // r
942
+ NUM2DBL(r_ary_entry(config, 2)) * 255, // g
943
+ NUM2DBL(r_ary_entry(config, 3)) * 255, // b
944
+ NUM2DBL(r_ary_entry(config, 4)) * 255, // a
945
+ true // skip first/last segments when drawing the polyline
946
+ );
947
+ }
948
+
949
+ return R_NIL;
950
+ }
951
+
952
+ /*
953
+ * Ruby2D::Canvas#ext_fill_polygon
954
+ */
955
+ #if MRUBY
956
+ static R_VAL ruby2d_canvas_ext_fill_polygon(mrb_state* mrb, R_VAL self) {
957
+ mrb_value coords, rgbas;
958
+ mrb_get_args(mrb, "oo", &coords, &rgbas);
959
+ #else
960
+ static R_VAL ruby2d_canvas_ext_fill_polygon(R_VAL self, R_VAL coords, R_VAL rgbas) {
961
+ #endif
962
+ // `coords` is an array of x, y values
963
+ // 0, 1, 2, 3, ...
964
+ // [ x1, y1, x2, y2, ... ]
965
+ //
966
+ // `rgbas` is an array of r, g, b, a values
967
+ // 0, 1, 2, 3, 4, 5, 6, 7 ...
968
+ // [ r1, g1, b1, a1, r2, g2, b2, a2, ... ]
969
+
970
+ SDL_Renderer *render;
971
+ r_data_get_struct(self, "@ext_renderer", &renderer_data_type, SDL_Renderer, render);
972
+
973
+ long coord_len = RARRAY_LEN(coords);
974
+ long rgbas_len = RARRAY_LEN(rgbas);
975
+
976
+ if (coord_len >= 6 && rgbas_len > 0) {
977
+ SDL_FPoint points[MAX_POLY_POINTS];
978
+ int num_points = 0;
979
+
980
+ SDL_Color colors[MAX_POLY_POINTS];
981
+ int num_colors = 0;
982
+
983
+ for (int i = 0; i < coord_len && num_points < MAX_POLY_POINTS; i+= 2) {
984
+ points[num_points++] = (SDL_FPoint) {
985
+ .x = NUM2INT(r_ary_entry(coords, i)),
986
+ .y = NUM2INT(r_ary_entry(coords, i+1)) };
987
+ }
988
+ for (int i = 0; i < rgbas_len && num_colors < MAX_POLY_POINTS; i+= 4) {
989
+ colors[num_colors++] = (SDL_Color) {
990
+ .r = NUM2DBL(r_ary_entry(rgbas, i)) * 255, // r
991
+ .g = NUM2DBL(r_ary_entry(rgbas, i+1)) * 255, // g
992
+ .b = NUM2DBL(r_ary_entry(rgbas, i+2)) * 255, // b
993
+ .a = NUM2DBL(r_ary_entry(rgbas, i+3)) * 255 // a
994
+ };
995
+ }
996
+
997
+ R2D_Canvas_FillPolygon(render, points, num_points, colors, num_colors);
998
+ }
999
+
1000
+ return R_NIL;
1001
+ }
1002
+
1003
+ /*
1004
+ * Ruby2D::Canvas#self.ext_fill_ellipse
1005
+ */
1006
+ #if MRUBY
1007
+ static R_VAL ruby2d_canvas_ext_fill_ellipse(mrb_state* mrb, R_VAL self) {
1008
+ mrb_value a;
1009
+ mrb_get_args(mrb, "o", &a);
1010
+ #else
1011
+ static R_VAL ruby2d_canvas_ext_fill_ellipse(R_VAL self, R_VAL a) {
1012
+ #endif
1013
+ // `a` is the array representing the filled circle
1014
+ // 0 1 2 3 4 5 6 7 8
1015
+ // [ x, y, xradius, yradius, sectors, r, g, b, a ]
1016
+ SDL_Renderer *render;
1017
+ r_data_get_struct(self, "@ext_renderer", &renderer_data_type, SDL_Renderer, render);
1018
+
1019
+ SDL_Vertex verts[3];
1020
+ // center
1021
+ float x, y;
1022
+ verts[0].position = (SDL_FPoint) {
1023
+ .x = x = NUM2INT(r_ary_entry(a, 0)),
1024
+ .y = y = NUM2INT(r_ary_entry(a, 1))
1025
+ };
1026
+ // dimensions
1027
+ float xradius = NUM2INT(r_ary_entry(a, 2));
1028
+ float yradius = NUM2INT(r_ary_entry(a, 3));
1029
+ float sectors = NUM2INT(r_ary_entry(a, 4));
1030
+ float unit_angle = 2 * M_PI / sectors;
1031
+
1032
+ // colour all vertices
1033
+ verts[1].color = verts[2].color = verts[0].color = (SDL_Color) {
1034
+ .r = NUM2DBL(r_ary_entry(a, 5)) * 255,
1035
+ .g = NUM2DBL(r_ary_entry(a, 6)) * 255,
1036
+ .b = NUM2DBL(r_ary_entry(a, 7)) * 255,
1037
+ .a = NUM2DBL(r_ary_entry(a, 8)) * 255,
1038
+ };
1039
+
1040
+ // point at 0 radians
1041
+ verts[1].position = (SDL_FPoint) {
1042
+ .x = x + xradius * cosf(0),
1043
+ .y = y + yradius * sinf(0)
1044
+ };
1045
+ for (float i = 1; i <= sectors; i++) {
1046
+ float angle = i * unit_angle;
1047
+ // re-use from previous calculation
1048
+ verts[2].position = verts[1].position;
1049
+ // calculate new point
1050
+ verts[1].position = (SDL_FPoint) {
1051
+ .x = x + xradius * cosf(angle),
1052
+ .y = y + yradius * sinf(angle)
1053
+ };
1054
+ SDL_RenderGeometry(render, NULL, verts, 3, NULL, 0);
1055
+ }
1056
+
1057
+ return R_NIL;
1058
+ }
1059
+
1060
+ /*
1061
+ * Ruby2D::Canvas#self.ext_draw_ellipse
1062
+ */
1063
+ #if MRUBY
1064
+ static R_VAL ruby2d_canvas_ext_draw_ellipse(mrb_state* mrb, R_VAL self) {
1065
+ mrb_value a;
1066
+ mrb_get_args(mrb, "o", &a);
1067
+ #else
1068
+ static R_VAL ruby2d_canvas_ext_draw_ellipse(R_VAL self, R_VAL a) {
1069
+ #endif
1070
+ // `a` is the array representing the ellipse to draw
1071
+ // 0 1 2 3 4 5 6 7 8 9
1072
+ // [ x, y, xradius, yradius, sectors, thickness, r, g, b, a ]
1073
+
1074
+ // thickness
1075
+ int thickness = NUM2INT(r_ary_entry(a, 5));
1076
+ if (thickness <= 0) return R_NIL;
1077
+
1078
+ SDL_Renderer *render;
1079
+ r_data_get_struct(self, "@ext_renderer", &renderer_data_type, SDL_Renderer, render);
1080
+
1081
+ // center
1082
+ float x = NUM2INT(r_ary_entry(a, 0));
1083
+ float y = NUM2INT(r_ary_entry(a, 1)) ;
1084
+ // dimensions
1085
+ float xradius = NUM2INT(r_ary_entry(a, 2));
1086
+ float yradius = NUM2INT(r_ary_entry(a, 3));
1087
+ float sectors = NUM2INT(r_ary_entry(a, 4));
1088
+ // colors
1089
+ int clr_r = NUM2DBL(r_ary_entry(a, 6)) * 255;
1090
+ int clr_g = NUM2DBL(r_ary_entry(a, 7)) * 255;
1091
+ int clr_b = NUM2DBL(r_ary_entry(a, 8)) * 255;
1092
+ int clr_a = NUM2DBL(r_ary_entry(a, 9)) * 255;
1093
+
1094
+ if (thickness > 1) {
1095
+ R2D_Canvas_DrawThickEllipse(render,
1096
+ x, y, xradius, yradius, sectors, thickness,
1097
+ clr_r, clr_g, clr_b, clr_a);
1098
+ }
1099
+ else {
1100
+ R2D_Canvas_DrawThinEllipse(render,
1101
+ x, y, xradius, yradius, sectors,
1102
+ clr_r, clr_g, clr_b, clr_a);
1103
+ }
1104
+
1105
+ return R_NIL;
1106
+ }
1107
+
1108
+ /*
1109
+ * Calculate the cross product of the two lines
1110
+ * connecting the three points clock-wise. A negative value
1111
+ * means the angle "to the right" is > 180.
1112
+ */
1113
+ /* Unused
1114
+ static inline int cross_product_corner(x1, y1, x2, y2, x3, y3) {
1115
+ register int vec1_x = x1 - x2;
1116
+ register int vec1_y = y1 - y2;
1117
+ register int vec2_x = x2 - x3;
1118
+ register int vec2_y = y2 - y3;
1119
+
1120
+ return (vec1_x * vec2_y) - (vec1_y * vec2_x);
1121
+ }
1122
+ */
1123
+
485
1124
  /*
486
1125
  * Ruby2D::Sound#ext_init
487
1126
  * Initialize sound structure data
@@ -510,7 +1149,22 @@ static R_VAL ruby2d_sound_ext_play(R_VAL self) {
510
1149
  #endif
511
1150
  R2D_Sound *snd;
512
1151
  r_data_get_struct(self, "@data", &sound_data_type, R2D_Sound, snd);
513
- R2D_PlaySound(snd);
1152
+ R2D_PlaySound(snd, r_test(r_iv_get(self, "@loop")));
1153
+ return R_NIL;
1154
+ }
1155
+
1156
+
1157
+ /*
1158
+ * Ruby2D::Sound#ext_stop
1159
+ */
1160
+ #if MRUBY
1161
+ static R_VAL ruby2d_sound_ext_stop(mrb_state* mrb, R_VAL self) {
1162
+ #else
1163
+ static R_VAL ruby2d_sound_ext_stop(R_VAL self) {
1164
+ #endif
1165
+ R2D_Sound *snd;
1166
+ r_data_get_struct(self, "@data", &sound_data_type, R2D_Sound, snd);
1167
+ R2D_StopSound(snd);
514
1168
  return R_NIL;
515
1169
  }
516
1170
 
@@ -798,6 +1452,30 @@ static void free_surface(SDL_Surface *surface) {
798
1452
  SDL_FreeSurface(surface);
799
1453
  }
800
1454
 
1455
+ /*
1456
+ * Free SDL texture structure used within the Ruby 2D `Pixmap` class
1457
+ */
1458
+ #if MRUBY
1459
+ static void free_sdl_texture(mrb_state *mrb, void *p_) {
1460
+ SDL_Texture *sdl_texure = (SDL_Texture *)p_;
1461
+ #else
1462
+ static void free_sdl_texture(SDL_Texture *sdl_texure) {
1463
+ #endif
1464
+ SDL_DestroyTexture(sdl_texure);
1465
+ }
1466
+
1467
+ /*
1468
+ * Free renderer structure used within the Ruby 2D `Canvas` class
1469
+ */
1470
+ #if MRUBY
1471
+ static void free_renderer(mrb_state *mrb, void *p_) {
1472
+ SDL_Renderer *renderer = (SDL_Renderer *)p_;
1473
+ #else
1474
+ static void free_renderer(SDL_Renderer *renderer) {
1475
+ #endif
1476
+ SDL_DestroyRenderer(renderer);
1477
+ }
1478
+
801
1479
 
802
1480
  /*
803
1481
  * Free music structure attached to Ruby 2D `Music` class
@@ -1236,11 +1914,11 @@ void Init_ruby2d() {
1236
1914
  // Ruby2D::Circle#self.ext_draw
1237
1915
  r_define_class_method(ruby2d_circle_class, "ext_draw", ruby2d_circle_ext_draw, r_args_req(1));
1238
1916
 
1239
- // Ruby2D::Image
1240
- R_CLASS ruby2d_image_class = r_define_class(ruby2d_module, "Image");
1917
+ // Ruby2D::Pixmap
1918
+ R_CLASS ruby2d_pixmap_class = r_define_class(ruby2d_module, "Pixmap");
1241
1919
 
1242
- // Ruby2D::Image#ext_load_image
1243
- r_define_class_method(ruby2d_image_class, "ext_load_image", ruby2d_image_ext_load_image, r_args_req(1));
1920
+ // Ruby2D::Pixmap#ext_load_pixmap
1921
+ r_define_method(ruby2d_pixmap_class, "ext_load_pixmap", ruby2d_pixmap_ext_load_pixmap, r_args_req(1));
1244
1922
 
1245
1923
  // Ruby2D::Text
1246
1924
  R_CLASS ruby2d_text_class = r_define_class(ruby2d_module, "Text");
@@ -1257,6 +1935,9 @@ void Init_ruby2d() {
1257
1935
  // Ruby2D::Sound#ext_play
1258
1936
  r_define_method(ruby2d_sound_class, "ext_play", ruby2d_sound_ext_play, r_args_none);
1259
1937
 
1938
+ // Ruby2D::Sound#ext_stop
1939
+ r_define_method(ruby2d_sound_class, "ext_stop", ruby2d_sound_ext_stop, r_args_none);
1940
+
1260
1941
  // Ruby2D::Sound#ext_get_volume
1261
1942
  r_define_method(ruby2d_sound_class, "ext_get_volume", ruby2d_sound_ext_get_volume, r_args_none);
1262
1943
 
@@ -1320,6 +2001,42 @@ void Init_ruby2d() {
1320
2001
  // Ruby2D::Texture#ext_delete
1321
2002
  r_define_method(ruby2d_texture_class, "ext_delete", ruby2d_texture_ext_delete, r_args_req(1));
1322
2003
 
2004
+ // Ruby2D::Canvas
2005
+ R_CLASS ruby2d_canvas_class = r_define_class(ruby2d_module, "Canvas");
2006
+
2007
+ // Ruby2D::Canvas#ext_create
2008
+ r_define_method(ruby2d_canvas_class, "ext_create", ruby2d_canvas_ext_create, r_args_req(1));
2009
+
2010
+ // Ruby2D::Canvas#ext_clear
2011
+ r_define_method(ruby2d_canvas_class, "ext_clear", ruby2d_canvas_ext_clear, r_args_req(1));
2012
+
2013
+ // Ruby2D::Canvas#ext_fill_rectangle
2014
+ r_define_method(ruby2d_canvas_class, "ext_fill_rectangle", ruby2d_canvas_ext_fill_rectangle, r_args_req(1));
2015
+
2016
+ // Ruby2D::Canvas#ext_draw_rectangle
2017
+ r_define_method(ruby2d_canvas_class, "ext_draw_rectangle", ruby2d_canvas_ext_draw_rectangle, r_args_req(1));
2018
+
2019
+ // Ruby2D::Canvas#ext_draw_line
2020
+ r_define_method(ruby2d_canvas_class, "ext_draw_line", ruby2d_canvas_ext_draw_line, r_args_req(1));
2021
+
2022
+ // Ruby2D::Canvas#ext_draw_polyline
2023
+ r_define_method(ruby2d_canvas_class, "ext_draw_polyline", ruby2d_canvas_ext_draw_polyline, r_args_req(2));
2024
+
2025
+ // Ruby2D::Canvas#ext_draw_polygon
2026
+ r_define_method(ruby2d_canvas_class, "ext_draw_polygon", ruby2d_canvas_ext_draw_polygon, r_args_req(2));
2027
+
2028
+ // Ruby2D::Canvas#ext_fill_polygon
2029
+ r_define_method(ruby2d_canvas_class, "ext_fill_polygon", ruby2d_canvas_ext_fill_polygon, r_args_req(2));
2030
+
2031
+ // Ruby2D::Canvas#ext_fill_ellipse
2032
+ r_define_method(ruby2d_canvas_class, "ext_fill_ellipse", ruby2d_canvas_ext_fill_ellipse, r_args_req(1));
2033
+
2034
+ // Ruby2D::Canvas#ext_draw_ellipse
2035
+ r_define_method(ruby2d_canvas_class, "ext_draw_ellipse", ruby2d_canvas_ext_draw_ellipse, r_args_req(1));
2036
+
2037
+ // Ruby2D::Canvas#ext_draw_pixmap
2038
+ r_define_method(ruby2d_canvas_class, "ext_draw_pixmap", ruby2d_canvas_ext_draw_pixmap, r_args_req(6));
2039
+
1323
2040
  // Ruby2D::Window
1324
2041
  R_CLASS ruby2d_window_class = r_define_class(ruby2d_module, "Window");
1325
2042