ruby2d 0.11.3 → 0.12.1

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/{windows/glew → include/GL}/glew.h +26427 -23686
  3. data/assets/include/GLES2/gl2.h +656 -0
  4. data/assets/include/GLES2/gl2ext.h +3949 -0
  5. data/assets/include/GLES2/gl2ext_angle.h +701 -0
  6. data/assets/include/GLES2/gl2platform.h +27 -0
  7. data/assets/include/GLES3/gl3.h +1192 -0
  8. data/assets/include/GLES3/gl31.h +1507 -0
  9. data/assets/include/GLES3/gl32.h +1808 -0
  10. data/assets/include/GLES3/gl3platform.h +27 -0
  11. data/assets/include/KHR/khrplatform.h +290 -0
  12. data/assets/include/SDL2/SDL.h +1 -0
  13. data/assets/include/SDL2/SDL_assert.h +4 -2
  14. data/assets/include/SDL2/SDL_atomic.h +20 -0
  15. data/assets/include/SDL2/SDL_audio.h +40 -4
  16. data/assets/include/SDL2/SDL_blendmode.h +4 -6
  17. data/assets/include/SDL2/SDL_clipboard.h +47 -0
  18. data/assets/include/SDL2/SDL_config.h +6 -2
  19. data/assets/include/SDL2/SDL_config_android.h +2 -0
  20. data/assets/include/SDL2/SDL_config_emscripten.h +2 -0
  21. data/assets/include/SDL2/SDL_config_iphoneos.h +3 -1
  22. data/assets/include/SDL2/SDL_config_macosx.h +3 -6
  23. data/assets/include/SDL2/SDL_config_minimal.h +18 -11
  24. data/assets/include/SDL2/SDL_config_ngage.h +89 -0
  25. data/assets/include/SDL2/SDL_config_os2.h +5 -3
  26. data/assets/include/SDL2/SDL_config_pandora.h +1 -0
  27. data/assets/include/SDL2/SDL_config_windows.h +71 -45
  28. data/assets/include/SDL2/SDL_config_wingdk.h +253 -0
  29. data/assets/include/SDL2/SDL_config_winrt.h +11 -49
  30. data/assets/include/SDL2/SDL_config_xbox.h +235 -0
  31. data/assets/include/SDL2/SDL_cpuinfo.h +39 -4
  32. data/assets/include/SDL2/SDL_egl.h +59 -9
  33. data/assets/include/SDL2/SDL_endian.h +34 -3
  34. data/assets/include/SDL2/SDL_events.h +32 -1
  35. data/assets/include/SDL2/SDL_filesystem.h +5 -1
  36. data/assets/include/SDL2/SDL_gamecontroller.h +78 -5
  37. data/assets/include/SDL2/SDL_guid.h +100 -0
  38. data/assets/include/SDL2/SDL_hints.h +645 -43
  39. data/assets/include/SDL2/SDL_image.h +2045 -33
  40. data/assets/include/SDL2/SDL_joystick.h +127 -7
  41. data/assets/include/SDL2/SDL_keyboard.h +38 -1
  42. data/assets/include/SDL2/SDL_keycode.h +6 -1
  43. data/assets/include/SDL2/SDL_log.h +2 -2
  44. data/assets/include/SDL2/SDL_main.h +42 -2
  45. data/assets/include/SDL2/SDL_metal.h +2 -1
  46. data/assets/include/SDL2/SDL_mixer.h +2529 -396
  47. data/assets/include/SDL2/SDL_mouse.h +12 -1
  48. data/assets/include/SDL2/SDL_opengl.h +0 -51
  49. data/assets/include/SDL2/SDL_opengl_glext.h +2260 -231
  50. data/assets/include/SDL2/SDL_opengles2_gl2.h +374 -339
  51. data/assets/include/SDL2/SDL_opengles2_gl2ext.h +3479 -1496
  52. data/assets/include/SDL2/SDL_opengles2_gl2platform.h +6 -9
  53. data/assets/include/SDL2/SDL_opengles2_khrplatform.h +43 -14
  54. data/assets/include/SDL2/SDL_platform.h +32 -6
  55. data/assets/include/SDL2/SDL_rect.h +154 -2
  56. data/assets/include/SDL2/SDL_render.h +46 -17
  57. data/assets/include/SDL2/SDL_revision.h +4 -0
  58. data/assets/include/SDL2/SDL_rwops.h +1 -15
  59. data/assets/include/SDL2/SDL_scancode.h +46 -21
  60. data/assets/include/SDL2/SDL_sensor.h +24 -3
  61. data/assets/include/SDL2/SDL_stdinc.h +119 -8
  62. data/assets/include/SDL2/SDL_surface.h +3 -1
  63. data/assets/include/SDL2/SDL_system.h +66 -6
  64. data/assets/include/SDL2/SDL_syswm.h +2 -0
  65. data/assets/include/SDL2/SDL_test_common.h +1 -0
  66. data/assets/include/SDL2/SDL_test_font.h +90 -3
  67. data/assets/include/SDL2/SDL_thread.h +3 -3
  68. data/assets/include/SDL2/SDL_touch.h +8 -0
  69. data/assets/include/SDL2/SDL_ttf.h +2084 -155
  70. data/assets/include/SDL2/SDL_version.h +19 -3
  71. data/assets/include/SDL2/SDL_video.h +71 -9
  72. data/assets/include/SDL2/begin_code.h +4 -4
  73. data/assets/include/mrbconf.h +15 -17
  74. data/assets/include/mruby/array.h +8 -21
  75. data/assets/include/mruby/boxing_nan.h +115 -86
  76. data/assets/include/mruby/boxing_word.h +104 -78
  77. data/assets/include/mruby/common.h +6 -0
  78. data/assets/include/mruby/compile.h +3 -4
  79. data/assets/include/mruby/debug.h +4 -2
  80. data/assets/include/mruby/dump.h +5 -2
  81. data/assets/include/mruby/error.h +12 -2
  82. data/assets/include/mruby/gc.h +2 -0
  83. data/assets/include/mruby/hash.h +1 -3
  84. data/assets/include/mruby/irep.h +4 -4
  85. data/assets/include/mruby/numeric.h +21 -13
  86. data/assets/include/mruby/opcode.h +30 -0
  87. data/assets/include/mruby/ops.h +99 -101
  88. data/assets/include/mruby/presym/scanning.h +15 -9
  89. data/assets/include/mruby/proc.h +4 -2
  90. data/assets/include/mruby/string.h +3 -24
  91. data/assets/include/mruby/value.h +80 -40
  92. data/assets/include/mruby/variable.h +0 -15
  93. data/assets/include/mruby/version.h +5 -5
  94. data/assets/include/mruby.h +86 -16
  95. data/assets/macos/universal/bin/mrbc +0 -0
  96. data/assets/macos/universal/lib/libFLAC.a +0 -0
  97. data/assets/macos/universal/lib/libSDL2.a +0 -0
  98. data/assets/macos/universal/lib/libSDL2_image.a +0 -0
  99. data/assets/macos/universal/lib/libSDL2_mixer.a +0 -0
  100. data/assets/macos/universal/lib/libSDL2_ttf.a +0 -0
  101. data/assets/macos/universal/lib/libavif.a +0 -0
  102. data/assets/macos/universal/lib/libbrotlicommon-static.a +0 -0
  103. data/assets/macos/universal/lib/libbrotlidec-static.a +0 -0
  104. data/assets/macos/universal/lib/libfreetype.a +0 -0
  105. data/assets/macos/universal/lib/libgraphite2.a +0 -0
  106. data/assets/macos/universal/lib/libharfbuzz.a +0 -0
  107. data/assets/macos/universal/lib/libhwy.a +0 -0
  108. data/assets/macos/universal/lib/libjpeg.a +0 -0
  109. data/assets/macos/universal/lib/libjxl.a +0 -0
  110. data/assets/macos/universal/lib/libmodplug.a +0 -0
  111. data/assets/macos/universal/lib/libmpg123.a +0 -0
  112. data/assets/macos/universal/lib/libmruby.a +0 -0
  113. data/assets/macos/universal/lib/libogg.a +0 -0
  114. data/assets/macos/universal/lib/libpng.a +0 -0
  115. data/assets/macos/universal/lib/libtiff.a +0 -0
  116. data/assets/macos/universal/lib/libvorbis.a +0 -0
  117. data/assets/macos/universal/lib/libvorbisfile.a +0 -0
  118. data/assets/macos/universal/lib/libwebp.a +0 -0
  119. data/assets/macos/universal/lib/libzstd.a +0 -0
  120. data/assets/wasm/template.html +2 -1
  121. data/assets/windows/mingw-w64-ucrt-x86_64/bin/mrbc.exe +0 -0
  122. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libFLAC.a +0 -0
  123. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libLerc.a +0 -0
  124. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2.a +0 -0
  125. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_image.a +0 -0
  126. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_mixer.a +0 -0
  127. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_ttf.a +0 -0
  128. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libbrotlicommon.a +0 -0
  129. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libbrotlidec.a +0 -0
  130. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libdeflate.a +0 -0
  131. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libfreetype.a +0 -0
  132. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libglew32.a +0 -0
  133. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libharfbuzz.a +0 -0
  134. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libhwy.a +0 -0
  135. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libjpeg.a +0 -0
  136. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libjxl.a +0 -0
  137. data/assets/windows/mingw-w64-ucrt-x86_64/lib/liblzma.a +0 -0
  138. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libmpg123.a +0 -0
  139. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libmruby.a +0 -0
  140. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libopus.a +0 -0
  141. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libpng.a +0 -0
  142. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libsndfile.a +0 -0
  143. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libssp.a +0 -0
  144. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libstdc++.a +0 -0
  145. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libtiff.a +0 -0
  146. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libwebp.a +0 -0
  147. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libz.a +0 -0
  148. data/assets/windows/mingw-w64-x86_64/bin/mrbc.exe +0 -0
  149. data/assets/windows/mingw-w64-x86_64/lib/libFLAC.a +0 -0
  150. data/assets/windows/mingw-w64-x86_64/lib/libLerc.a +0 -0
  151. data/assets/windows/mingw-w64-x86_64/lib/libSDL2.a +0 -0
  152. data/assets/windows/mingw-w64-x86_64/lib/libSDL2_image.a +0 -0
  153. data/assets/windows/mingw-w64-x86_64/lib/libSDL2_mixer.a +0 -0
  154. data/assets/windows/mingw-w64-x86_64/lib/libSDL2_ttf.a +0 -0
  155. data/assets/windows/mingw-w64-x86_64/lib/libbrotlicommon.a +0 -0
  156. data/assets/windows/mingw-w64-x86_64/lib/libbrotlidec.a +0 -0
  157. data/assets/windows/mingw-w64-x86_64/lib/libdeflate.a +0 -0
  158. data/assets/windows/mingw-w64-x86_64/lib/libfreetype.a +0 -0
  159. data/assets/windows/mingw-w64-x86_64/lib/libglew32.a +0 -0
  160. data/assets/windows/mingw-w64-x86_64/lib/libharfbuzz.a +0 -0
  161. data/assets/windows/mingw-w64-x86_64/lib/libhwy.a +0 -0
  162. data/assets/windows/mingw-w64-x86_64/lib/libjpeg.a +0 -0
  163. data/assets/windows/mingw-w64-x86_64/lib/libjxl.a +0 -0
  164. data/assets/windows/mingw-w64-x86_64/lib/liblzma.a +0 -0
  165. data/assets/windows/mingw-w64-x86_64/lib/libmpg123.a +0 -0
  166. data/assets/windows/mingw-w64-x86_64/lib/libmruby.a +0 -0
  167. data/assets/windows/mingw-w64-x86_64/lib/libopus.a +0 -0
  168. data/assets/windows/mingw-w64-x86_64/lib/libpng.a +0 -0
  169. data/assets/windows/mingw-w64-x86_64/lib/libsndfile.a +0 -0
  170. data/assets/windows/mingw-w64-x86_64/lib/libssp.a +0 -0
  171. data/assets/windows/mingw-w64-x86_64/lib/libstdc++.a +0 -0
  172. data/assets/windows/mingw-w64-x86_64/lib/libtiff.a +0 -0
  173. data/assets/windows/mingw-w64-x86_64/lib/libwebp.a +0 -0
  174. data/assets/windows/mingw-w64-x86_64/lib/libz.a +0 -0
  175. data/assets/windows/mingw-w64-x86_64/lib/libzstd.a +0 -0
  176. data/ext/ruby2d/canvas.c +540 -0
  177. data/ext/ruby2d/extconf.rb +33 -20
  178. data/ext/ruby2d/gl.c +3 -3
  179. data/ext/ruby2d/image.c +7 -7
  180. data/ext/ruby2d/ruby2d.c +741 -24
  181. data/ext/ruby2d/ruby2d.h +66 -3
  182. data/ext/ruby2d/sound.c +16 -2
  183. data/lib/ruby2d/canvas.rb +315 -0
  184. data/lib/ruby2d/circle.rb +30 -15
  185. data/lib/ruby2d/cli/build.rb +5 -3
  186. data/lib/ruby2d/cli/enable_console.rb +3 -1
  187. data/lib/ruby2d/color.rb +133 -77
  188. data/lib/ruby2d/core.rb +32 -0
  189. data/lib/ruby2d/dsl.rb +38 -32
  190. data/lib/ruby2d/exceptions.rb +2 -1
  191. data/lib/ruby2d/font.rb +97 -62
  192. data/lib/ruby2d/image.rb +48 -27
  193. data/lib/ruby2d/line.rb +84 -45
  194. data/lib/ruby2d/music.rb +33 -23
  195. data/lib/ruby2d/pixel.rb +10 -9
  196. data/lib/ruby2d/pixmap.rb +39 -0
  197. data/lib/ruby2d/pixmap_atlas.rb +56 -0
  198. data/lib/ruby2d/quad.rb +98 -49
  199. data/lib/ruby2d/rectangle.rb +35 -36
  200. data/lib/ruby2d/renderable.rb +7 -6
  201. data/lib/ruby2d/sound.rb +23 -17
  202. data/lib/ruby2d/sprite.rb +181 -140
  203. data/lib/ruby2d/square.rb +21 -20
  204. data/lib/ruby2d/text.rb +47 -19
  205. data/lib/ruby2d/texture.rb +13 -3
  206. data/lib/ruby2d/tileset.rb +97 -44
  207. data/lib/ruby2d/triangle.rb +91 -42
  208. data/lib/ruby2d/version.rb +3 -1
  209. data/lib/ruby2d/vertices.rb +81 -45
  210. data/lib/ruby2d/window.rb +508 -371
  211. data/lib/ruby2d.rb +11 -29
  212. metadata +66 -16
  213. data/assets/include/SDL2/SDL_config_psp.h +0 -165
  214. data/assets/include/SDL2/SDL_config_wiz.h +0 -154
  215. data/assets/include/glew.h +0 -23686
  216. data/assets/macos/universal/lib/libpng16.a +0 -0
  217. data/assets/windows/glew/README.md +0 -10
  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
