sfml3-rb 0.0.1

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 (58) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.md +14 -0
  3. data/README.md +110 -0
  4. data/ext/circle.c +198 -0
  5. data/ext/clock.c +65 -0
  6. data/ext/color.c +43 -0
  7. data/ext/drawable.c +39 -0
  8. data/ext/event.c +148 -0
  9. data/ext/event_name.c +45 -0
  10. data/ext/exceptions.c +44 -0
  11. data/ext/ext/exceptions.h +16 -0
  12. data/ext/ext/klass/clock.h +12 -0
  13. data/ext/ext/klass/color.h +26 -0
  14. data/ext/ext/klass/drawable/circle.h +12 -0
  15. data/ext/ext/klass/drawable/image.h +4 -0
  16. data/ext/ext/klass/drawable/polygon.h +4 -0
  17. data/ext/ext/klass/drawable/rectangle.h +4 -0
  18. data/ext/ext/klass/drawable/sprite.h +4 -0
  19. data/ext/ext/klass/drawable/texture.h +4 -0
  20. data/ext/ext/klass/event/event_name.h +8 -0
  21. data/ext/ext/klass/event.h +12 -0
  22. data/ext/ext/klass/keyboard.h +8 -0
  23. data/ext/ext/klass/render_state.h +16 -0
  24. data/ext/ext/klass/target.h +18 -0
  25. data/ext/ext/klass/transform.h +17 -0
  26. data/ext/ext/klass/transformable.h +13 -0
  27. data/ext/ext/klass/video_mode.h +12 -0
  28. data/ext/ext/klass/view.h +14 -0
  29. data/ext/ext/klass/window.h +12 -0
  30. data/ext/ext/module/drawable/drawable.h +10 -0
  31. data/ext/ext/module/transform.h +18 -0
  32. data/ext/ext/module.h +10 -0
  33. data/ext/ext/rect.h +16 -0
  34. data/ext/ext/sfml.h +16 -0
  35. data/ext/ext/style_name.h +11 -0
  36. data/ext/ext/vec2.h +38 -0
  37. data/ext/ext.c +47 -0
  38. data/ext/extconf.rb +84 -0
  39. data/ext/image.c +5 -0
  40. data/ext/keyboard.c +135 -0
  41. data/ext/polygon.c +5 -0
  42. data/ext/ports.rb +368 -0
  43. data/ext/rect.c +26 -0
  44. data/ext/rectangle.c +5 -0
  45. data/ext/render_state.c +109 -0
  46. data/ext/sprite.c +5 -0
  47. data/ext/style_name.c +15 -0
  48. data/ext/target.c +106 -0
  49. data/ext/texture.c +5 -0
  50. data/ext/transform.c +107 -0
  51. data/ext/transformable.c +145 -0
  52. data/ext/vec2.c +42 -0
  53. data/ext/video_mode.c +78 -0
  54. data/ext/view.c +170 -0
  55. data/ext/window.c +274 -0
  56. data/lib/sfml/version.rb +3 -0
  57. data/lib/sfml.rb +9 -0
  58. metadata +104 -0
