sfml3-rb 0.2.1-x86-linux-gnu

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 84809cc4c794953cd58bf5e6b31f3385c6ea182a598ed088b0182e988df24b5b
4
+ data.tar.gz: cfe291ff0fadfcaf2c42d494ab93d848086b63e33b39d32458436f65d25ca9af
5
+ SHA512:
6
+ metadata.gz: 57d54f51846fe483d5b7b271309b91790bba97732246c53f4ebe2be5573956ee637a4aa023cf3b39838274fe4b905901d850473eb83ba74a98b8ad372558ba1e
7
+ data.tar.gz: 59fee398a04effffa6fb60d0cd7cb4cbe58fd5ae787ee5a8b302d1c9df88c32b02c9188060731d494164aa59badc1dcc0902e47b8bab5abeb2a6827cf3a90d64
data/CHANGELOG.md ADDED
@@ -0,0 +1,321 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.2.1]
10
+
11
+ ### Added
12
+ * **`SFML::Transform` is now a class**, wrapping `sfTransform` by value. It previously exposed
13
+ only `combine` and `inverse` as module functions over plain 9-element Arrays, leaving 11 of
14
+ CSFML's 13 transform functions unbound: you could read a matrix out of a `Sprite` but not build
15
+ one, apply one to a point, or compose one. It now has `Transform.identity` / `IDENTITY`,
16
+ `Transform.from_a`, `#to_a`/`#matrix`, `#gl_matrix`, `#==`, `#translate!`, `#rotate!`,
17
+ `#scale!` (the last two taking an optional centre), non-mutating `#translate`/`#rotate`/
18
+ `#scale`, `#transform_point`, `#transform_rect`, `#combine!`, `#*`, `#inverse` and `#copy`.
19
+ * **`map_pixel_to_coords` and `map_coords_to_pixel` on both render targets.** The screen-to-world
20
+ conversion behind every click-to-select interaction; without it a zoomed, rotated or
21
+ viewport-shifted `View` could not be hit-tested from Ruby at all.
22
+ * **`SFML::Window` gained the render-target methods only `RenderTexture` had**: `clear_stencil`,
23
+ `clear_color_and_stencil`, `viewport`, `scissor` and `srgb?`. Both classes also gained
24
+ `push_gl_states`, `pop_gl_states`, `reset_gl_states`, `draw_primitives` and
25
+ `draw_vertex_buffer_range`. The shared surface is generated once from
26
+ `ext/graphics/render_target.inc`, the same way `ext/audio/sound_source.inc` already serves the
27
+ three sound sources.
28
+ * `SFML::View.from_rect`, `View#scissor` and `View#scissor=`.
29
+ * `SFML::Transformable#inverse_transform` and `#copy` — every subclass (`Sprite`, `Text`,
30
+ `Circle`, `RectangleShape`, `ConvexShape`, `Shape`) already had both.
31
+ * `SFML::Texture.srgb`, `.srgb_from_stream`, `.srgb_from_image`, `Texture#resize_srgb` and
32
+ `Texture#swap`.
33
+ * `SFML::Shader#set_vec4_array`, `#set_mat3_array` and `#set_mat4_array`, completing the array
34
+ uniforms alongside the existing float/vec2/vec3 forms.
35
+ * `SFML::Circle#point_count=`, `SFML::VertexBuffer#swap`, `SFML::Window.from_handle` and
36
+ `SFML::Window#create_vulkan_surface`.
37
+
38
+ ### Fixed
39
+ * **Non-ASCII text and window titles were mangled.** `Text#string=`, `Window#title=`, window
40
+ creation and `FtpDirectoryResponse#directory` passed UTF-8 bytes to CSFML's `const char*`
41
+ entry points, which hand them to `sf::String`'s narrow-character constructor and decode them
42
+ with the C locale: `"héllo"` came back as `U+0068 U+FFFFFFFF U+FFFFFFFF U+006C U+006C U+006F`.
43
+ All four now go through the UTF-32 entry points and round-trip exactly, including astral-plane
44
+ characters. The converters live in `ext/core/unicode.c`.
45
+ * **`Mouse.position`, `Mouse.position=` and `Touch.position` reinterpret-cast `sfRenderWindow*`
46
+ to `sfWindowBase*`**, relying on the base being at offset 0 — true of CSFML 3.0.0's layout but
47
+ not guaranteed by it. They now call `sfMouse_getPositionRenderWindow`,
48
+ `sfMouse_setPositionRenderWindow` and `sfTouch_getPositionRenderWindow`, which CSFML ships for
49
+ exactly this reason. Ruby-visible behaviour is unchanged.
50
+ * `Shader#set_float_array`, `#set_vec2_array` and `#set_vec3_array` leaked their conversion
51
+ buffer if an element raised part-way through. All six array setters are now generated from one
52
+ macro built on `ALLOCV_N`, whose buffer Ruby frees while unwinding.
53
+ * `VertexBuffer#update` had the same leak; it now shares `vertices_from_rb`, which validates
54
+ every element before allocating anything.
55
+ * **Audio-thread callbacks re-entered the VM from a foreign native thread.** The
56
+ `SoundStream#on_get_data` / `#on_seek` callbacks and the effect processor run on SFML's audio
57
+ thread, which Ruby never created; calling back into Ruby from it (`rb_thread_call_with_gvl`) is
58
+ a fatal VM error. Each now hands off to one shared Ruby-owned worker
59
+ (`ext/core/foreign_thread.c`). `SoundSource#stop`, `Sound#buffer=` and the `Sound` / `Music` /
60
+ `SoundStream` destructors release the GVL while they wait on the audio thread, and a processor
61
+ that times out degrades to a full buffer of silence rather than stalling playback.
62
+
63
+ ### Changed
64
+ * `Window` is created through `sfRenderWindow_createUnicode` rather than `sfRenderWindow_create`,
65
+ so a title given at construction is subject to the same UTF-8 fix as `#title=`.
66
+ * `RenderTexture#viewport` and `#scissor` now take the view as an *optional* argument; omitting
67
+ it means the target's current view, matching CSFML's `NULL`.
68
+
69
+ ## [0.2.0]
70
+
71
+ ### Added
72
+ * **Full Audio binding.** `SFML::Listener`, `SFML::SoundSourceCone`, `SFML::SoundBuffer`,
73
+ `SFML::Sound`, `SFML::Music`, `SFML::SoundStream`, `SFML::SoundRecorder` and
74
+ `SFML::SoundBufferRecorder`, plus the `SFML::SoundStatus` and `SFML::SoundChannel` enums. The
75
+ shared sound-source surface (play/pause/stop/status, pitch, pan, volume, spatialization,
76
+ position/direction/velocity, cone, doppler and attenuation factors, distance/gain bounds and
77
+ playing offset) is generated once from `ext/audio/sound_source.inc` for all three source classes.
78
+ `SoundStream` and `SoundRecorder` are subclassable through `#on_get_data`/`#on_seek` and
79
+ `#on_process`/`#on_start`/`#on_stop`; their callbacks re-enter Ruby under the GVL and treat an
80
+ exception as "stop", since they run on SFML's audio thread.
81
+ * **Full Network binding.** `SFML::IpAddress` (string/bytes/integer constructors, `NONE`, `ANY`,
82
+ `LOCAL_HOST`, `BROADCAST`, local/public lookup), `SFML::Packet` (raw data plus every typed
83
+ reader/writer), `SFML::SocketSelector`, `SFML::TcpSocket`, `SFML::TcpListener`,
84
+ `SFML::UdpSocket`, `SFML::Http`/`HttpRequest`/`HttpResponse`, `SFML::Ftp` with its response,
85
+ directory-response and listing-response classes, and the `SocketStatus`, `HttpMethod`,
86
+ `HttpStatus`, `FtpStatus` and `FtpTransferMode` enums.
87
+ * `SFML::SoundSource#effect_processor=` accepts a Ruby proc. Because `sfEffectProcessor` carries
88
+ no `userData` (so one C callback cannot tell which source invoked it), the binding dispatches
89
+ through a bounded pool of C thunks, one per active source; exceeding the pool raises.
90
+
91
+ ### Changed
92
+ * The vendored CSFML/SFML archives are now linked by **full path** instead of `-l`. mkmf puts the
93
+ host's `-L/usr/lib64` ahead of the ports prefix, which made `-lfreetype` (and the new codec
94
+ libraries) resolve to the host's shared objects and silently add runtime dependencies. The
95
+ built extension again has no `libsfml`/`libcsfml`/`libfreetype`/`libvorbis`/`libFLAC`/`libogg`
96
+ shared dependency.
97
+
98
+ ### Build
99
+ * `ext/ports.rb` now builds **Ogg 1.3.5, Vorbis 1.3.7 and FLAC 1.4.3** as pinned,
100
+ checksum-verified, static and position-independent ports, alongside FreeType. SFML 3's audio
101
+ backend is miniaudio, so OpenAL is not needed.
102
+ * `SFML_BUILD_AUDIO`, `SFML_BUILD_NETWORK`, `CSFML_BUILD_AUDIO` and `CSFML_BUILD_NETWORK` are
103
+ enabled; `ws2_32` was added to the Windows system libraries and the CoreAudio/CoreFoundation
104
+ frameworks to the macOS ones. `CMakeLists.txt` finds and links the `Audio`/`Network` components.
105
+ * Archive extraction accepts `.tar.xz` as well as `.tar.gz`, since the FLAC release ships only as
106
+ xz.
107
+
108
+ ### Known issues
109
+ * Audio playback and capture need an audio device; the CI suite stays headless, so
110
+ `SoundStream#on_get_data` and `SoundRecorder` are exercised by construction and mapping only,
111
+ never by actually playing or capturing.
112
+ * `Http` and `Ftp` perform real network I/O and are not exercised in CI beyond construction and
113
+ enum mapping.
114
+
115
+ ## [0.1.1]
116
+
117
+ ### Added
118
+ * **Full Graphics binding.** `RectangleShape`, `ConvexShape`, a callback-based custom `Shape`, `Sprite`,
119
+ `Texture`, `Image`, `Font`, `Text`, `RenderTexture`, `Shader`, `Vertex`, `VertexArray`,
120
+ `VertexBuffer`, `Glyph`, and the value types `BlendMode`, `StencilMode`. `Circle` gained the
121
+ outline/texture/bounds surface it was missing.
122
+ * **Full Window/input binding.** `Keyboard` real-time queries (`pressed?`, `scancode_pressed?`,
123
+ `localize`, `delocalize`, `description`), and the `Mouse`, `Joystick`, `Touch`, `Sensor`,
124
+ `Clipboard`, `Cursor`, `Context`, `ContextSettings` and `Vulkan` modules/classes. `Event` now
125
+ exposes every payload (text, mouse move/raw/button/wheel, joystick move/button/connect, touch,
126
+ sensor).
127
+ * **System completeness.** `SFML::Time` (arithmetic, comparison, unit conversions), `SFML.sleep`,
128
+ `SFML::Buffer`, and `SFML::InputStream` (wraps any `#read`-able object so `Font`/`Texture`/`Image`/
129
+ `Shader` can load from streams).
130
+ * **Value classes.** `Vector2`, `Vector3`, `Color`, `Rect` are now real Ruby classes; every setter
131
+ still accepts a plain array, and getters return the class (which behaves like an array via
132
+ `to_ary`/`Enumerable`).
133
+ * `RenderTexture` is a draw target alongside `Window`: both route through the shared `Target`
134
+ dispatcher, so every drawable renders to either.
135
+ * Predefined `Color` constants, `BlendMode`/`StencilMode` predefined values, `ContextSettings`,
136
+ and `VideoMode.desktop_mode` / `.fullscreen_modes`.
137
+ * Initial project scaffolding: C extension wrapping CSFML (SFML 2 bindings).
138
+ * Windows, video modes, events, keyboard input, transforms, drawables (circle, rectangle, sprite, image), textures, views, clocks, and render targets.
139
+ * Unit tests (minitest) for Clock, Transformable, Circle, RenderState, VideoMode — headless, deterministic.
140
+ * RuboCop configuration and CI integration (test, check, publish workflows).
141
+ * Publish GitHub Action to build and upload the gem on release.
142
+ * `ext/ports.rb`: downloads, checksum-verifies, and builds SFML 3.0.2 and CSFML 3.0.0 from source into a static, position-independent prefix. Ships inside the gem, so `gem install sfml3-rb` builds its own dependencies with no CSFML pre-installed. Shared by `rake ports` (development) and `ext/extconf.rb` (install time).
143
+ * `ext/extconf.rb` three-way dependency resolution: `--enable-system-libraries` (or `SFML_USE_SYSTEM_LIBRARIES`) links a system CSFML 3; otherwise an existing `ports/<host>` prefix is reused, or built automatically.
144
+ * A compile-time `CSFML_VERSION_MAJOR < 3` guard (`ext/ext/sfml.h`) and an `extconf.rb` header check, so a CSFML 2.x install fails with one actionable message instead of a wall of compiler errors.
145
+ * `CMakeLists.txt` rewritten into a real, buildable configuration (CLion/IDE use only — `rake compile` remains the build of record): resolves the vendored `ports/<host>` prefix, links `find_package(SFML 3 ...)` and the CSFML static archives, and links through the C++ driver, since SFML is C++.
146
+
147
+ ### Changed
148
+ * **Rebuilt the drawing path around `Target`.** `Target` now carries a `{type, handle}` union and
149
+ dispatches each draw call to the window or render-texture variant; `Window#draw` and every
150
+ drawable's `#draw` go through it. `RenderState` is initialized from `sfRenderStates_default`
151
+ instead of field-by-field, fixing the `stencilMode`/`coordinateType` fields that were left
152
+ uninitialized under CSFML 3, and it now exposes `blend_mode`, `stencil_mode`, `coordinate_type`,
153
+ `texture` and `shader`.
154
+ * **Naming aligned with SFML 3, typos fixed.** `angle`/`angle=` → `rotation`/`rotation=`;
155
+ `escalate` → `scale!` (the mutating operation; `scale` remains the getter); `matrix` → `transform`
156
+ (`matrix` kept as an alias). `View#position`/`position=` were removed: the old setter wrote the
157
+ viewport rather than the center — use `center`/`viewport`.
158
+ * `Clock#elapsed_time`/`#restart!` now return `SFML::Time` rather than bare `Float` seconds.
159
+ * `Window.new` accepts `(video_mode, title, style = :default, state = :windowed, settings = nil)`
160
+ instead of hardcoding `sfDefaultStyle`/`sfWindowed`/no settings.
161
+ * **The C extension is now organised by SFML subsystem.** The 24 sources no longer sit flat in `ext/`
162
+ with their headers in a doubled `ext/ext/` tree; each binding's `.c` and `.h` live together under
163
+ `ext/core/`, `ext/system/`, `ext/window/` or `ext/graphics/`, matching how SFML and CSFML split
164
+ themselves, so a binding's home follows from the CSFML header it wraps. Includes became
165
+ subsystem-relative (`#include "graphics/circle.h"`) and header guards path-derived
166
+ (`SFML_RB_GRAPHICS_CIRCLE_H`), retiring three `CANDY2D_EXT_*` guards left over from a previous
167
+ project name. `ext/extconf.rb` sets `$srcs` from a recursive glob and extends `$VPATH`, because mkmf
168
+ globs only the top level; objects stay flat, which is why every `.c` basename must remain unique.
169
+ `Rakefile` gained `source_pattern = '**/*.{c,h}'` — recursive so the new tree is seen at all, and
170
+ including headers because editing one previously triggered no rebuild. `CMakeLists.txt` globs
171
+ recursively to match.
172
+ * `ext/ext/klass/transform.h` deleted: a stale duplicate of the live `module/transform.h` that nothing
173
+ included, and which would have collided with it in the new tree. The five unbound placeholders
174
+ (Image, Polygon, Rectangle, Sprite, Texture) were kept, so the layout still shows where they will
175
+ land.
176
+ * `CrossBuild#build` now clears **every** staging directory under `pkg/`, not just the current
177
+ platform's. `rake native:<platform> gem` also runs the shared source-gem task, so a stale
178
+ `pkg/<name>-<version>/` fails the cross build with `... are not files` about files that plainly
179
+ exist — which is exactly what the restructuring triggered.
180
+ * **The C extension moved from the untyped `Data_Wrap_Struct` family to `TypedData`.** All wrapped
181
+ types now carry an `rb_data_type_t`. `Data_*` has been deprecated since Ruby 2.3 and warns on every
182
+ use under Ruby 4.0, which was the extension's only compile-time portability problem — the build is
183
+ now warning-clean under `-Wall -Wextra` from Ruby 3.1 to 4.0. `TypedData_Get_Struct` also
184
+ type-checks, where `Data_Get_Struct` silently reinterpreted whatever pointer it was handed.
185
+ * `ext/extconf.rb` now always compiles with `-Wall -Wextra`, and with `-Werror=deprecated-declarations`
186
+ when `SFML_STRICT=1`. CI sets it, so a regression to the deprecated API fails the build rather than
187
+ adding noise. It is opt-in because an unfamiliar compiler at `gem install` time must never fail on a
188
+ warning.
189
+ * **Minimum Ruby raised from 2.5.0 to 3.1**, matched by `TargetRubyVersion` in `.rubocop.yml` and by
190
+ the binary gems, which is the point: there is now **one** floor rather than a source/binary split.
191
+ `>= 2.5.0` had never been exercised — every workflow ran only Ruby 3.3. 3.1 is the oldest
192
+ cross-ruby the `x64-mingw-ucrt` rake-compiler-dock image carries, so it is what lets a single
193
+ `RUBY_CC_VERSION` serve every platform.
194
+ * `test.yaml` now runs the suite across 3.1, 3.2, 3.3, 3.4 and 4.0 — exactly the ABI set the binary
195
+ gems ship — so every Ruby that can receive a precompiled gem is also proven to build from source,
196
+ with `SFML_STRICT=1`.
197
+ * `publish.yaml` gained a `verify-source` gate that installs the freshly built source gem on the floor
198
+ and requires `sfml`, so a release cannot ship a source gem that fails to build. Every supported
199
+ Ruby now has a binary gem, but most *platforms* (macOS, ARM, the BSDs) still do not, and that path
200
+ stays load-bearing.
201
+ * `Gemfile` gained a `:test` group pinning `minitest` to `~> 5.0`; minitest 6 requires Ruby >= 3.2,
202
+ still above the floor. The cross-compile containers now install with `BUNDLE_WITHOUT="development
203
+ test"`.
204
+ * `.rubocop.yml` excludes `pkg/`, `tmp/` and `ports/`. Those hold staged copies of `lib/` and `ext/`,
205
+ so every offence in a real source file was being counted twice or more.
206
+ * **Packaging now produces precompiled binary gems** alongside the source gem. `rake gem:native`
207
+ cross-compiles inside [rake-compiler-dock](https://github.com/rake-compiler/rake-compiler-dock);
208
+ `rake platforms` lists the targets. On a covered platform `gem install sfml3-rb` no longer needs a
209
+ toolchain, CMake, or a source build at all. The source gem remains the fallback everywhere else,
210
+ unchanged in behaviour.
211
+ * **Binary gems now cover i686 as well as x86_64, on both glibc and musl Linux and on 32- and 64-bit
212
+ Windows**: `x86-linux-gnu`, `x86-linux-musl` and `x86-mingw32` join `x86_64-linux-gnu`,
213
+ `x86_64-linux-musl` and `x64-mingw-ucrt`, with `aarch64-linux-gnu`, `x86_64-darwin` and
214
+ `arm64-darwin` still experimental. Two gaps are upstream, not ours: RubyInstaller publishes no
215
+ 32-bit Ruby 4.0, so `x86-mingw32` stops at 3.4; and 64-bit Windows before Ruby 3.1 is a different
216
+ platform (`x64-mingw32`), which is not built.
217
+ * `rakelib/package.rake` asserts the ABIs of each gem it builds against `EXPECTED_ABIS`.
218
+ rake-compiler only *warns* when an image lacks a cross-ruby it was asked for, so without this a gem
219
+ could quietly ship fewer ABIs than intended.
220
+ * `ext/ports.rb` targets gained a `multiarch` key. i686 compiles with `i686-linux-gnu-gcc` but its
221
+ libraries live in `/usr/lib/i386-linux-gnu`, and feeding the compiler triple to
222
+ `CMAKE_LIBRARY_ARCHITECTURE` would have pointed CMake at a directory that does not exist.
223
+ * The extension build moved from a hand-rolled `rake compile` (`ruby extconf.rb && make` inside
224
+ `ext/`, then a manual copy) to `rake-compiler`'s `Rake::ExtensionTask`. Builds are now out of tree
225
+ in `tmp/`, so `ext/` no longer accumulates `.o` files, a `Makefile` and `mkmf.log` beside its
226
+ sources.
227
+ * `lib/sfml.rb` prefers `sfml/<major.minor>/sfml_ext` — the per-ABI layout binary gems use — and falls
228
+ back to `sfml/sfml_ext` for a source build.
229
+ * `ext/ports.rb` is now cross-aware: prefixes and build trees are keyed by target (`ports/<target>`)
230
+ rather than by host, and a CMake toolchain file is generated per target. `SFML_TARGET` selects one;
231
+ a native build is unaffected.
232
+ * Project renamed to sfml3.rb; **migrated from SFML 2 to SFML 3** (via CSFML 3) — no longer just
233
+ planned. Distro CSFML packages are frequently still 2.x and are no longer supported.
234
+ * Native extension renamed from the bare `ext` to `sfml/sfml_ext`, matching the `sfml` gem namespace
235
+ and what `rake-compiler` cross-compilation expects.
236
+ * `event_name.c` and `keyboard.c` name tables are now indexed by named enum constant (C99 designated
237
+ initializers) instead of raw ordinal position, so a future upstream reorder is a compile error
238
+ rather than a silently wrong event or key name.
239
+ * `Window#clear` now takes a single `[r, g, b, a]` color array, matching every other color-setting
240
+ method in the API, instead of three positional numbers.
241
+ * Removed the dead `install-package` extconf hook and its accompanying `ext/linux.sh` (empty) and
242
+ `ext/msys2.sh` stubs, and the unused `run_script`/`Arguments`/`library_nofound` helpers in
243
+ `ext/auxlib.rb`.
244
+ * Removed the vendored `include/ruby/*.h` stubs and the empty `include/SFML/CSFML headers` placeholder;
245
+ nothing referenced them once `CMakeLists.txt` was fixed to query the real Ruby headers.
246
+ * `sfml3-rb.gemspec` carries more information: a `documentation_uri` alongside the existing
247
+ source/bug-tracker/changelog links, a summary that actually names SFML 3 and the precompiled
248
+ binaries (it is the line `gem search` shows), and `extra_rdoc_files`/`rdoc_options`. It also ships
249
+ `CHANGELOG.md` and `TODO.md` — the latter being the module-by-module record of what is bound, which
250
+ is what tells someone whether the gem covers their case. Comments now record what a reader cannot
251
+ infer: that rake-compiler rewrites `platform`, `required_ruby_version` and `extensions` for binary
252
+ gems, and that `required_rubygems_version` is deliberately unset because pinning `>= 3.3.22` here
253
+ would lock Ruby 3.1.0 (RubyGems 3.3.3) out of the source gem. Reformatted to 2-space indentation.
254
+ No `homepage_uri`: it would duplicate `source_code_uri`, and RubyGems warns that only the first of a
255
+ duplicated link is shown.
256
+ * `sfml.gemspec` → `sfml3-rb.gemspec`: description now describes the self-building install rather
257
+ than a still-planned migration; license changed to `0BSD`, matching `LICENSE.md`.
258
+ * **Gem package renamed from `sfml` to `sfml3-rb`** (`gem install sfml3-rb`). `require 'sfml'` and the
259
+ `SFML` Ruby module are unchanged — only the RubyGems package name moved.
260
+
261
+ ### Fixed
262
+ * `Circle#scale` returned the position, not the scale.
263
+ * `RenderState` was missing a `dmark` slot; the wrapped struct now holds its texture/shader Ruby
264
+ references so a GC cannot collect them while the states are in use.
265
+ * `View#position`/`position=` wrote the viewport under a misleading name (removed).
266
+ * `raise_method_no_implemented` crashed on `NULL` and never reached its message branch.
267
+ * `Window#joystick_threshold=` treated the threshold as a boolean.
268
+ * `Circle#draw` raised unconditionally: its second argument check tested `rb_target` against
269
+ `RenderState` instead of `rb_state` (`ext/circle.c`), and a valid `Target` is never a `RenderState`,
270
+ so no call could get past it.
271
+ * `Target#draw` unwrapped its `state` argument with no class check — the one remaining place a
272
+ caller-supplied object reached a struct accessor unguarded. Combined with the untyped
273
+ `Data_Get_Struct` it used to call, passing the wrong object there reinterpreted an arbitrary
274
+ pointer; it now raises before that can happen.
275
+ * `ext/ext/module.h` and `ext/ext/klass/transform.h` each declared a `static VALUE` at file scope in a
276
+ **header**, giving every one of the ~10 including translation units its own zero-initialized copy.
277
+ `rb_mExt` moved into `ext.c`, its only user; `rb_cTransform` was dead and is gone.
278
+ * An unused `hash` local in `Event_key` (`ext/event.c`).
279
+ * Gem metadata: summary typo, empty description, incorrect homepage.
280
+ * Double-free crash (`free(): double free detected in tcache`) in `Circle`, `Clock`, `Transformable`,
281
+ and `Window`: their `_free` functions called both CSFML's own `sfX_destroy` *and* `free()` on the
282
+ same pointer, though `sfX_destroy` already releases it.
283
+ * `Event#size` read `event->size.height` for both components, so a resize event always reported a
284
+ square. Also fixes the CSFML 3 struct layout (`sfSizeEvent.size` is now a vector, not flat
285
+ `width`/`height`).
286
+ * `View#get_rotation` and `RenderTarget#draw` were missing `return` statements, so both handed an
287
+ uninitialized `VALUE` back to Ruby — the same crash class as the double-free above, just not yet
288
+ triggered by the test suite.
289
+ * `Transform.inverse` was bound to `Transform_combine` instead of `Transform_inverse` — a copy-paste
290
+ bug that made `.inverse` silently wrong (and unusable at 1 argument).
291
+ * `Window#view=`, `#view`, and `#default_view` were fully implemented but never registered — calling
292
+ them raised `NoMethodError`.
293
+ * CSFML 3 API port: video mode fields, `sfRenderWindow_create`'s new window-state parameter,
294
+ `sfRenderWindow_waitEvent`'s new timeout parameter, and `sfFloatRect`'s `position`/`size` fields
295
+ (was flat `left/top/width/height`).
296
+ * A `%ul` printf format-string bug in `ext/exceptions.c` produced garbled error messages (e.g.
297
+ "given 3l"); corrected to `%lu`.
298
+ * `test/sfml_test.rb`: `require 'minitest/unit'` (removed from modern minitest) →
299
+ `require 'minitest/autorun'`; classes referenced without their `SFML::` namespace;
300
+ `assert_in_epsilon` used directly on arrays, which fails because it calls `.abs` on the expected
301
+ value.
302
+
303
+ ### Known issues
304
+ * Classes that wrap `T_DATA` never call `rb_define_alloc_func`, so Ruby prints `undefining the
305
+ allocator of T_DATA class ...` once per class on first construction. Harmless and long-standing;
306
+ fixing it means moving construction out of the singleton `new` into an alloc func plus
307
+ `initialize`.
308
+ * Of the nine binary-gem targets, only `x86_64-linux-gnu` has been verified end to end (built,
309
+ installed, full suite passes). `x64-mingw-ucrt` cross-builds and links cleanly with correct PE
310
+ imports but has not been run on Windows. The rest have not been run on their target hardware;
311
+ `aarch64-linux-gnu`, `x86_64-darwin` and `arm64-darwin` are marked `experimental` in
312
+ `publish.yaml`, so a failure can't hold back a release.
313
+ * The Windows gem imports `libwinpthread-1.dll`, which RubyInstaller ships in its
314
+ `ruby_builtin_dlls` directory. If that ever proves unreliable, add `-lwinpthread` to the
315
+ `-Wl,-Bstatic` group in `Ports.cxx_runtime`.
316
+ * `bundle exec rubocop` does not pass on the repository as a whole (55 offenses across 14 files, 40
317
+ autocorrectable, mostly `Style/FrozenStringLiteralComment`) — this predates the packaging work and
318
+ `check.yaml` has been failing on it. The gemspec's own remaining offence is
319
+ `Gemspec/RequireMFA`, left deliberately: setting `rubygems_mfa_required` requires MFA on every
320
+ owner's RubyGems account, and `publish.yaml` pushes with an API token.
321
+ * [TODO.md](TODO.md) tracks SFML 3 → Ruby API porting coverage, module by module.
data/LICENSE.md ADDED
@@ -0,0 +1,14 @@
1
+ BSD Zero Clause License
2
+
3
+ Copyright (c) 2026 Algaves
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted.
7
+
8
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14
+ PERFORMANCE OF THIS SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,140 @@
1
+ # sfml3.rb
2
+
3
+ Ruby bindings for [SFML 3](https://www.sfml-dev.org/), via its C API, [CSFML](https://github.com/SFML/CSFML).
4
+
5
+ ## Status
6
+
7
+ Latest release: **0.2.1**. Bound against **CSFML 3**. See [TODO.md](TODO.md) for which parts of the
8
+ SFML 3 API are ported so far, and [CHANGELOG.md](CHANGELOG.md) for what changed recently.
9
+
10
+ ## Install
11
+
12
+ ```sh
13
+ gem install sfml3-rb
14
+ ```
15
+
16
+ On a platform with a precompiled gem this installs a binary with FreeType, SFML 3 and CSFML 3
17
+ already linked in — no toolchain, no build, nothing to install system-wide:
18
+
19
+ | Platform | Ruby | Status |
20
+ | --- | --- | --- |
21
+ | `x86_64-linux-gnu` | 3.1 – 4.0 | built, installed and tested |
22
+ | `x86-linux-gnu` | 3.1 – 4.0 | 32-bit glibc Linux |
23
+ | `x86_64-linux-musl` | 3.1 – 4.0 | Alpine and other musl systems |
24
+ | `x86-linux-musl` | 3.1 – 4.0 | 32-bit musl |
25
+ | `x64-mingw-ucrt` | 3.1 – 4.0 | 64-bit Windows, RubyInstaller 3.1+ |
26
+ | `x86-mingw32` | 3.1 – **3.4** | 32-bit Windows |
27
+ | `aarch64-linux-gnu`, `x86_64-darwin`, `arm64-darwin` | 3.1 – 4.0 | experimental, not yet built |
28
+
29
+ Each gem carries one extension per Ruby ABI. Two gaps come from upstream rather than from this
30
+ project: **RubyInstaller publishes no 32-bit Ruby 4.0**, so `x86-mingw32` stops at 3.4; and 64-bit
31
+ Windows before Ruby 3.1 used a different platform (`x64-mingw32`), which is not built.
32
+
33
+ Anywhere else — macOS, ARM, the BSDs — RubyGems falls back to the source gem, which downloads and
34
+ builds FreeType, SFML 3 and CSFML 3 from pinned, checksum-verified tarballs at install time. That
35
+ takes a few minutes and needs:
36
+
37
+ * Ruby >= 3.1
38
+ * A C/C++ toolchain and CMake >= 3.22
39
+ * On Linux, the X11/udev/OpenGL development headers SFML links against — these can't be bundled.
40
+ On Fedora:
41
+
42
+ ```sh
43
+ sudo dnf install cmake gcc-c++ libX11-devel \
44
+ libXrandr-devel libXcursor-devel libXi-devel systemd-devel libglvnd-devel
45
+ ```
46
+
47
+ or on Debian/Ubuntu:
48
+
49
+ ```sh
50
+ sudo apt-get install cmake build-essential libx11-dev \
51
+ libxrandr-dev libxcursor-dev libxi-dev libudev-dev libgl1-mesa-dev
52
+ ```
53
+
54
+ Each installed gem version builds its own copy; there's no build cache shared across versions.
55
+
56
+ To link against a system CSFML 3 instead (no download, no build):
57
+
58
+ ```sh
59
+ gem install sfml3-rb -- --enable-system-libraries
60
+ ```
61
+
62
+ ## Usage
63
+
64
+ ```ruby
65
+ require 'sfml'
66
+ include SFML
67
+
68
+ window = Window.new VideoMode.new(640, 480, 32), 'SFML'
69
+ event = Event.new
70
+
71
+ while window.is_open?
72
+ while window.poll_event! event
73
+ window.close! if event.type == 'closed'
74
+ end
75
+
76
+ window.clear [51, 76, 102, 255] # [r, g, b, a], 0-255
77
+ window.display
78
+ end
79
+ ```
80
+
81
+ See [`test/hello-world.rb`](test/hello-world.rb) for a fuller example with shapes and transforms.
82
+
83
+ ## Development
84
+
85
+ ```sh
86
+ rake ports # build the vendored FreeType + SFML 3 + CSFML 3 (rake compile does this too)
87
+ rake compile # build the C extension into lib/sfml/
88
+ rake test # compile, then run the test suite
89
+ rake gem # build the source gem into pkg/
90
+ ```
91
+
92
+ `rake githooks:install` points your checkout at the committed `.githooks/` pre-commit hook, which
93
+ lints staged Ruby with RuboCop and auto-formats staged C with clang-format (`sudo dnf install
94
+ clang-tools-extra` on Fedora for the C side).
95
+
96
+ `CMakeLists.txt` is a CLion/IDE convenience build against the same vendored `ports/` prefix — `rake`
97
+ is the build of record.
98
+
99
+ The C extension under `ext/` mirrors SFML's own subsystems, with each binding's `.c` and `.h`
100
+ side by side: `core/` (CSFML umbrella header, macros, exceptions, UTF-32 conversion),
101
+ `system/` (Clock, Time, vectors, streams), `window/` (Window, Event, VideoMode, and the input
102
+ devices), `graphics/` (shapes, Color, Transform, View, Texture, Text, Shader, the render targets),
103
+ `audio/` and `network/`. Includes are subsystem-relative, e.g. `#include "graphics/circle.h"`.
104
+
105
+ Two `.inc` files hold method bodies shared by several classes and are included once per class with
106
+ a different macro prefix: `audio/sound_source.inc` (Sound, Music, SoundStream) and
107
+ `graphics/render_target.inc` (Window, RenderTexture).
108
+
109
+ Note that mkmf flattens object files to their basenames, so every `.c` filename has to stay
110
+ unique across the whole tree — and that `$srcs` is baked into the generated Makefile, so after
111
+ adding a `.c` file run `touch ext/extconf.rb && rake compile` (or `rake clean compile`), otherwise
112
+ it is silently left out of the link.
113
+
114
+ ### Building the binary gems
115
+
116
+ Cross-compilation runs in [rake-compiler-dock](https://github.com/rake-compiler/rake-compiler-dock),
117
+ which supplies the cross toolchains and the cross-compiled rubies. It needs Docker or Podman, and
118
+ pulls a large image per platform on first use.
119
+
120
+ ```sh
121
+ rake platforms # list the targets
122
+ rake gem:x86_64-linux-gnu # build one platform into pkg/
123
+ rake gem:native # build all of them
124
+ ```
125
+
126
+ Each run provisions the container with [`script/provision.sh`](script/provision.sh) — a current
127
+ CMake everywhere, plus the target-side X11/udev/GL development files on Linux targets, which the
128
+ images don't ship. Windows and macOS need nothing extra: SFML uses OS libraries and frameworks the
129
+ mingw toolchain and the osxcross SDK already provide.
130
+
131
+ Binary gems carry one extension per Ruby ABI under `lib/sfml/<major.minor>/`; `lib/sfml.rb` prefers
132
+ that and falls back to the single `lib/sfml/sfml_ext.so` a source build installs.
133
+
134
+ ## License
135
+
136
+ [0BSD](LICENSE.md)
137
+
138
+ ---
139
+
140
+ Developed by: [Algaves](https://github.com/algaves/sfml3.rb) @ 2026
data/TODO.md ADDED
@@ -0,0 +1,199 @@
1
+ # Roadmap: SFML 3 API port to Ruby
2
+
3
+ Tracks porting coverage of the SFML 3 API into this gem, module by module and class by class.
4
+
5
+ This binding wraps **CSFML 3** (the C API), not SFML's C++ API directly, so the scope below is
6
+ CSFML 3.0.0's actual header set — not every C++-only construct in the
7
+ [reference docs](https://www.sfml-dev.org/documentation/3.1.0/annotated.html). Out of scope for that
8
+ reason: `String`/`Utf`/`Literals` (SFML C++ uses `std::string`; CSFML takes plain C strings),
9
+ `Exception` (CSFML reports errors via return codes, not C++ exceptions), and C++-utility-only types
10
+ (`SuspendAwareClock`, `TimeoutWithPredicate`, `U8StringCharTraits`). `Glsl` is handled as plain
11
+ `set_*_uniform` calls (its types are CSFML structs, not a templated class), and `InputStream`'s C
12
+ struct form *is* bound (`SFML::InputStream`). `Sftp` is also out of scope: it was added to SFML in
13
+ 3.1, and the CSFML 3.0.0 this gem vendors predates it.
14
+
15
+ Status legend: `[x]` bound and tested · `[~]` compiled but not exposed to Ruby, or exposed as an
16
+ internal helper only · `[ ]` not started.
17
+
18
+ **Coverage is tracked per function, not per class.** Every `sf*` entry point in
19
+ `ports/<target>/include/CSFML` is accounted for: bound, or listed in "Deliberately unbound" at the
20
+ bottom. Re-derive the list with:
21
+
22
+ ```sh
23
+ grep -rhoE '\bsf[A-Za-z0-9_]+\s*\(' ports/<target>/include/CSFML --include='*.h' \
24
+ | tr -d ' (' | sort -u > /tmp/api.txt
25
+ grep -rhoE '\bsf[A-Za-z0-9_]+' ext --include='*.c' --include='*.h' --include='*.inc' \
26
+ | sort -u > /tmp/used.txt
27
+ comm -23 /tmp/api.txt /tmp/used.txt
28
+ ```
29
+
30
+ Mind the false positives: functions reached through token paste (`sfSound_*`, `sfMusic_*`,
31
+ `sfSoundStream_*` from `ext/audio/sound_source.inc`; `sfPacket_read*`/`write*` from the macro in
32
+ `ext/network/packet.c`; the shared `sfRenderWindow_*`/`sfRenderTexture_*` render-target methods
33
+ from `ext/graphics/render_target.inc`) never appear literally in the sources and so show up as
34
+ "missing" every time.
35
+
36
+ ## System
37
+
38
+ Base module: time, vectors, clocks, streams.
39
+
40
+ - [x] **Clock** — `SFML::Clock` (`ext/system/clock.c`); `elapsed_time`, `restart!`, `reset!`,
41
+ `start!`, `stop!`, `running?`, `copy`
42
+ - [x] **Vector2** — `SFML::Vector2` (`ext/system/vec2.c`); setters still accept `[x, y]`
43
+ - [x] **Vector3** — `SFML::Vector3` (`ext/system/vec3.c`)
44
+ - [x] **Time** — `SFML::Time` (`ext/system/time.c`); arithmetic, comparison, unit conversions
45
+ - [x] **Sleep** — `SFML.sleep` (`ext/system/sleep.c`)
46
+ - [x] **InputStream** — `SFML::InputStream` (`ext/system/input_stream.c`); wraps any `#read`-able
47
+ object and is accepted by every `from_stream` constructor
48
+ - [x] **Buffer** — `SFML::Buffer` (`ext/system/buffer.c`); returned by `Image#save_to_memory`
49
+
50
+ ## Window
51
+
52
+ OpenGL-based windows, events, input handling.
53
+
54
+ - [x] **Window** — `SFML::Window` (`ext/window/window.c`); wraps `sfRenderWindow`, so this single
55
+ class covers what SFML splits into `WindowBase` + `Window` + `RenderWindow`. Accepts style,
56
+ state and `ContextSettings`; exposes min/max size, icon, cursor, native handle, settings.
57
+ - [x] **VideoMode** — `SFML::VideoMode` (`ext/window/video_mode.c`); includes `desktop_mode` and
58
+ `fullscreen_modes`
59
+ - [x] **Event** — `SFML::Event` (`ext/window/event.c`, `ext/window/event_name.c`); every payload is
60
+ exposed — text, key, mouse move/raw/button/wheel, joystick move/button/connect, touch, sensor
61
+ - [x] **Keyboard** — `SFML::Keyboard` (`ext/window/keyboard.c`); real-time `pressed?`,
62
+ `scancode_pressed?`, `localize`, `delocalize`, `description`, virtual-keyboard toggle
63
+ - [x] **Mouse** — `SFML::Mouse` (`ext/window/mouse.c`)
64
+ - [x] **Joystick** — `SFML::Joystick` (`ext/window/joystick.c`)
65
+ - [x] **Touch** — `SFML::Touch` (`ext/window/touch.c`)
66
+ - [x] **Sensor** — `SFML::Sensor` (`ext/window/sensor.c`)
67
+ - [x] **Clipboard** — `SFML::Clipboard` (`ext/window/clipboard.c`)
68
+ - [x] **Cursor** — `SFML::Cursor` (`ext/window/cursor.c`)
69
+ - [x] **Context** / **ContextSettings** — `SFML::Context`, `SFML::ContextSettings`
70
+ (`ext/window/context.c`, `ext/window/context_settings.c`)
71
+ - [x] **Vulkan** — `SFML::Vulkan` (`ext/window/vulkan.c`)
72
+
73
+ ## Graphics
74
+
75
+ 2D rendering: shapes, sprites, text, render targets.
76
+
77
+ - [x] **Transform** — `SFML::Transform` (`ext/graphics/transform.c`); a class wrapping
78
+ `sfTransform` by value. `identity`/`IDENTITY` (frozen), `from_a`, `to_a`/`matrix` (3x3),
79
+ `gl_matrix` (the 16-float 4x4 for `glLoadMatrixf`), `==`, `translate!`, `rotate!`, `scale!`
80
+ (both taking an optional centre), non-mutating `translate`/`rotate`/`scale`,
81
+ `transform_point`, `transform_rect`, `combine!`, `*`, `inverse`, `copy`. The old module
82
+ functions `Transform.combine`/`Transform.inverse` remain, Array-in/Array-out. Every class
83
+ that exposes `#transform` still returns a plain 9-element Array, and anything that *takes*
84
+ a transform accepts either form
85
+ - [x] **Transformable** — `SFML::Transformable` (`ext/graphics/transformable.c`); including
86
+ `inverse_transform` and `copy`
87
+ - [x] **Drawable** — `SFML::Drawable` mixin (`ext/graphics/drawable.c`)
88
+ - [x] **RenderStates** — `SFML::RenderState` (`ext/graphics/render_state.c`); blend mode, stencil
89
+ mode, coordinate type, texture, shader and transform are all settable
90
+ - [x] **RenderTarget** — `SFML::Target` (`ext/graphics/target.c`) dispatches to `sfRenderWindow_*`
91
+ or `sfRenderTexture_*` at runtime for `Drawable#draw`. The methods each concrete target owns
92
+ directly — `map_pixel_to_coords`, `map_coords_to_pixel`, `push_gl_states`, `pop_gl_states`,
93
+ `reset_gl_states`, `draw_primitives`, `draw_vertex_buffer_range`, `clear_stencil`,
94
+ `clear_color_and_stencil`, `viewport`, `scissor`, `srgb?` — are generated once for both
95
+ `Window` and `RenderTexture` from `ext/graphics/render_target.inc`
96
+ - [x] **RenderWindow** — folded into `SFML::Window` (see Window module above)
97
+ - [x] **RenderTexture** — `SFML::RenderTexture` (`ext/graphics/render_texture.c`)
98
+ - [x] **View** — `SFML::View` (`ext/graphics/view.c`); including `View.from_rect` and
99
+ `scissor`/`scissor=`
100
+ - [x] **CircleShape** — `SFML::Circle` (`ext/graphics/circle.c`)
101
+ - [x] **RectangleShape** — `SFML::RectangleShape` (`ext/graphics/rectangle.c`)
102
+ - [x] **ConvexShape** — `SFML::ConvexShape` (`ext/graphics/polygon.c`)
103
+ - [x] **Shape** — `SFML::Shape` (`ext/graphics/shape.c`); subclass and define `point_count`/`point`
104
+ - [x] **Sprite** — `SFML::Sprite` (`ext/graphics/sprite.c`)
105
+ - [x] **Texture** — `SFML::Texture` (`ext/graphics/texture.c`); every constructor in both linear
106
+ and sRGB form, plus `resize`/`resize_srgb` and `swap`
107
+ - [x] **Image** — `SFML::Image` (`ext/graphics/image.c`)
108
+ - [x] **Font** — `SFML::Font` (`ext/graphics/font.c`)
109
+ - [x] **Text** — `SFML::Text` (`ext/graphics/text.c`); `#string` goes through the UTF-32 entry
110
+ points, so non-ASCII round-trips exactly
111
+ - [x] **Glyph** — `SFML::Glyph` (`ext/graphics/glyph.c`)
112
+ - [x] **Shader** — `SFML::Shader` (`ext/graphics/shader.c`); scalar/vector/color/int/bool/matrix
113
+ uniforms, all six array uniforms (float, vec2-4, mat3, mat4), plus a generic `uniform=`
114
+ - [x] **Color** — `SFML::Color` (`ext/graphics/color.c`)
115
+ - [x] **Rect** — `SFML::Rect` (`ext/graphics/rect.c`); `sfFloatRect` and `sfIntRect`
116
+ - [x] **BlendMode** — `SFML::BlendMode` (`ext/graphics/blend_mode.c`)
117
+ - [x] **StencilMode** — `SFML::StencilMode` (`ext/graphics/stencil_mode.c`)
118
+ - [x] **Vertex** / **VertexArray** / **VertexBuffer** — `ext/graphics/vertex*.c`
119
+
120
+ ## Audio
121
+
122
+ Sounds, streaming, recording, spatialization.
123
+
124
+ - [x] **Listener** — `SFML::Listener` (`ext/audio/listener.c`); global volume plus
125
+ position/direction/velocity/up-vector/cone
126
+ - [x] **ListenerCone** / **SoundSourceCone** — `SFML::SoundSourceCone` (`ext/audio/sound_source_cone.c`)
127
+ - [x] **SoundSource** — the shared play/pause/stop/status, pitch, pan, volume, spatialization,
128
+ position/direction/velocity, cone, doppler/directional-attenuation, min/max distance/gain,
129
+ attenuation, playing-offset and effect-processor surface, generated per class from
130
+ `ext/audio/sound_source.inc`
131
+ - [x] **SoundStatus** / **SoundChannel** — `SFML::SoundStatus`, `SFML::SoundChannel`
132
+ (`ext/audio/audio_enums.c`)
133
+ - [x] **SoundBuffer** — `SFML::SoundBuffer` (`ext/audio/sound_buffer.c`); loading from file, memory,
134
+ stream and raw samples, saving, sample access and channel map
135
+ - [x] **Sound** — `SFML::Sound` (`ext/audio/sound.c`)
136
+ - [x] **SoundStream** — `SFML::SoundStream` (`ext/audio/sound_stream.c`); subclass and implement
137
+ `#on_get_data` (and optionally `#on_seek`)
138
+ - [x] **SoundBufferRecorder** — `SFML::SoundBufferRecorder` (`ext/audio/sound_buffer_recorder.c`)
139
+ - [x] **SoundRecorder** — `SFML::SoundRecorder` (`ext/audio/sound_recorder.c`); subclass and
140
+ implement `#on_process` (and optionally `#on_start`/`#on_stop`)
141
+ - [x] **Music** — `SFML::Music` (`ext/audio/music.c`); file, memory and stream sources, loop points
142
+ - [x] **EffectProcessor** — `SFML::SoundSource#effect_processor=`; a Ruby proc is dispatched through
143
+ a bounded pool of C thunks (`ext/audio/effect_processor.c`), because `sfEffectProcessor` has
144
+ no `userData` to identify the source
145
+ - [x] **Build support** — `ext/ports.rb` builds Ogg 1.3.5, Vorbis 1.3.7 and FLAC 1.4.3 as pinned,
146
+ static, position-independent ports (SFML 3's audio backend is miniaudio, so no OpenAL), and
147
+ enables `SFML_BUILD_AUDIO` / `CSFML_BUILD_AUDIO`
148
+
149
+ ## Network
150
+
151
+ Socket-based communication and higher-level protocols.
152
+
153
+ - [x] **IpAddress** — `SFML::IpAddress` (`ext/network/ip_address.c`); string/bytes/integer
154
+ constructors, `NONE`/`ANY`/`LOCAL_HOST`/`BROADCAST`, local and public address lookup
155
+ - [x] **Packet** — `SFML::Packet` (`ext/network/packet.c`); raw data plus every typed reader/writer
156
+ (booleans, all integer widths, floats, string)
157
+ - [x] **SocketSelector** — `SFML::SocketSelector` (`ext/network/socket_selector.c`); add/remove for
158
+ each socket type, wait and readiness checks
159
+ - [x] **TcpSocket** / **TcpListener** — `SFML::TcpSocket`, `SFML::TcpListener`
160
+ (`ext/network/tcp_socket.c`, `ext/network/tcp_listener.c`); connect/accept, blocking control,
161
+ raw and packet sends/receives
162
+ - [x] **UdpSocket** — `SFML::UdpSocket` (`ext/network/udp_socket.c`); bind/send/receive and packet
163
+ variants, datagram size and any-port helpers
164
+ - [x] **Http** — `SFML::Http`, `SFML::HttpRequest`, `SFML::HttpResponse` (`ext/network/http.c`)
165
+ - [x] **Ftp** — `SFML::Ftp`, `SFML::FtpResponse`, `SFML::FtpDirectoryResponse`,
166
+ `SFML::FtpListingResponse` (`ext/network/ftp.c`)
167
+ - [x] **SocketStatus** / **HttpMethod** / **HttpStatus** / **FtpStatus** / **FtpTransferMode** —
168
+ enum modules (`ext/network/network_enums.c`)
169
+ - [x] **Build support** — `ext/ports.rb` enables `SFML_BUILD_NETWORK` / `CSFML_BUILD_NETWORK`; the
170
+ module needs no external dependency (just `ws2_32` on Windows)
171
+
172
+ Note that CSFML exposes no `sfSocket` base class, so there is nothing to bind for "Socket base" —
173
+ only the concrete TCP/UDP sockets and the selector.
174
+
175
+ ## Deliberately unbound
176
+
177
+ These CSFML entry points have no Ruby surface on purpose. Listed so a coverage diff can be read
178
+ without re-deriving the reasoning each time.
179
+
180
+ | Symbols | Why |
181
+ | --- | --- |
182
+ | `sfWindow_*`, `sfWindowBase_*` (~55 functions) | `SFML::Window` wraps `sfRenderWindow`, which subsumes both a plain window and a base window. |
183
+ | `sfMouse_*WindowBase`, `sfTouch_getPositionWindowBase` | Superseded by the `*RenderWindow` forms, which need no downcast. |
184
+ | `sfRenderWindow_create`, `sfText_getString`/`setString`, `sfRenderWindow_setTitle`, `sfFtpDirectoryResponse_getDirectory` | Superseded by their `*Unicode` counterparts; the narrow forms decode through the C locale and mangle non-ASCII. |
185
+ | `sfColor_add`/`subtract`/`modulate`/`fromRGB`/`fromRGBA`/`fromInteger`/`toInteger`, `sfIntRect_contains`/`intersects` | Reimplemented directly in C in `color.c` / `rect.c`; the Ruby methods exist. |
186
+ | `sfSprite_getTexture`, `sfText_getFont`, `sf*Shape_getTexture` | The Ruby getters return the cached wrapper object. CSFML returns a non-owning pointer, so re-wrapping it would hand Ruby an object it must not free. |
187
+ | `sfShape_getPoint`, `sfShape_getPointCount` | `SFML::Shape` reads these from the Ruby subclass, which is where they are defined. |
188
+ | `sfTexture_updateFromWindow` | `Texture#update_from_window` uses `sfTexture_updateFromRenderWindow`, since `SFML::Window` is a render window. |
189
+ | `sfFree` | CSFML's allocator hook; nothing in a Ruby binding should call it. |
190
+ | `sfGlslVec4_fromsfColor`, `sfGlslIvec4_fromsfColor` | Documentation-only helpers; `Shader#set_color` does the conversion. |
191
+
192
+ ## References
193
+
194
+ - [SFML 3.1.0 module topics](https://www.sfml-dev.org/documentation/3.1.0/topics.html)
195
+ - [SFML 3.1.0 class index](https://www.sfml-dev.org/documentation/3.1.0/annotated.html)
196
+ - [SFML 3.1.0 namespace index](https://www.sfml-dev.org/documentation/3.1.0/namespaces.html)
197
+ - [CSFML 3.0.0 headers](https://github.com/SFML/CSFML/tree/3.0.0/include/CSFML) — the actual C API
198
+ surface this gem binds against, vendored locally under `ports/<target>/include/CSFML/`
199
+ once `rake ports` has run
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SFML
4
+ VERSION = '0.2.1'
5
+ end
data/lib/sfml.rb ADDED
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sfml/version'
4
+
5
+ begin
6
+ # Binary gems ship one extension per Ruby ABI under lib/sfml/<major.minor>/.
7
+ # A gem built from source installs a single lib/sfml/sfml_ext.so instead.
8
+ require "sfml/#{RUBY_VERSION[/\d+\.\d+/]}/sfml_ext"
9
+ rescue LoadError
10
+ require 'sfml/sfml_ext'
11
+ end
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sfml3-rb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ platform: x86-linux-gnu
6
+ authors:
7
+ - Algaves
8
+ - Diego-Sealtiel Valderrama
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 1980-01-02 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Ruby bindings for SFML 3 via CSFML. Precompiled binaries are published
14
+ for common platforms; elsewhere SFML and CSFML are downloaded and built from source
15
+ at install time, so neither needs to be installed system-wide.
16
+ email: SealtielFreak@yandex.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files:
20
+ - CHANGELOG.md
21
+ - LICENSE.md
22
+ - README.md
23
+ - TODO.md
24
+ files:
25
+ - CHANGELOG.md
26
+ - LICENSE.md
27
+ - README.md
28
+ - TODO.md
29
+ - lib/sfml.rb
30
+ - lib/sfml/3.1/sfml_ext.so
31
+ - lib/sfml/3.2/sfml_ext.so
32
+ - lib/sfml/3.3/sfml_ext.so
33
+ - lib/sfml/3.4/sfml_ext.so
34
+ - lib/sfml/4.0/sfml_ext.so
35
+ - lib/sfml/version.rb
36
+ homepage: https://github.com/algaves/sfml3.rb
37
+ licenses:
38
+ - 0BSD
39
+ metadata:
40
+ source_code_uri: https://github.com/algaves/sfml3.rb
41
+ bug_tracker_uri: https://github.com/algaves/sfml3.rb/issues
42
+ changelog_uri: https://github.com/algaves/sfml3.rb/blob/main/CHANGELOG.md
43
+ documentation_uri: https://rubydoc.info/gems/sfml3-rb
44
+ rubygems_mfa_required: 'true'
45
+ rdoc_options:
46
+ - "--main"
47
+ - README.md
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '3.1'
55
+ - - "<"
56
+ - !ruby/object:Gem::Version
57
+ version: 4.1.dev
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 3.3.22
63
+ requirements: []
64
+ rubygems_version: 4.0.6
65
+ specification_version: 4
66
+ summary: Ruby bindings for SFML 3, with precompiled binaries
67
+ test_files: []