@@ -0,0 +1,540 @@
1
+ // canvas.c
2
+
3
+ #include "ruby2d.h"
4
+
5
+ typedef SDL_FPoint vector_t;
6
+
7
+ static float vector_magnitude(const vector_t *vec)
8
+ {
9
+ return sqrtf((vec->x * vec->x) + (vec->y * vec->y));
10
+ }
11
+
12
+ static vector_t *vector_normalize(vector_t *vec)
13
+ {
14
+ float mag = vector_magnitude(vec);
15
+ if (mag == 0)
16
+ mag = INFINITY;
17
+ vec->x /= mag;
18
+ vec->y /= mag;
19
+ return vec;
20
+ }
21
+
22
+ static vector_t *vector_perpendicular(vector_t *vec)
23
+ {
24
+ float tmp_x = vec->x;
25
+ vec->x = vec->y;
26
+ vec->y = -tmp_x;
27
+ return vec;
28
+ }
29
+
30
+ static vector_t *vector_times_scalar(vector_t *vec, float value)
31
+ {
32
+ vec->x *= value;
33
+ vec->y *= value;
34
+ return vec;
35
+ }
36
+
37
+ static vector_t *vector_minus_vector(vector_t *vec, const vector_t *other)
38
+ {
39
+ vec->x -= other->x;
40
+ vec->y -= other->y;
41
+ return vec;
42
+ }
43
+
44
+ /* Unused
45
+ static vector_t *vector_minus_xy(vector_t *vec, float other_x, float other_y)
46
+ {
47
+ vec->x -= other_x;
48
+ vec->y -= other_y;
49
+ return vec;
50
+ }
51
+ */
52
+
53
+ static vector_t *vector_plus_vector(vector_t *vec, const vector_t *other)
54
+ {
55
+ vec->x += other->x;
56
+ vec->y += other->y;
57
+ return vec;
58
+ }
59
+
60
+ /* Unused
61
+ static vector_t *vector_plus_xy(vector_t *vec, float other_x, float other_y)
62
+ {
63
+ vec->x += other_x;
64
+ vec->y += other_y;
65
+ return vec;
66
+ }
67
+ */
68
+
69
+ typedef enum { CONCAVE = -1, INVALID, CONVEX } poly_type_e;
70
+
71
+ //
72
+ // Go through each corner and identify and count the number of concave
73
+ // ones, also noting down the last concave point.
74
+ //
75
+ // TODO: collect all the concave points for a later ear-clipper.
76
+ // @param [int *] pconcave_ix Pointer to array of slots for concave point
77
+ // indices
78
+ // @param [int] max_pconcave Max number of clots for concave point indices
79
+ //
80
+ // @return number of concave points; note this may be > +max_pconcave+ so caller
81
+ // needs to check result carefully.
82
+ //
83
+ static int count_concave_corners(const SDL_FPoint *points, int num_points,
84
+ int *pconcave_ix, const int max_pconcave)
85
+ {
86
+ // triangles are always convex
87
+ if (num_points <= 3)
88
+ return (0);
89
+
90
+ int nconcave = 0;
91
+
92
+ // pick first last and first points
93
+ int x1 = points[0].x;
94
+ int y1 = points[0].y;
95
+ int x2 = points[1].x;
96
+ int y2 = points[1].y;
97
+ // start with second point and proceed point by point inspecting
98
+ // each corner
99
+ float z, zprev = 0;
100
+ for (int i = 1; i < num_points; i++, zprev = z) {
101
+ int j = (i + 1) % num_points;
102
+ int x3 = points[j].x;
103
+ int y3 = points[j].y;
104
+ // cross product
105
+ z = ((x1 - x2) * (y2 - y3)) - ((y1 - y2) * (x2 - x3));
106
+ if (z < 0) {
107
+ if (nconcave < max_pconcave)
108
+ *pconcave_ix++ = i;
109
+ nconcave++;
110
+ }
111
+ // shift points left so we
112
+ x1 = x2;
113
+ y1 = y2;
114
+ x2 = x3;
115
+ y2 = y3;
116
+ }
117
+ return nconcave;
118
+ }
119
+
120
+ //
121
+ // If a polygon is entirely conves, we triangulate trivially
122
+ // by using the first point as the anchor to fan out the triangles
123
+ static void fill_convex_polygon(SDL_Renderer *render, const SDL_FPoint *points,
124
+ int num_points, const SDL_Color *colors,
125
+ int num_colors)
126
+ {
127
+ // Setup the vertices from incoming arguments
128
+ SDL_Vertex verts[3];
129
+
130
+ // use first vertex as anchor and draw a triangle with
131
+ // subsequent pair of points.
132
+ verts[0].position = points[0];
133
+ verts[0].color = colors[0];
134
+ for (int i = 2; i < num_points; i++) {
135
+ verts[1].position = points[i - 1];
136
+ verts[1].color = colors[(i - 1) % num_colors];
137
+ verts[2].position = points[i];
138
+ verts[2].color = colors[i % num_colors];
139
+ SDL_RenderGeometry(render, NULL, verts, 3, NULL, 0);
140
+ }
141
+ }
142
+
143
+ //
144
+ // If a polygon has one concave corner, we can still do trivial
145
+ // triangulation as we do for convex polygons using the
146
+ // concave corner as the anchor point for the fan-out.
147
+ static void fill_concave1pt_polygon(SDL_Renderer *render,
148
+ const SDL_FPoint *points, int num_points,
149
+ int anchor_ix, const SDL_Color *colors,
150
+ int num_colors)
151
+ {
152
+ // Setup the vertices from incoming arguments
153
+ SDL_Vertex verts[3];
154
+
155
+ verts[0].position = points[anchor_ix];
156
+ verts[0].color = colors[anchor_ix % num_colors];
157
+ anchor_ix = (anchor_ix + 1) % num_points;
158
+ for (int i = 2; i < num_points; i++) {
159
+ verts[1].position = points[anchor_ix];
160
+ verts[1].color = colors[anchor_ix % num_colors];
161
+ anchor_ix = (anchor_ix + 1) % num_points;
162
+ verts[2].position = points[anchor_ix];
163
+ verts[2].color = colors[anchor_ix % num_colors];
164
+ SDL_RenderGeometry(render, NULL, verts, 3, NULL, 0);
165
+ }
166
+ }
167
+
168
+ #define MAX_CONCAVE_POINT_INDICES 32
169
+
170
+ /*
171
+ * Fill a polygon with a single colour.
172
+ * @param points Array of points
173
+ * @param num_points Number of points
174
+ * @param colors Array of colours
175
+ * @param num_colors Number of colors, must be at least 1, and may be less than
176
+ * +num_points+ in which case the colours will be repeated
177
+ * via modulo.
178
+ * @note Currently supports only: convex polygons or simple polygons with one
179
+ * concave corner. For now.
180
+ */
181
+ void R2D_Canvas_FillPolygon(SDL_Renderer *render, SDL_FPoint *points,
182
+ int num_points, SDL_Color *colors, int num_colors)
183
+ {
184
+ if (num_points < 3)
185
+ return;
186
+
187
+ // poly_type_e type = polygon_type(points, num_points);
188
+ int concave_point_indices[MAX_CONCAVE_POINT_INDICES];
189
+
190
+ int nconcave =
191
+ num_points == 3
192
+ ? 0 // triangles are always convex
193
+ : count_concave_corners(points, num_points, concave_point_indices,
194
+ MAX_CONCAVE_POINT_INDICES);
195
+
196
+ if (nconcave == 0) {
197
+ // convex
198
+ fill_convex_polygon(render, points, num_points, colors, num_colors);
199
+ }
200
+ else if (nconcave == 1) {
201
+ // use concave point as the origin if only one concave vertex
202
+ fill_concave1pt_polygon(render, points, num_points,
203
+ concave_point_indices[0], colors, num_colors);
204
+ }
205
+ // else
206
+ // printf("TODO: Non-convex polygon with %d concave corners\n", nconcave);
207
+ }
208
+
209
+ /*
210
+ * Draw a thick line on a canvas using a pre-converted RGBA colour value.
211
+ * @param [int] thickness must be > 1, else does nothing
212
+ */
213
+ void R2D_Canvas_DrawThickLine(SDL_Renderer *render, int x1, int y1, int x2,
214
+ int y2, int thickness, int r, int g, int b, int a)
215
+ {
216
+
217
+ if (thickness <= 1)
218
+ return;
219
+
220
+ vector_t vec = {.x = (x2 - x1), .y = (y2 - y1)};
221
+
222
+ // calculate perpendicular with half-thickness in place
223
+ vector_times_scalar(vector_perpendicular(vector_normalize(&vec)),
224
+ thickness / 2.0f);
225
+
226
+ // calculate perp vertices based on thickness
227
+ SDL_Vertex verts[4];
228
+
229
+ verts[0].position = (SDL_FPoint){.x = x1 + vec.x, .y = y1 + vec.y};
230
+ verts[1].position = (SDL_FPoint){.x = x2 + vec.x, .y = y2 + vec.y};
231
+ verts[2].position = (SDL_FPoint){.x = x2 - vec.x, .y = y2 - vec.y};
232
+ verts[3].position = (SDL_FPoint){.x = x1 - vec.x, .y = y1 - vec.y};
233
+
234
+ // set the vertex colour
235
+ for (register int i = 0; i < 4; i++) {
236
+ verts[i].color = (SDL_Color){.r = r, .g = g, .b = b, .a = a};
237
+ }
238
+
239
+ // sub-divide the two triangles; we know this is convex
240
+ int indices[] = {0, 1, 2, 2, 3, 0};
241
+ SDL_RenderGeometry(render, NULL, verts, 4, indices, 6);
242
+ }
243
+
244
+ /*
245
+ * Draw a thick rectangle on a canvas using a pre-converted RGBA colour value.
246
+ * @param [int] thickness must be > 1, else does nothing
247
+ */
248
+ void R2D_Canvas_DrawThickRect(SDL_Renderer *render, int x, int y, int width,
249
+ int height, int thickness, int r, int g, int b,
250
+ int a)
251
+ {
252
+ if (thickness <= 1) {
253
+ return;
254
+ }
255
+
256
+ float half_thick = thickness / 2.0f;
257
+ SDL_Vertex verts[8];
258
+
259
+ // all points have the same colour so
260
+ verts[0].color = (SDL_Color){.r = r, .g = g, .b = b, .a = a};
261
+ for (register int i = 1; i < 8; i++) {
262
+ verts[i].color = verts[0].color;
263
+ }
264
+
265
+ // outer coords
266
+ verts[0].position = (SDL_FPoint){.x = x - half_thick, .y = y - half_thick};
267
+ verts[1].position =
268
+ (SDL_FPoint){.x = x + width + half_thick, .y = y - half_thick};
269
+ verts[2].position =
270
+ (SDL_FPoint){.x = x + width + half_thick, .y = y + height + half_thick};
271
+ verts[3].position =
272
+ (SDL_FPoint){.x = x - half_thick, .y = y + height + half_thick};
273
+
274
+ // inner coords
275
+ verts[4].position = (SDL_FPoint){.x = x + half_thick, .y = y + half_thick};
276
+ verts[5].position =
277
+ (SDL_FPoint){.x = x + width - half_thick, .y = y + half_thick};
278
+ verts[6].position =
279
+ (SDL_FPoint){.x = x + width - half_thick, .y = y + height - half_thick};
280
+ verts[7].position =
281
+ (SDL_FPoint){.x = x + half_thick, .y = y + height - half_thick};
282
+
283
+ int indices[] = {
284
+ 0, 4, 1, // top outer triangle
285
+ 4, 1, 5, // inner
286
+ 1, 5, 2, // right outer
287
+ 5, 2, 6, // inner
288
+ 2, 6, 3, // bottom outer
289
+ 6, 3, 7, // inner
290
+ 3, 7, 0, // left outer
291
+ 7, 0, 4 // inner
292
+ };
293
+ SDL_RenderGeometry(render, NULL, verts, 8, indices, 24);
294
+ }
295
+
296
+ /*
297
+ * Draw a thick ellipse on a canvas using a pre-converted RGBA colour value.
298
+ * @param [int] thickness must be > 1, else does nothing
299
+ */
300
+ void R2D_Canvas_DrawThickEllipse(SDL_Renderer *render, int x, int y,
301
+ float xradius, float yradius, float sectors,
302
+ int thickness, int r, int g, int b, int a)
303
+ {
304
+ if (thickness <= 1) {
305
+ return;
306
+ }
307
+
308
+ // renders a thick circle by treating each segment as a monotonic quad
309
+ // and rendering as two triangles per segment
310
+ SDL_Vertex verts[4];
311
+
312
+ // colour all vertices
313
+ verts[3].color = verts[2].color = verts[1].color = verts[0].color =
314
+ (SDL_Color){.r = r, .g = g, .b = b, .a = a};
315
+ float half_thick = thickness / 2.0f;
316
+ SDL_FPoint outer_radius = {.x = xradius + half_thick,
317
+ .y = yradius + half_thick};
318
+ SDL_FPoint inner_radius = {.x = xradius - half_thick,
319
+ .y = yradius - half_thick};
320
+ float cache_cosf = cosf(0), cache_sinf = sinf(0);
321
+ float unit_angle = 2 * M_PI / sectors;
322
+
323
+ int indices[] = {0, 1, 3, 3, 1, 2};
324
+
325
+ // point at 0 radians
326
+ verts[0].position = (SDL_FPoint){.x = x + outer_radius.x * cache_cosf,
327
+ .y = y + outer_radius.y * cache_sinf};
328
+ verts[3].position = (SDL_FPoint){.x = x + inner_radius.x * cache_cosf,
329
+ .y = y + inner_radius.y * cache_sinf};
330
+ for (float i = 1; i <= sectors; i++) {
331
+ float angle = i * unit_angle;
332
+ // re-use index 0 and 3 from previous calculation
333
+ verts[1].position = verts[0].position;
334
+ verts[2].position = verts[3].position;
335
+ // calculate new index 0 and 3 values
336
+ cache_cosf = cosf(angle);
337
+ cache_sinf = sinf(angle);
338
+ verts[0].position = (SDL_FPoint){.x = x + outer_radius.x * cache_cosf,
339
+ .y = y + outer_radius.y * cache_sinf};
340
+ verts[3].position = (SDL_FPoint){.x = x + inner_radius.x * cache_cosf,
341
+ .y = y + inner_radius.y * cache_sinf};
342
+ SDL_RenderGeometry(render, NULL, verts, 4, indices, 6);
343
+ }
344
+ }
345
+
346
+ /*
347
+ * Draw a thin (single pixel) ellipse on a canvas using a pre-converted RGBA
348
+ * colour value.
349
+ */
350
+ void R2D_Canvas_DrawThinEllipse(SDL_Renderer *render, int x, int y,
351
+ float xradius, float yradius, float sectors,
352
+ int r, int g, int b, int a)
353
+ {
354
+ float unit_angle = 2 * M_PI / sectors;
355
+ // point at 0 radians
356
+ float x1 = x + xradius * cosf(0);
357
+ float y1 = y + yradius * sinf(0);
358
+ SDL_SetRenderDrawColor(render, r, g, b, a);
359
+ for (float i = 1; i <= sectors; i++) {
360
+ float angle = i * unit_angle;
361
+ // re-use from previous calculation
362
+ float x2 = x1;
363
+ float y2 = y1;
364
+ // calculate new point
365
+ x1 = x + xradius * cosf(angle);
366
+ y1 = y + yradius * sinf(angle);
367
+ SDL_RenderDrawLine(render, x1, y1, x2, y2);
368
+ }
369
+ }
370
+
371
+ /*
372
+ * Compute the intersection between two lines represented by the input line
373
+ * segments. Unlike a typical line segment collision detector, this function
374
+ * will find a possible intersection point even if that point is not on either
375
+ * of the input line "segments". This helps find where two line segments "would"
376
+ * intersect if they were long enough, in addition to the case when the segments
377
+ * intersect.
378
+ * @param line1_p1
379
+ * @param line1_p2
380
+ * @param line2_p1
381
+ * @param line2_p2
382
+ * @param intersection Pointer into which to write the point of intersection.
383
+ * @return true if an intersection is found, false if the lines are parallel
384
+ * (collinear).
385
+ */
386
+ static bool intersect_two_lines(const vector_t *line1_p1,
387
+ const vector_t *line1_p2,
388
+ const vector_t *line2_p1,
389
+ const vector_t *line2_p2,
390
+ vector_t *intersection)
391
+ {
392
+ vector_t alpha = {.x = line1_p2->x - line1_p1->x,
393
+ .y = line1_p2->y - line1_p1->y};
394
+ vector_t beta = {.x = line2_p1->x - line2_p2->x,
395
+ .y = line2_p1->y - line2_p2->y};
396
+ float denom = (alpha.y * beta.x) - (alpha.x * beta.y);
397
+
398
+ if (denom == 0)
399
+ return false; // collinear
400
+
401
+ vector_t theta = {.x = line1_p1->x - line2_p1->x,
402
+ .y = line1_p1->y - line2_p1->y};
403
+ float alpha_numerator = beta.y * theta.x - (beta.x * theta.y);
404
+
405
+ intersection->x = alpha.x;
406
+ intersection->y = alpha.y;
407
+ vector_times_scalar(intersection, alpha_numerator / denom);
408
+ vector_plus_vector(intersection, line1_p1);
409
+ return true;
410
+ }
411
+
412
+ #define POLYLINE_RENDER_NVERTS 6
413
+ #define POLYLINE_RENDER_NINDICES 6
414
+
415
+ /*
416
+ * Draw a thick N-point polyline, with a mitre join where two
417
+ * segments are joined.
418
+ * @param [int] thickness must be > 1, else does nothing
419
+ */
420
+ void R2D_Canvas_DrawThickPolyline(SDL_Renderer *render, SDL_FPoint *points,
421
+ int num_points, int thickness, int r, int g,
422
+ int b, int a, bool skip_first_last)
423
+ {
424
+ if (thickness <= 1)
425
+ return;
426
+ if (num_points < 3)
427
+ return;
428
+
429
+ float thick_half = thickness / 2.0f;
430
+
431
+ // Prepare to store the different points used map
432
+ // the triangles that render the thick polyline
433
+ SDL_Vertex verts[POLYLINE_RENDER_NVERTS];
434
+
435
+ // all points have the same colour so
436
+ for (int i = 0; i < POLYLINE_RENDER_NVERTS; i++) {
437
+ verts[i].color = (SDL_Color){.r = r, .g = g, .b = b, .a = a};
438
+ }
439
+
440
+ // the indices into the vertex, always the same two triangles
441
+ const int indices[] = {
442
+ 0, 1, 2, // left outer triangle
443
+ 0, 2, 3, // left inner triangle
444
+ };
445
+
446
+ // Setup the first segment
447
+ int x1 = points[0].x, y1 = points[0].y;
448
+ int x2 = points[1].x, y2 = points[1].y;
449
+
450
+ // calculate the unit perpendicular for each of the line segments
451
+ vector_t vec_one_perp = {.x = (x2 - x1), .y = (y2 - y1)};
452
+ vector_times_scalar(vector_normalize(vector_perpendicular(&vec_one_perp)),
453
+ thick_half);
454
+
455
+ // left outer bottom
456
+ verts[0].position =
457
+ (SDL_FPoint){.x = x1 + vec_one_perp.x, .y = y1 + vec_one_perp.y};
458
+ // left outer top
459
+ verts[1].position =
460
+ (SDL_FPoint){.x = x2 + vec_one_perp.x, .y = y2 + vec_one_perp.y};
461
+ // left inner top
462
+ verts[2].position =
463
+ (SDL_FPoint){.x = x2 - vec_one_perp.x, .y = y2 - vec_one_perp.y};
464
+ // left inner bottom
465
+ verts[3].position =
466
+ (SDL_FPoint){.x = x1 - vec_one_perp.x, .y = y1 - vec_one_perp.y};
467
+
468
+ //
469
+ // go through each subsequent point to work with the two segments and
470
+ // figure out how they join, and then render the
471
+ // left segment.
472
+ // then shift the vertices left to work on the next and so on
473
+ // until we have one last segment left after the loop is done
474
+ for (int pix = 2; pix < num_points; pix++) {
475
+
476
+ int x3 = points[pix].x, y3 = points[pix].y;
477
+ if (x3 == x2 && y3 == y2)
478
+ continue;
479
+
480
+ vector_t vec_two_perp = {.x = (x3 - x2), .y = (y3 - y2)};
481
+ vector_times_scalar(vector_normalize(vector_perpendicular(&vec_two_perp)),
482
+ thick_half);
483
+
484
+ // right inner bottom
485
+ verts[4].position =
486
+ (SDL_FPoint){.x = x3 - vec_two_perp.x, .y = y3 - vec_two_perp.y};
487
+ // right outer bottom
488
+ verts[5].position =
489
+ (SDL_FPoint){.x = x3 + vec_two_perp.x, .y = y3 + vec_two_perp.y};
490
+
491
+ // temporarily calculate the "right inner top" to
492
+ // figure out the intersection with the "left inner top" which
493
+ vector_t tmp = {.x = x2 - vec_two_perp.x, .y = y2 - vec_two_perp.y};
494
+ // find intersection of the left/right inner lines
495
+ bool has_intersect = intersect_two_lines(
496
+ &verts[3].position, &verts[2].position, // left inner line
497
+ &verts[4].position, &tmp, // right inner line
498
+ &verts[2].position // over-write with intersection
499
+ );
500
+
501
+ if (has_intersect) {
502
+ // not collinear
503
+ // adjust the "left outer top" point so that it's distance from (x2, y2)
504
+ // is the same as the left/right "inner top" intersection we calculated
505
+ // above
506
+ tmp = (vector_t){.x = x2, .y = y2};
507
+ vector_minus_vector(&tmp, &verts[2].position);
508
+ verts[1].position = (SDL_FPoint){.x = x2 + tmp.x, .y = y2 + tmp.y};
509
+ }
510
+ //
511
+ // TODO: handle degenerate case that can result in crazy long mitre join
512
+ // point
513
+ //
514
+ if (pix > 2 || !skip_first_last) {
515
+ // we only render the "left" segment of this particular segment pair
516
+ SDL_RenderGeometry(render, NULL, verts, POLYLINE_RENDER_NVERTS, indices,
517
+ POLYLINE_RENDER_NINDICES);
518
+ }
519
+
520
+ // shift left
521
+ // i.e. (x2, y2) becomes the first point in the next triple
522
+ // (x3, y3) becomes the second point
523
+ // and their respective calculated thick corners are shifted as well
524
+ // ans t
525
+ x1 = x2;
526
+ y1 = y2;
527
+ x2 = x3;
528
+ y2 = y3;
529
+ verts[0].position = verts[1].position;
530
+ verts[3].position = verts[2].position;
531
+ verts[2].position = verts[4].position;
532
+ verts[1].position = verts[5].position;
533
+ }
534
+
535
+ if (!skip_first_last) {
536
+ // we render the last segment.
537
+ SDL_RenderGeometry(render, NULL, verts, POLYLINE_RENDER_NVERTS, indices,
538
+ POLYLINE_RENDER_NINDICES);
539
+ }
540
+ }
@@ -75,19 +75,38 @@ def set_rpi_flags
75
75
  end