data/ext/keyboard.c ADDED
@@ -0,0 +1,135 @@
1
+ #include "ext/klass/keyboard.h"
2
+
3
+ #include <stddef.h>
4
+ #include <string.h>
5
+
6
+ #include "ext/sfml.h"
7
+
8
+ /* Indexed by sfKeyCode rather than by position: if upstream reorders or
9
+ removes a key, this fails to compile instead of silently renaming every
10
+ key after the change. sfKeyUnknown is -1 and so has no entry. */
11
+ static const char *keys[] = {
12
+ [sfKeyA] = "a",
13
+ [sfKeyB] = "b",
14
+ [sfKeyC] = "c",
15
+ [sfKeyD] = "d",
16
+ [sfKeyE] = "e",
17
+ [sfKeyF] = "f",
18
+ [sfKeyG] = "g",
19
+ [sfKeyH] = "h",
20
+ [sfKeyI] = "i",
21
+ [sfKeyJ] = "j",
22
+ [sfKeyK] = "k",
23
+ [sfKeyL] = "l",
24
+ [sfKeyM] = "m",
25
+ [sfKeyN] = "n",
26
+ [sfKeyO] = "o",
27
+ [sfKeyP] = "p",
28
+ [sfKeyQ] = "q",
29
+ [sfKeyR] = "r",
30
+ [sfKeyS] = "s",
31
+ [sfKeyT] = "t",
32
+ [sfKeyU] = "u",
33
+ [sfKeyV] = "v",
34
+ [sfKeyW] = "w",
35
+ [sfKeyX] = "x",
36
+ [sfKeyY] = "y",
37
+ [sfKeyZ] = "z",
38
+ [sfKeyNum0] = "num0",
39
+ [sfKeyNum1] = "num1",
40
+ [sfKeyNum2] = "num2",
41
+ [sfKeyNum3] = "num3",
42
+ [sfKeyNum4] = "num4",
43
+ [sfKeyNum5] = "num5",
44
+ [sfKeyNum6] = "num6",
45
+ [sfKeyNum7] = "num7",
46
+ [sfKeyNum8] = "num8",
47
+ [sfKeyNum9] = "num9",
48
+ [sfKeyEscape] = "escape",
49
+ [sfKeyLControl] = "LControl",
50
+ [sfKeyLShift] = "LShift",
51
+ [sfKeyLAlt] = "LAlt",
52
+ [sfKeyLSystem] = "LSystem",
53
+ [sfKeyRControl] = "RControl",
54
+ [sfKeyRShift] = "RShift",
55
+ [sfKeyRAlt] = "RAlt",
56
+ [sfKeyRSystem] = "RSystem",
57
+ [sfKeyMenu] = "Menu",
58
+ [sfKeyLBracket] = "LBracket",
59
+ [sfKeyRBracket] = "RBracket",
60
+ [sfKeySemicolon] = "Semicolon",
61
+ [sfKeyComma] = "Comma",
62
+ [sfKeyPeriod] = "Period",
63
+ [sfKeyApostrophe] = "Quote",
64
+ [sfKeySlash] = "Slash",
65
+ [sfKeyBackslash] = "Backslash",
66
+ [sfKeyGrave] = "Tilde",
67
+ [sfKeyEqual] = "Equal",
68
+ [sfKeyHyphen] = "Hyphen",
69
+ [sfKeySpace] = "Space",
70
+ [sfKeyEnter] = "Enter",
71
+ [sfKeyBackspace] = "Backspace",
72
+ [sfKeyTab] = "Tab",
73
+ [sfKeyPageUp] = "PageUp",
74
+ [sfKeyPageDown] = "PageDown",
75
+ [sfKeyEnd] = "End",
76
+ [sfKeyHome] = "Home",
77
+ [sfKeyInsert] = "Insert",
78
+ [sfKeyDelete] = "Delete",
79
+ [sfKeyAdd] = "Add",
80
+ [sfKeySubtract] = "Subtract",
81
+ [sfKeyMultiply] = "Multiply",
82
+ [sfKeyDivide] = "Divide",
83
+ [sfKeyLeft] = "Left",
84
+ [sfKeyRight] = "Right",
85
+ [sfKeyUp] = "Up",
86
+ [sfKeyDown] = "Down",
87
+ [sfKeyNumpad0] = "Numpad0",
88
+ [sfKeyNumpad1] = "Numpad1",
89
+ [sfKeyNumpad2] = "Numpad2",
90
+ [sfKeyNumpad3] = "Numpad3",
91
+ [sfKeyNumpad4] = "Numpad4",
92
+ [sfKeyNumpad5] = "Numpad5",
93
+ [sfKeyNumpad6] = "Numpad6",
94
+ [sfKeyNumpad7] = "Numpad7",
95
+ [sfKeyNumpad8] = "Numpad8",
96
+ [sfKeyNumpad9] = "Numpad9",
97
+ [sfKeyF1] = "f1",
98
+ [sfKeyF2] = "f2",
99
+ [sfKeyF3] = "f3",
100
+ [sfKeyF4] = "f4",
101
+ [sfKeyF5] = "f5",
102
+ [sfKeyF6] = "f6",
103
+ [sfKeyF7] = "f7",
104
+ [sfKeyF8] = "f8",
105
+ [sfKeyF9] = "f9",
106
+ [sfKeyF10] = "f10",
107
+ [sfKeyF11] = "f11",
108
+ [sfKeyF12] = "f12",
109
+ [sfKeyF13] = "f13",
110
+ [sfKeyF14] = "f14",
111
+ [sfKeyF15] = "f15",
112
+ [sfKeyPause] = "pause",
113
+ };
114
+
115
+ #define LENGTH_KEYS (sizeof(keys) / sizeof(keys[0]))
116
+
117
+ int find_key(const char *name) {
118
+ size_t i;
119
+
120
+ for (i = 0; i < LENGTH_KEYS; i++) {
121
+ if (keys[i] != NULL && strcmp(keys[i], name) == 0) {
122
+ return (int) i;
123
+ }
124
+ }
125
+
126
+ return -1;
127
+ }
128
+
129
+ const char *get_key_event(unsigned int key) {
130
+ if (key < LENGTH_KEYS && keys[key] != NULL) {
131
+ return keys[key];
132
+ }
133
+
134
+ return "";
135
+ }
data/ext/polygon.c ADDED
@@ -0,0 +1,5 @@
1
+ //
2
+ // Created by Sealtiel on 03/06/2022.
3
+ //
4
+
5
+ #include "ext/klass/drawable/polygon.h"
data/ext/ports.rb ADDED
@@ -0,0 +1,368 @@
1
+ require 'digest'
2
+ require 'etc'
3
+ require 'fileutils'
4
+ require 'open-uri'
5
+ require 'rbconfig'
6
+
7
+ # Downloads, verifies and builds FreeType, SFML 3 and CSFML 3 from source into
8
+ # ports/<target>, static and position-independent, so the extension links them
9
+ # directly and the resulting .so has no libsfml/libcsfml runtime dependency.
10
+ #
11
+ # This lives under ext/ rather than rakelib/ because the gemspec ships
12
+ # ext/**/*.rb: it has to be inside the gem for `gem install` to build its own
13
+ # dependencies. For the same reason it uses no Rake helpers -- Rake is not
14
+ # guaranteed to be loaded during an extension build.
15
+ #
16
+ # Three entry points call it: `rake ports` (development), ext/extconf.rb
17
+ # (source-gem install time), and `rake gem:native` (cross-compilation inside
18
+ # rake-compiler-dock, which exports SFML_TARGET).
19
+ module Ports
20
+ ROOT = File.expand_path('../ports', __dir__)
21
+ ARCHIVES = File.join(ROOT, 'archives')
22
+
23
+ # Cross targets, keyed by the RubyGems platform name that rake-compiler and
24
+ # rake-compiler-dock use for them. `triple` is the GNU host triple whose
25
+ # toolchain the matching rake-compiler-dock image installs as <triple>-gcc.
26
+ TARGETS = {
27
+ 'x86_64-linux-gnu' => { triple: 'x86_64-linux-gnu', os: :linux, cpu: 'x86_64' },
28
+ 'aarch64-linux-gnu' => { triple: 'aarch64-linux-gnu', os: :linux, cpu: 'aarch64' },
29
+ 'x86_64-linux-musl' => { triple: 'x86_64-unknown-linux-musl', os: :linux, cpu: 'x86_64' },
30
+ 'x64-mingw-ucrt' => { triple: 'x86_64-w64-mingw32', os: :windows, cpu: 'x86_64' },
31
+ 'x86_64-darwin' => { triple: 'x86_64-apple-darwin', os: :darwin, cpu: 'x86_64' },
32
+ 'arm64-darwin' => { triple: 'aarch64-apple-darwin', os: :darwin, cpu: 'arm64' }
33
+ }.freeze
34
+
35
+ CMAKE_SYSTEM = { linux: 'Linux', windows: 'Windows', darwin: 'Darwin' }.freeze
36
+
37
+ # osxcross ships clang wrappers rather than gcc ones.
38
+ COMPILERS = {
39
+ darwin: %w[clang clang++],
40
+ linux: %w[gcc g++],
41
+ windows: %w[gcc g++]
42
+ }.freeze
43
+
44
+ # What the extension links on top of the static SFML/CSFML/FreeType archives.
45
+ # SFML resolves GL entry points through its own loader, so on Linux libGL is
46
+ # only needed for the handful of symbols SFML references directly.
47
+ SYSTEM_LIBS = {
48
+ linux: %w[GL X11 Xrandr Xcursor Xi udev pthread dl rt m],
49
+ windows: %w[opengl32 winmm gdi32 user32 advapi32 ole32],
50
+ darwin: %w[]
51
+ }.freeze
52
+
53
+ # Clang wants -framework, not -l, and SFML's macOS backend is Objective-C++.
54
+ FRAMEWORKS = { darwin: %w[Cocoa OpenGL IOKit Carbon], linux: [], windows: [] }.freeze
55
+
56
+ # Order matters. CSFML does find_package(SFML 3 ... REQUIRED) and does not
57
+ # fetch SFML itself, and SFML does find_package(Freetype REQUIRED) once
58
+ # SFML_USE_SYSTEM_DEPS is on -- so each has to be installed into PREFIX
59
+ # before the next configures.
60
+ #
61
+ # FreeType is built here rather than left to SFML because SFML's own
62
+ # FetchContent path clones it from git (no checksum, needs git at configure
63
+ # time) and then does not install the resulting archive -- which leaves
64
+ # libsfml-graphics-s.a with an undefined FT_Init_FreeType that only stays
65
+ # latent while nothing binds sf::Font. Pinning it as a port fixes both.
66
+ #
67
+ # Audio and network are off because the binding wraps neither, which also
68
+ # drops the FLAC/Ogg/Vorbis and mbedtls dependency families.
69
+ RECIPES = [
70
+ {
71
+ name: 'freetype',
72
+ version: '2.13.2',
73
+ sha256: '1ac27e16c134a7f2ccea177faba19801131116fd682efc1f5737037c5db224b5',
74
+ url: 'https://download.savannah.gnu.org/releases/freetype/freetype-%<version>s.tar.gz',
75
+ # FreeType 2.13.2 still declares cmake_minimum_required(VERSION 3.0),
76
+ # which CMake 4 refuses outright. Older CMake ignores the variable.
77
+ flags: %w[
78
+ -DCMAKE_POLICY_VERSION_MINIMUM=3.5
79
+ -DFT_DISABLE_ZLIB=ON
80
+ -DFT_DISABLE_BZIP2=ON
81
+ -DFT_DISABLE_PNG=ON
82
+ -DFT_DISABLE_HARFBUZZ=ON
83
+ -DFT_DISABLE_BROTLI=ON
84
+ ]
85
+ },
86
+ {
87
+ name: 'SFML',
88
+ version: '3.0.2',
89
+ sha256: '0034e05f95509e5d3fb81b1625713e06da7b068f210288ce3fd67106f8f46995',
90
+ flags: %w[
91
+ -DSFML_USE_SYSTEM_DEPS=ON
92
+ -DSFML_BUILD_AUDIO=OFF
93
+ -DSFML_BUILD_NETWORK=OFF
94
+ -DSFML_BUILD_EXAMPLES=OFF
95
+ -DSFML_BUILD_DOC=OFF
96
+ -DSFML_BUILD_TEST_SUITE=OFF
97
+ ]
98
+ },
99
+ {
100
+ name: 'CSFML',
101
+ version: '3.0.0',
102
+ sha256: '903cd4a782fb0b233f732dc5b37861b552998e93ae8f268c40bd4ce50b2e88ca',
103
+ flags: %w[
104
+ -DCSFML_BUILD_AUDIO=OFF
105
+ -DCSFML_BUILD_NETWORK=OFF
106
+ -DCSFML_BUILD_EXAMPLES=OFF
107
+ -DCSFML_LINK_SFML_STATICALLY=ON
108
+ ]
109
+ }
110
+ ].freeze
111
+
112
+ TOOLCHAIN_HINT = <<~HINT.freeze
113
+ Building SFML from source needs CMake >= 3.22, a C++17 compiler, and the
114
+ X11/udev/OpenGL development headers. SFML links those from the system and
115
+ they cannot be bundled.
116
+
117
+ Fedora/RHEL sudo dnf install cmake gcc-c++ libX11-devel \\
118
+ libXrandr-devel libXcursor-devel libXi-devel systemd-devel libglvnd-devel
119
+
120
+ Debian/Ubuntu sudo apt-get install cmake build-essential libx11-dev \\
121
+ libxrandr-dev libxcursor-dev libxi-dev libudev-dev libgl1-mesa-dev
122
+
123
+ If you already have CSFML 3 installed system-wide, skip this build with:
124
+
125
+ gem install sfml3-rb -- --enable-system-libraries
126
+
127
+ A precompiled binary gem may also be available for your platform; upgrading
128
+ RubyGems (gem update --system) lets it be selected automatically.
129
+ HINT
130
+
131
+ module_function
132
+
133
+ # The RubyGems platform being built for. rake-compiler-dock invocations set
134
+ # this explicitly; a native build falls back to the host triple, which is not
135
+ # a TARGETS key and so uses the native toolchain and native system headers.
136
+ def target
137
+ ENV.fetch('SFML_TARGET', nil) || RbConfig::CONFIG['host']
138
+ end
139
+
140
+ def cross?
141
+ TARGETS.key?(target)
142
+ end
143
+
144
+ def spec
145
+ TARGETS.fetch(target)
146
+ end
147
+
148
+ # Each target gets its own prefix so a cross build never reuses the host's
149
+ # archives -- they are the same file names with an incompatible ABI.
150
+ def prefix
151
+ File.join(ROOT, target)
152
+ end
153
+
154
+ def build_root
155
+ File.join(ROOT, 'build', target)
156
+ end
157
+
158
+ def os
159
+ return spec[:os] if cross?
160
+
161
+ case RbConfig::CONFIG['host_os']
162
+ when /darwin/ then :darwin
163
+ when /mingw|mswin|cygwin/ then :windows
164
+ else :linux
165
+ end
166
+ end
167
+
168
+ def libs
169
+ SYSTEM_LIBS.fetch(os)
170
+ end
171
+
172
+ def frameworks
173
+ FRAMEWORKS.fetch(os)
174
+ end
175
+
176
+ # On Windows the CSFML and SFML headers declare every entry point
177
+ # __declspec(dllimport) unless told the build is static, which leaves the
178
+ # link hunting for __imp_-prefixed symbols that a static archive never has.
179
+ # Applies to any Windows build against the vendored ports, cross or native.
180
+ def defines
181
+ return [] unless os == :windows
182
+
183
+ %w[-DCSFML_STATIC -DSFML_STATIC]
184
+ end
185
+
186
+ # SFML is C++, but mkmf links the extension with `gcc -shared` because every
187
+ # source here is C -- so libstdc++ has to be named explicitly, and
188
+ # -static-libstdc++ does nothing, since it only redirects the -lstdc++ the
189
+ # driver would have added itself.
190
+ #
191
+ # For a binary gem that matters: a Windows user has no libstdc++-6.dll, and
192
+ # a musl one may have no libstdc++ at all. -Bstatic/-Bdynamic pins just this
193
+ # one library to its archive and is understood by both GNU ld and mingw's.
194
+ # macOS resolves C++ through the system libc++ and needs none of it.
195
+ def cxx_runtime
196
+ return [] if os == :darwin
197
+ return ['-lstdc++'] unless cross?
198
+
199
+ ['-Wl,-Bstatic', '-lstdc++', '-Wl,-Bdynamic']
200
+ end
201
+
202
+ def built?
203
+ Dir.exist?(File.join(prefix, 'include', 'CSFML'))
204
+ end
205
+
206
+ def build!
207
+ RECIPES.each do |recipe|
208
+ fetch(recipe)
209
+ compile(recipe)
210
+ end
211
+ end
212
+
213
+ def tarball(recipe)
214
+ File.join(ARCHIVES, "#{recipe[:name]}-#{recipe[:version]}.tar.gz")
215
+ end
216
+
217
+ def source_dir(recipe)
218
+ File.join(build_root, "#{recipe[:name]}-#{recipe[:version]}")
219
+ end
220
+
221
+ def fetch(recipe)
222
+ path = tarball(recipe)
223
+ download(recipe, path) unless File.exist?(path)
224
+
225
+ actual = Digest::SHA256.file(path).hexdigest
226
+ return if actual == recipe[:sha256]
227
+
228
+ # Never build unverified source: remove it so a retry re-downloads.
229
+ File.delete(path)
230
+ raise "#{File.basename(path)} failed checksum verification\n" \
231
+ "expected #{recipe[:sha256]}\nactual #{actual}"
232
+ end
233
+
234
+ def url_for(recipe)
235
+ template = recipe[:url] ||
236
+ "https://github.com/SFML/#{recipe[:name]}/archive/refs/tags/%<version>s.tar.gz"
237
+ format(template, version: recipe[:version])
238
+ end
239
+
240
+ def download(recipe, path)
241
+ url = url_for(recipe)
242
+ puts "Downloading #{url}"
243
+
244
+ FileUtils.mkdir_p(ARCHIVES)
245
+ partial = "#{path}.part"
246
+
247
+ begin
248
+ # URI.parse(...).open rather than URI.open: the latter routes through
249
+ # Kernel#open semantics, where a "|command" string would be executed.
250
+ URI.parse(url).open { |remote| IO.copy_stream(remote, partial) }
251
+ rescue StandardError => e
252
+ FileUtils.rm_f(partial)
253
+ raise "Could not download #{url}: #{e.message}\n\n" \
254
+ "`gem install` needs network access to build SFML from source.\n" \
255
+ "#{TOOLCHAIN_HINT}"
256
+ end
257
+
258
+ # Only becomes the real tarball once complete, so an interrupted download
259
+ # cannot be mistaken for a cached one on the next run.
260
+ FileUtils.mv(partial, path)
261
+ end
262
+
263
+ # CMAKE_INSTALL_LIBDIR is pinned because GNUInstallDirs otherwise picks lib64
264
+ # on Fedora/RHEL and lib on Debian, which would split the ports across two
265
+ # directories that extconf would then both have to know about.
266
+ def common_flags
267
+ flags = %W[
268
+ -DCMAKE_INSTALL_PREFIX=#{prefix}
269
+ -DCMAKE_PREFIX_PATH=#{prefix}
270
+ -DCMAKE_BUILD_TYPE=Release
271
+ -DBUILD_SHARED_LIBS=OFF
272
+ -DCMAKE_POSITION_INDEPENDENT_CODE=ON
273
+ -DCMAKE_INSTALL_LIBDIR=lib
274
+ ]
275
+ flags << "-DCMAKE_TOOLCHAIN_FILE=#{toolchain_file}" if cross?
276
+ flags
277
+ end
278
+
279
+ # The musl toolchain rake-compiler-dock builds with musl-cross-make installs
280
+ # its sysroot here, and build/provision.sh unpacks Alpine's X11 development
281
+ # files into it.
282
+ def musl_sysroot
283
+ "/usr/#{spec[:triple]}"
284
+ end
285
+
286
+ # osxcross keeps the macOS SDK under its target directory; the exact version
287
+ # tracks the rake-compiler-dock image, so find it rather than pin it.
288
+ def osx_sysroot
289
+ ENV.fetch('SFML_OSX_SYSROOT', nil) ||
290
+ Dir.glob('/opt/osxcross/target/SDK/MacOSX*.sdk').max ||
291
+ raise("No macOS SDK found under /opt/osxcross/target/SDK.\n#{TOOLCHAIN_HINT}")
292
+ end
293
+
294
+ # Written rather than shipped because the prefix and triple are only known at
295
+ # build time, and CMake needs a real file path for CMAKE_TOOLCHAIN_FILE.
296
+ def toolchain_file
297
+ path = File.join(build_root, 'toolchain.cmake')
298
+ return path if File.exist?(path)
299
+
300
+ FileUtils.mkdir_p(build_root)
301
+ File.write(path, toolchain_source)
302
+ path
303
+ end
304
+
305
+ def toolchain_source
306
+ cc, cxx = COMPILERS.fetch(spec[:os])
307
+ roots = [prefix]
308
+ lines = [
309
+ "set(CMAKE_SYSTEM_NAME #{CMAKE_SYSTEM.fetch(spec[:os])})",
310
+ "set(CMAKE_SYSTEM_PROCESSOR #{spec[:cpu]})",
311
+ "set(CMAKE_C_COMPILER #{spec[:triple]}-#{cc})",
312
+ "set(CMAKE_CXX_COMPILER #{spec[:triple]}-#{cxx})"
313
+ ]
314
+
315
+ case spec[:os]
316
+ when :windows
317
+ lines << "set(CMAKE_RC_COMPILER #{spec[:triple]}-windres)"
318
+ when :darwin
319
+ # SFML's macOS backend is Objective-C++, so the SDK has to be visible to
320
+ # the frameworks lookup as well as to the compiler.
321
+ lines << "set(CMAKE_OSX_SYSROOT #{osx_sysroot})"
322
+ lines << "set(CMAKE_OSX_ARCHITECTURES #{spec[:cpu]})"
323
+ roots << osx_sysroot
324
+ when :linux
325
+ if spec[:triple].include?('musl')
326
+ lines << "set(CMAKE_SYSROOT #{musl_sysroot})"
327
+ roots << musl_sysroot << "#{musl_sysroot}/usr"
328
+ else
329
+ # Debian multiarch: without this CMake searches /usr/lib, finds the
330
+ # container's own amd64 libraries and hands them to an aarch64 linker.
331
+ lines << "set(CMAKE_LIBRARY_ARCHITECTURE #{spec[:triple]})"
332
+ end
333
+ end
334
+
335
+ <<~CMAKE
336
+ #{lines.join("\n")}
337
+
338
+ # Look for headers and libraries in the target's sysroot and in our own
339
+ # prefix, but run build tools from the host.
340
+ set(CMAKE_FIND_ROOT_PATH #{roots.join(';')})
341
+ set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
342
+ set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)
343
+ set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)
344
+ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH)
345
+ CMAKE
346
+ end
347
+
348
+ def compile(recipe)
349
+ source = source_dir(recipe)
350
+ build = "#{source}-build"
351
+
352
+ unless Dir.exist?(source)
353
+ FileUtils.mkdir_p(build_root)
354
+ run('tar', 'xzf', tarball(recipe), '-C', build_root)
355
+ end
356
+
357
+ puts "Building #{recipe[:name]} #{recipe[:version]} for #{target}"
358
+ run('cmake', '-S', source, '-B', build, *common_flags, *recipe[:flags])
359
+ run('cmake', '--build', build, '--parallel', Etc.nprocessors.to_s)
360
+ run('cmake', '--install', build)
361
+ end
362
+
363
+ def run(*command)
364
+ return if system(*command)
365
+
366
+ raise "Command failed: #{command.join(' ')}\n\n#{TOOLCHAIN_HINT}"
367
+ end
368
+ end
data/ext/rect.c ADDED
@@ -0,0 +1,26 @@
1
+ #include "ext/rect.h"
2
+
3
+ #include <stdio.h>
4
+ #include <stdlib.h>
5
+
6
+ #include <ext/sfml.h>
7
+ #include <ext/module.h>
8
+
9
+ VALUE Rect_new(float x, float y, float width, float height) {
10
+ VALUE arr;
11
+
12
+ arr = rb_ary_new();
13
+
14
+ rb_ary_store(arr, 0, DBL2NUM(x));
15
+ rb_ary_store(arr, 1, DBL2NUM(y));
16
+ rb_ary_store(arr, 2, DBL2NUM(width));
17
+ rb_ary_store(arr, 3, DBL2NUM(height));
18
+
19
+ return arr;
20
+ }
21
+
22
+ void Rect_check(VALUE rb_arr) {
23
+ if (rb_array_len(rb_arr) != 4) {
24
+ rb_raise(rb_eArgError, "invalid length of array");
25
+ }
26
+ }
data/ext/rectangle.c ADDED
@@ -0,0 +1,5 @@
1
+ //
2
+ // Created by Sealtiel on 03/06/2022.
3
+ //
4
+
5
+ #include "ext/klass/drawable/rectangle.h"
@@ -0,0 +1,109 @@
1
+ #include "ext/klass/render_state.h"
2
+
3
+ #include <ruby.h>
4
+ #include <stdio.h>
5
+
6
+ #include "ext/module/transform.h"
7
+ #include "ext/klass/transformable.h"
8
+ #include "ext/vec2.h"
9
+ #include "ext/rect.h"
10
+ #include "ext/module.h"
11
+ #include "ext/sfml.h"
12
+
13
+ static VALUE rb_cRenderState;
14
+
15
+ static sfRenderStates *RenderStates_create(sfTransform transform) {
16
+ sfRenderStates *states = malloc(sizeof(sfRenderStates));
17
+
18
+ states->transform = transform;
19
+ states->blendMode = sfBlendAlpha;
20
+ states->texture = NULL;
21
+ states->shader = NULL;
22
+
23
+ return states;
24
+ }
25
+
26
+ static void RenderStates_free(void *ptr) {
27
+ free(ptr);
28
+ }
29
+
30
+ static VALUE RenderStates_new(int argc, VALUE *argv, VALUE klass) {
31
+ float c_matrix[MATRIX_LENGTH] = DefaultMatrix3x3();
32
+ sfRenderStates *states;
33
+ sfTransform transform;
34
+ VALUE self;
35
+
36
+ if (argc > 1) {
37
+ rb_raise(rb_eArgError, "invalid number of arguments");
38
+ }
39
+
40
+ if (argc == 1) {
41
+ VALUE rb_arr = argv[0];
42
+
43
+ if (TYPE(rb_arr) == T_ARRAY) {
44
+ if (rb_array_len(rb_arr) != 9) {
45
+ rb_raise(rb_eArgError, "invalid length array");
46
+ }
47
+
48
+ Transform_ArrayToMatrix(rb_arr, c_matrix);
49
+ }
50
+ }
51
+
52
+ Transform_SwapMatrix(c_matrix, transform.matrix);
53
+
54
+ states = RenderStates_create(transform);
55
+ self = Data_Wrap_Struct(klass, 0, RenderStates_free, states);
56
+
57
+ rb_obj_call_init(self, argc, argv);
58
+
59
+ return self;
60
+ }
61
+
62
+ static VALUE RenderStates_init(int argc, VALUE *argv, VALUE self) {
63
+ return self;
64
+ }
65
+
66
+ static VALUE RenderStates_set_matrix(VALUE self, VALUE rb_matrix) {
67
+ float c_matrix[MATRIX_LENGTH];
68
+ sfRenderStates *states;
69
+
70
+ states = Get_RenderState_Struct(self);
71
+
72
+ Transform_ArrayToMatrix(rb_matrix, c_matrix);
73
+ Transform_SwapMatrix(c_matrix, states->transform.matrix);
74
+
75
+ return self;
76
+ }
77
+
78
+ static VALUE RenderStates_get_matrix(VALUE self) {
79
+ return Transform_MatrixToArray(((sfRenderStates *) Get_RenderState_Struct(self))->transform.matrix);
80
+ }
81
+
82
+ void Init_RenderState(VALUE rb_module) {
83
+ rb_cRenderState = rb_define_class_under(rb_module, "RenderState", rb_cObject);
84
+
85
+ rb_define_singleton_method(rb_cRenderState, "new", RenderStates_new, -1);
86
+
87
+ // methods
88
+ rb_define_method(rb_cRenderState, "initialize", RenderStates_init, -1);
89
+
90
+ // setters
91
+ rb_define_method(rb_cRenderState, "matrix=", RenderStates_set_matrix, 1);
92
+
93
+ // getters
94
+ rb_define_method(rb_cRenderState, "matrix", RenderStates_get_matrix, 0);
95
+ }
96
+
97
+ void *Get_RenderState_Struct(VALUE self) {
98
+ sfRenderStates *states;
99
+ Data_Get_Struct(self, sfRenderStates, states);
100
+ return states;
101
+ }
102
+
103
+ VALUE Get_Klass_RenderState(void) {
104
+ return rb_cRenderState;
105
+ }
106
+
107
+ VALUE Get_New_RenderState(void) {
108
+ return RenderStates_new(0, NULL, Get_Klass_RenderState());
109
+ }
data/ext/sprite.c ADDED
@@ -0,0 +1,5 @@
1
+ //
2
+ // Created by Sealtiel on 03/06/2022.
3
+ //
4
+
5
+ #include "ext/klass/drawable/sprite.h"
data/ext/style_name.c ADDED
@@ -0,0 +1,15 @@
1
+ #include "ext/style_name.h"
2
+
3
+ const char *styles[STYLES_LENGTH] = {"none", "titlebar", "resize", "close", "fullscreen", "default"};
4
+
5
+ int search_style_name(const char *style) {
6
+ int i;
7
+
8
+ for (i = 0; i < STYLES_LENGTH; i++) {
9
+ if (strcmp(styles[i], style) != 0) {
10
+ return i;
11
+ }
12
+ }
13
+
14
+ return -1;
15
+ }