76
76
 
77
77
 
78
+ # Set flags for Linux and BSD
79
+ def set_linux_bsd_flags
80
+ check_sdl
81
+ set_rpi_flags
82
+ add_flags(:ld, "-lSDL2 -lSDL2_image -lSDL2_mixer -lSDL2_ttf -lm")
83
+ if $RUBY2D_PLATFORM == :linux then add_flags(:ld, '-lGL') end
84
+ end
85
+
86
+
78
87
  # Use SDL and other libraries installed by the user (not those bundled with the gem)
79
88
  def use_usr_libs
80
- # Add flags
81
- set_rpi_flags
82
- add_flags(:c, '-I/usr/local/include')
89
+ case $RUBY2D_PLATFORM
90
+ when :macos
91
+ add_flags(:c, `sdl2-config --cflags`)
92
+ add_flags(:c, '-I/opt/homebrew/include')
93
+ add_flags(:ld, `sdl2-config --libs`)
94
+ add_flags(:ld, '-lSDL2 -lSDL2_image -lSDL2_mixer -lSDL2_ttf')
95
+ add_flags(:ld, '-Wl,-framework,OpenGL')
96
+ when :windows
97
+ add_flags(:ld, '-lSDL2 -lSDL2_image -lSDL2_mixer -lSDL2_ttf')
98
+ add_flags(:ld, '-lopengl32 -lglew32')
99
+ when :linux_rpi
100
+ set_linux_bsd_flags
101
+ end
83
102
  end
84
103
 
85
104
 
86
105
  # Configure native extension ###################################################
87
106
 
88
107
  # Build Ruby 2D native extention using libraries installed by user
89
- # To use install flag: `gem install ruby2d -- libs`
90
- if ARGV.include? 'libs'
108
+ # To use install flag: `gem install ruby2d -- dev`
109
+ if ARGV.include? 'dev'
91
110
  use_usr_libs
92
111
 
93
112
  # Use libraries provided by the gem (default)
@@ -101,21 +120,11 @@ else
101
120
  ldir = "#{Dir.pwd}/../../assets/macos/universal/lib"
102
121
 
103
122
  add_flags(:ld, "#{ldir}/libSDL2.a #{ldir}/libSDL2_image.a #{ldir}/libSDL2_mixer.a #{ldir}/libSDL2_ttf.a")
104
- add_flags(:ld, "#{ldir}/libjpeg.a #{ldir}/libpng16.a #{ldir}/libtiff.a #{ldir}/libwebp.a")
123
+ add_flags(:ld, "#{ldir}/libjpeg.a #{ldir}/libjxl.a #{ldir}/libavif.a #{ldir}/libzstd.a #{ldir}/libbrotlicommon-static.a #{ldir}/libbrotlidec-static.a #{ldir}/libhwy.a #{ldir}/libpng.a #{ldir}/libtiff.a #{ldir}/libwebp.a")
105
124
  add_flags(:ld, "#{ldir}/libmpg123.a #{ldir}/libogg.a #{ldir}/libFLAC.a #{ldir}/libvorbis.a #{ldir}/libvorbisfile.a #{ldir}/libmodplug.a")
106
125
  add_flags(:ld, "#{ldir}/libfreetype.a #{ldir}/libharfbuzz.a #{ldir}/libgraphite2.a")
107
- add_flags(:ld, "-Wl,-framework,Cocoa -Wl,-framework,GameController -Wl,-framework,ForceFeedback")
108
-
109
- # Delete the quarantine attribute on the mruby compiler executable
110
- # (This may not be needed)
111
- # system "xattr -d com.apple.quarantine #{Dir.pwd}/../../assets/macos/universal/bin/mrbc"
112
-
113
- when :linux, :linux_rpi, :bsd
114
- check_sdl
115
-
116
- set_rpi_flags
117
- add_flags(:ld, "-lSDL2 -lSDL2_image -lSDL2_mixer -lSDL2_ttf -lm")
118
- if $RUBY2D_PLATFORM == :linux then add_flags(:ld, '-lGL') end
126
+ add_flags(:ld, "-lz -lbz2 -liconv -lstdc++")
127
+ add_flags(:ld, "-Wl,-framework,Cocoa -Wl,-framework,Carbon -Wl,-framework,GameController -Wl,-framework,ForceFeedback -Wl,-framework,OpenGL -Wl,-framework,AudioToolbox -Wl,-framework,CoreAudio -Wl,-framework,IOKit -Wl,-framework,CoreHaptics -Wl,-framework,CoreVideo -Wl,-framework,Metal")
119
128
 
120
129
  when :windows
121
130
  add_flags(:c, '-I../../assets/include')
@@ -134,8 +143,8 @@ else
134
143
 
135
144
  # SDL2_image
136
145
  add_flags(:ld, "#{ldir}/libSDL2_image.a")
137
- add_flags(:ld, "#{ldir}/libjpeg.a #{ldir}/libpng16.a #{ldir}/libtiff.a #{ldir}/libwebp.a")
138
- add_flags(:ld, "#{ldir}/libjbig.a #{ldir}/libdeflate.a #{ldir}/liblzma.a #{ldir}/libzstd.a #{ldir}/libLerc.a")
146
+ add_flags(:ld, "#{ldir}/libjpeg.a #{ldir}/libpng.a #{ldir}/libtiff.a #{ldir}/libwebp.a")
147
+ add_flags(:ld, "#{ldir}/libjxl.a #{ldir}/libhwy.a #{ldir}/libjbig.a #{ldir}/libdeflate.a #{ldir}/liblzma.a #{ldir}/libzstd.a #{ldir}/libLerc.a")
139
148
 
140
149
  # SDL2_mixer
141
150
  add_flags(:ld, "#{ldir}/libSDL2_mixer.a")
@@ -154,12 +163,16 @@ else
154
163
  # End linker flags
155
164
  add_flags(:ld, "-Wl,--end-group")
156
165
 
166
+ when :linux, :linux_rpi, :bsd
167
+ set_linux_bsd_flags
168
+
157
169
  # If can't detect the platform, use libraries installed by the user
158
170
  else
159
171
  use_usr_libs
160
172
  end
161
173
  end
162
174
 
175
+ $CFLAGS.gsub!(/\n/, ' ') # remove newlines in flags, they can cause problems
163
176
  $LDFLAGS.gsub!(/\n/, ' ') # remove newlines in flags, they can cause problems
164
177
 
165
178
  # Create Makefile
data/ext/ruby2d/gl.c CHANGED
@@ -299,7 +299,7 @@ int R2D_GL_Init(R2D_Window *window) {
299
299
  /*
300
300
  * Creates a texture for rendering
301
301
  */
302
- void R2D_GL_CreateTexture(GLuint *id, GLint format,
302
+ void R2D_GL_CreateTexture(GLuint *id, GLint internalFormat, GLint format, GLenum type,
303
303
  int w, int h,
304
304
  const GLvoid *data, GLint filter) {
305
305
 
@@ -311,8 +311,8 @@ void R2D_GL_CreateTexture(GLuint *id, GLint format,
311
311
 
312
312
  // Specifies the 2D texture image
313
313
  glTexImage2D(
314
- GL_TEXTURE_2D, 0, format, w, h,
315
- 0, format, GL_UNSIGNED_BYTE, data
314
+ GL_TEXTURE_2D, 0, internalFormat, w, h,
315
+ 0, format, type, data
316
316
  );
317
317
 
318
318
  // Set the filtering mode
data/ext/ruby2d/image.c CHANGED
@@ -14,15 +14,15 @@ SDL_Surface *R2D_CreateImageSurface(const char *path) {
14
14
 
15
15
  // Load image from file as SDL_Surface
16
16
  SDL_Surface *surface = IMG_Load(path);
17
+ if (surface != NULL) {
18
+ int bits_per_color = surface->format->Amask == 0 ?
19
+ surface->format->BitsPerPixel / 3 :
20
+ surface->format->BitsPerPixel / 4;
17
21
 
18
- int bits_per_color = surface->format->Amask == 0 ?
19
- surface->format->BitsPerPixel / 3 :
20
- surface->format->BitsPerPixel / 4;
21
-
22
- if (bits_per_color < 8) {
23
- R2D_Log(R2D_WARN, "`%s` has less than 8 bits per color and will likely not render correctly", path, bits_per_color);
22
+ if (bits_per_color < 8) {
23
+ R2D_Log(R2D_WARN, "`%s` has less than 8 bits per color and will likely not render correctly", path, bits_per_color);
24
+ }
24
25
  }
25
-
26
26
  return surface;
27
27
  }
28
28