sfml3-rb 0.2.2 → 0.3.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.
- checksums.yaml +4 -4
- data/.yardopts +9 -0
- data/CHANGELOG.md +67 -16
- data/README.md +123 -32
- data/TODO.md +18 -11
- data/ext/audio/audio_enums.c +58 -20
- data/ext/audio/listener.c +89 -6
- data/ext/audio/music.c +212 -5
- data/ext/audio/sound.c +218 -9
- data/ext/audio/sound_buffer.c +197 -47
- data/ext/audio/sound_buffer_recorder.c +90 -18
- data/ext/audio/sound_recorder.c +188 -58
- data/ext/audio/sound_source_cone.c +127 -33
- data/ext/audio/sound_stream.c +204 -21
- data/ext/core/exceptions.c +10 -8
- data/ext/core/unicode.c +12 -2
- data/ext/ext.c +8 -0
- data/ext/graphics/blend_mode.c +218 -60
- data/ext/graphics/circle.c +300 -16
- data/ext/graphics/color.c +253 -94
- data/ext/graphics/drawable.c +16 -4
- data/ext/graphics/font.c +144 -25
- data/ext/graphics/glyph.c +38 -8
- data/ext/graphics/image.c +205 -41
- data/ext/graphics/polygon.c +317 -30
- data/ext/graphics/rect.c +225 -60
- data/ext/graphics/rectangle.c +307 -35
- data/ext/graphics/render_state.c +124 -12
- data/ext/graphics/render_texture.c +191 -14
- data/ext/graphics/render_window.c +55 -0
- data/ext/graphics/render_window.h +10 -0
- data/ext/graphics/shader.c +289 -17
- data/ext/graphics/shape.c +265 -32
- data/ext/graphics/sprite.c +245 -30
- data/ext/graphics/stencil_mode.c +163 -46
- data/ext/graphics/target.c +121 -43
- data/ext/graphics/target.h +31 -17
- data/ext/graphics/text.c +339 -19
- data/ext/graphics/texture.c +291 -6
- data/ext/graphics/transform.c +178 -5
- data/ext/graphics/transformable.c +127 -12
- data/ext/graphics/vertex.c +98 -6
- data/ext/graphics/vertex_array.c +142 -21
- data/ext/graphics/vertex_buffer.c +154 -12
- data/ext/graphics/view.c +140 -6
- data/ext/network/ftp.c +278 -12
- data/ext/network/http.c +179 -44
- data/ext/network/ip_address.c +127 -35
- data/ext/network/network_enums.c +248 -141
- data/ext/network/packet.c +280 -41
- data/ext/network/socket_selector.c +98 -21
- data/ext/network/tcp_listener.c +82 -18
- data/ext/network/tcp_socket.c +135 -27
- data/ext/network/udp_socket.c +129 -28
- data/ext/ports.rb +7 -0
- data/ext/system/buffer.c +47 -16
- data/ext/system/clock.c +77 -12
- data/ext/system/input_stream.c +113 -51
- data/ext/system/sleep.c +10 -2
- data/ext/system/time.c +182 -40
- data/ext/system/vec2.c +166 -39
- data/ext/system/vec3.c +177 -39
- data/ext/window/clipboard.c +47 -17
- data/ext/window/context.c +66 -13
- data/ext/window/context_settings.c +132 -42
- data/ext/window/cursor.c +45 -9
- data/ext/window/event.c +164 -53
- data/ext/window/joystick.c +69 -3
- data/ext/window/keyboard.c +168 -116
- data/ext/window/mouse.c +64 -13
- data/ext/window/sensor.c +28 -2
- data/ext/window/touch.c +32 -12
- data/ext/window/video_mode.c +93 -31
- data/ext/window/vulkan.c +34 -6
- data/ext/window/window.c +228 -229
- data/ext/window/window.h +4 -4
- data/ext/window/window_base.c +251 -0
- data/ext/window/window_base.h +43 -0
- data/ext/window/window_base.inc +236 -0
- data/lib/sfml/version.rb +1 -1
- data/sig/audio/audio_enums.rbs +30 -0
- data/sig/audio/listener.rbs +16 -0
- data/sig/audio/music.rbs +56 -0
- data/sig/audio/sound.rbs +51 -0
- data/sig/audio/sound_buffer.rbs +17 -0
- data/sig/audio/sound_buffer_recorder.rbs +14 -0
- data/sig/audio/sound_recorder.rbs +17 -0
- data/sig/audio/sound_source_cone.rbs +14 -0
- data/sig/audio/sound_stream.rbs +51 -0
- data/sig/graphics/blend_mode.rbs +29 -0
- data/sig/graphics/circle.rbs +44 -0
- data/sig/graphics/color.rbs +39 -0
- data/sig/graphics/drawable.rbs +5 -0
- data/sig/graphics/font.rbs +20 -0
- data/sig/graphics/glyph.rbs +7 -0
- data/sig/graphics/image.rbs +22 -0
- data/sig/graphics/polygon.rbs +42 -0
- data/sig/graphics/rect.rbs +33 -0
- data/sig/graphics/rectangle.rbs +42 -0
- data/sig/graphics/render_state.rbs +21 -0
- data/sig/graphics/render_target.rbs +18 -0
- data/sig/graphics/render_texture.rbs +39 -0
- data/sig/graphics/render_window.rbs +7 -0
- data/sig/graphics/shader.rbs +39 -0
- data/sig/graphics/shape.rbs +38 -0
- data/sig/graphics/sprite.rbs +34 -0
- data/sig/graphics/stencil_mode.rbs +18 -0
- data/sig/graphics/target.rbs +8 -0
- data/sig/graphics/text.rbs +48 -0
- data/sig/graphics/texture.rbs +34 -0
- data/sig/graphics/transform.rbs +37 -0
- data/sig/graphics/transformable.rbs +25 -0
- data/sig/graphics/vertex.rbs +17 -0
- data/sig/graphics/vertex_array.rbs +17 -0
- data/sig/graphics/vertex_buffer.rbs +22 -0
- data/sig/graphics/view.rbs +23 -0
- data/sig/network/ftp.rbs +46 -0
- data/sig/network/http.rbs +27 -0
- data/sig/network/ip_address.rbs +22 -0
- data/sig/network/network_enums.rbs +95 -0
- data/sig/network/packet.rbs +40 -0
- data/sig/network/socket_selector.rbs +14 -0
- data/sig/network/tcp_listener.rbs +13 -0
- data/sig/network/tcp_socket.rbs +18 -0
- data/sig/network/udp_socket.rbs +17 -0
- data/sig/sfml/version.rbs +3 -0
- data/sig/system/buffer.rbs +11 -0
- data/sig/system/clock.rbs +13 -0
- data/sig/system/input_stream.rbs +7 -0
- data/sig/system/sleep.rbs +3 -0
- data/sig/system/time.rbs +28 -0
- data/sig/system/vec2.rbs +26 -0
- data/sig/system/vec3.rbs +27 -0
- data/sig/window/clipboard.rbs +8 -0
- data/sig/window/context.rbs +11 -0
- data/sig/window/context_settings.rbs +20 -0
- data/sig/window/cursor.rbs +6 -0
- data/sig/window/event.rbs +20 -0
- data/sig/window/joystick.rbs +15 -0
- data/sig/window/keyboard.rbs +10 -0
- data/sig/window/mouse.rbs +9 -0
- data/sig/window/sensor.rbs +8 -0
- data/sig/window/touch.rbs +6 -0
- data/sig/window/video_mode.rbs +16 -0
- data/sig/window/vulkan.rbs +7 -0
- data/sig/window/window.rbs +34 -0
- data/sig/window/window_base.rbs +33 -0
- metadata +76 -3
data/ext/system/input_stream.c
CHANGED
|
@@ -16,21 +16,20 @@ typedef struct {
|
|
|
16
16
|
|
|
17
17
|
static VALUE rb_cInputStream;
|
|
18
18
|
|
|
19
|
-
static void InputStream_mark(void
|
|
20
|
-
InputStream
|
|
19
|
+
static void InputStream_mark(void* ptr) {
|
|
20
|
+
InputStream* stream = ptr;
|
|
21
21
|
|
|
22
22
|
rb_gc_mark(stream->rb_io);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
static void InputStream_free(void
|
|
25
|
+
static void InputStream_free(void* ptr) {
|
|
26
26
|
free(ptr);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
static const rb_data_type_t InputStream_data_type = {
|
|
30
30
|
.wrap_struct_name = "SFML::InputStream",
|
|
31
31
|
.function = {.dmark = InputStream_mark, .dfree = InputStream_free, .dsize = NULL},
|
|
32
|
-
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
33
|
-
};
|
|
32
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY};
|
|
34
33
|
|
|
35
34
|
/* Callbacks run from C++ (SFML), so a Ruby exception must never unwind through
|
|
36
35
|
those frames. Each body runs under rb_protect and reports failure as a
|
|
@@ -38,12 +37,12 @@ static const rb_data_type_t InputStream_data_type = {
|
|
|
38
37
|
typedef struct {
|
|
39
38
|
VALUE io;
|
|
40
39
|
size_t size;
|
|
41
|
-
void
|
|
40
|
+
void* data;
|
|
42
41
|
int64_t result;
|
|
43
42
|
} ReadContext;
|
|
44
43
|
|
|
45
44
|
static VALUE InputStream_read_body(VALUE v) {
|
|
46
|
-
ReadContext
|
|
45
|
+
ReadContext* ctx = (ReadContext*)v;
|
|
47
46
|
VALUE str = rb_funcall(ctx->io, rb_intern("read"), 1, SIZET2NUM(ctx->size));
|
|
48
47
|
|
|
49
48
|
if (NIL_P(str)) {
|
|
@@ -55,25 +54,31 @@ static VALUE InputStream_read_body(VALUE v) {
|
|
|
55
54
|
|
|
56
55
|
long length = RSTRING_LEN(str);
|
|
57
56
|
|
|
58
|
-
if ((size_t)
|
|
59
|
-
length = (long)
|
|
57
|
+
if ((size_t)length > ctx->size) {
|
|
58
|
+
length = (long)ctx->size;
|
|
60
59
|
}
|
|
61
60
|
|
|
62
61
|
if (length > 0) {
|
|
63
|
-
|
|
62
|
+
const unsigned char* src = (const unsigned char*)RSTRING_PTR(str);
|
|
63
|
+
unsigned char* dest = ctx->data;
|
|
64
|
+
long i;
|
|
65
|
+
|
|
66
|
+
for (i = 0; i < length; i++) {
|
|
67
|
+
dest[i] = src[i];
|
|
68
|
+
}
|
|
64
69
|
}
|
|
65
70
|
|
|
66
|
-
ctx->result = (int64_t)
|
|
71
|
+
ctx->result = (int64_t)length;
|
|
67
72
|
|
|
68
73
|
return Qnil;
|
|
69
74
|
}
|
|
70
75
|
|
|
71
|
-
static int64_t InputStream_read(void
|
|
72
|
-
InputStream
|
|
76
|
+
static int64_t InputStream_read(void* data, size_t size, void* userData) {
|
|
77
|
+
InputStream* stream = userData;
|
|
73
78
|
ReadContext ctx = {.io = stream->rb_io, .size = size, .data = data, .result = -1};
|
|
74
79
|
int state = 0;
|
|
75
80
|
|
|
76
|
-
rb_protect(InputStream_read_body, (VALUE)
|
|
81
|
+
rb_protect(InputStream_read_body, (VALUE)&ctx, &state);
|
|
77
82
|
|
|
78
83
|
if (state) {
|
|
79
84
|
rb_set_errinfo(Qnil);
|
|
@@ -90,20 +95,20 @@ typedef struct {
|
|
|
90
95
|
} SeekContext;
|
|
91
96
|
|
|
92
97
|
static VALUE InputStream_seek_body(VALUE v) {
|
|
93
|
-
SeekContext
|
|
98
|
+
SeekContext* ctx = (SeekContext*)v;
|
|
94
99
|
|
|
95
100
|
rb_funcall(ctx->io, rb_intern("seek"), 2, SIZET2NUM(ctx->position), INT2NUM(SEEK_SET));
|
|
96
|
-
ctx->result = (int64_t)
|
|
101
|
+
ctx->result = (int64_t)ctx->position;
|
|
97
102
|
|
|
98
103
|
return Qnil;
|
|
99
104
|
}
|
|
100
105
|
|
|
101
|
-
static int64_t InputStream_seek(size_t position, void
|
|
102
|
-
InputStream
|
|
106
|
+
static int64_t InputStream_seek(size_t position, void* userData) {
|
|
107
|
+
InputStream* stream = userData;
|
|
103
108
|
SeekContext ctx = {.io = stream->rb_io, .position = position, .result = -1};
|
|
104
109
|
int state = 0;
|
|
105
110
|
|
|
106
|
-
rb_protect(InputStream_seek_body, (VALUE)
|
|
111
|
+
rb_protect(InputStream_seek_body, (VALUE)&ctx, &state);
|
|
107
112
|
|
|
108
113
|
if (state) {
|
|
109
114
|
rb_set_errinfo(Qnil);
|
|
@@ -113,82 +118,139 @@ static int64_t InputStream_seek(size_t position, void *userData) {
|
|
|
113
118
|
return ctx.result;
|
|
114
119
|
}
|
|
115
120
|
|
|
121
|
+
typedef struct {
|
|
122
|
+
VALUE io;
|
|
123
|
+
int64_t result;
|
|
124
|
+
} Int64Context;
|
|
125
|
+
|
|
126
|
+
/* NUM2LL is done here, inside the rb_protect-called body, rather than after
|
|
127
|
+
rb_protect returns: if the IO's #tell/#pos/#size/#length returns something
|
|
128
|
+
that doesn't convert cleanly to a C integer (a String, nil, a Bignum too
|
|
129
|
+
large for int64_t, a #to_int that itself raises), NUM2LL raises directly --
|
|
130
|
+
and unprotected, that exception would unwind straight through CSFML's (and
|
|
131
|
+
possibly SFML's C++) stack frames, exactly what rb_protect exists to
|
|
132
|
+
prevent here. */
|
|
116
133
|
static VALUE InputStream_tell_body(VALUE v) {
|
|
117
|
-
|
|
134
|
+
Int64Context* ctx = (Int64Context*)v;
|
|
135
|
+
VALUE result;
|
|
118
136
|
|
|
119
|
-
if (rb_respond_to(io, rb_intern("tell"))) {
|
|
120
|
-
|
|
137
|
+
if (rb_respond_to(ctx->io, rb_intern("tell"))) {
|
|
138
|
+
result = rb_funcall(ctx->io, rb_intern("tell"), 0);
|
|
139
|
+
} else {
|
|
140
|
+
result = rb_funcall(ctx->io, rb_intern("pos"), 0);
|
|
121
141
|
}
|
|
122
142
|
|
|
123
|
-
|
|
143
|
+
ctx->result = NUM2LL(result);
|
|
144
|
+
|
|
145
|
+
return Qnil;
|
|
124
146
|
}
|
|
125
147
|
|
|
126
|
-
static int64_t InputStream_tell(void
|
|
127
|
-
InputStream
|
|
148
|
+
static int64_t InputStream_tell(void* userData) {
|
|
149
|
+
InputStream* stream = userData;
|
|
150
|
+
Int64Context ctx = {.io = stream->rb_io, .result = -1};
|
|
128
151
|
int state = 0;
|
|
129
|
-
|
|
152
|
+
|
|
153
|
+
rb_protect(InputStream_tell_body, (VALUE)&ctx, &state);
|
|
130
154
|
|
|
131
155
|
if (state) {
|
|
132
156
|
rb_set_errinfo(Qnil);
|
|
133
157
|
return -1;
|
|
134
158
|
}
|
|
135
159
|
|
|
136
|
-
return
|
|
160
|
+
return ctx.result;
|
|
137
161
|
}
|
|
138
162
|
|
|
139
163
|
static VALUE InputStream_get_size_body(VALUE v) {
|
|
140
|
-
|
|
164
|
+
Int64Context* ctx = (Int64Context*)v;
|
|
165
|
+
VALUE result;
|
|
141
166
|
|
|
142
|
-
if (rb_respond_to(io, rb_intern("size"))) {
|
|
143
|
-
|
|
167
|
+
if (rb_respond_to(ctx->io, rb_intern("size"))) {
|
|
168
|
+
result = rb_funcall(ctx->io, rb_intern("size"), 0);
|
|
169
|
+
} else {
|
|
170
|
+
result = rb_funcall(ctx->io, rb_intern("length"), 0);
|
|
144
171
|
}
|
|
145
172
|
|
|
146
|
-
|
|
173
|
+
ctx->result = NUM2LL(result);
|
|
174
|
+
|
|
175
|
+
return Qnil;
|
|
147
176
|
}
|
|
148
177
|
|
|
149
|
-
static int64_t InputStream_get_size(void
|
|
150
|
-
InputStream
|
|
178
|
+
static int64_t InputStream_get_size(void* userData) {
|
|
179
|
+
InputStream* stream = userData;
|
|
180
|
+
Int64Context ctx = {.io = stream->rb_io, .result = -1};
|
|
151
181
|
int state = 0;
|
|
152
|
-
|
|
182
|
+
|
|
183
|
+
rb_protect(InputStream_get_size_body, (VALUE)&ctx, &state);
|
|
153
184
|
|
|
154
185
|
if (state) {
|
|
155
186
|
rb_set_errinfo(Qnil);
|
|
156
187
|
return -1;
|
|
157
188
|
}
|
|
158
189
|
|
|
159
|
-
return
|
|
190
|
+
return ctx.result;
|
|
160
191
|
}
|
|
161
192
|
|
|
162
|
-
static VALUE
|
|
163
|
-
|
|
164
|
-
InputStream *stream;
|
|
193
|
+
static VALUE InputStream_alloc(VALUE klass) {
|
|
194
|
+
InputStream* stream = malloc(sizeof(InputStream));
|
|
165
195
|
|
|
166
|
-
if (
|
|
167
|
-
rb_raise(
|
|
196
|
+
if (stream == NULL) {
|
|
197
|
+
rb_raise(rb_eNoMemError, "failed to allocate input stream");
|
|
168
198
|
}
|
|
169
199
|
|
|
170
|
-
stream =
|
|
171
|
-
|
|
172
|
-
stream->rb_io = rb_io;
|
|
200
|
+
stream->rb_io = Qnil;
|
|
173
201
|
stream->stream.read = InputStream_read;
|
|
174
202
|
stream->stream.seek = InputStream_seek;
|
|
175
203
|
stream->stream.tell = InputStream_tell;
|
|
176
204
|
stream->stream.getSize = InputStream_get_size;
|
|
177
205
|
stream->stream.userData = stream;
|
|
178
206
|
|
|
179
|
-
|
|
207
|
+
return TypedData_Wrap_Struct(klass, &InputStream_data_type, stream);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/* call-seq:
|
|
211
|
+
* InputStream.new(io) -> InputStream
|
|
212
|
+
*
|
|
213
|
+
* Wraps a Ruby object that responds to +#read+ (and ideally +#seek+/+#tell+
|
|
214
|
+
* or +#pos+, and +#size+ or +#length+) so it can be passed anywhere the
|
|
215
|
+
* library accepts a stream-based data source.
|
|
216
|
+
*
|
|
217
|
+
* @return [InputStream]
|
|
218
|
+
* @raise [ArgumentError] if +io+ does not respond to +#read+
|
|
219
|
+
*/
|
|
220
|
+
static VALUE InputStream_initialize(VALUE self, VALUE rb_io) {
|
|
221
|
+
InputStream* stream;
|
|
222
|
+
|
|
223
|
+
if (!rb_respond_to(rb_io, rb_intern("read"))) {
|
|
224
|
+
rb_raise(rb_eArgError, "stream object must respond to #read");
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
TypedData_Get_Struct(self, InputStream, &InputStream_data_type, stream);
|
|
228
|
+
|
|
229
|
+
stream->rb_io = rb_io;
|
|
180
230
|
|
|
181
231
|
return self;
|
|
182
232
|
}
|
|
183
233
|
|
|
234
|
+
/* call-seq: io -> Object
|
|
235
|
+
*
|
|
236
|
+
* Returns the IO-like object the stream was created from.
|
|
237
|
+
*
|
|
238
|
+
* @return [Object] the wrapped IO-like object
|
|
239
|
+
*/
|
|
184
240
|
static VALUE InputStream_get_io(VALUE self) {
|
|
185
|
-
return ((InputStream
|
|
241
|
+
return ((InputStream*)Get_InputStream_Struct(self))->rb_io;
|
|
186
242
|
}
|
|
187
243
|
|
|
188
|
-
|
|
189
|
-
|
|
244
|
+
/* Document-class: SFML::InputStream
|
|
245
|
+
* Adapts any Ruby object that responds to +#read+ into the stream interface
|
|
246
|
+
* SFML's loaders expect, so resources can be loaded from something other
|
|
247
|
+
* than a filesystem path (e.g. an in-memory StringIO, or a custom source).
|
|
248
|
+
*/
|
|
249
|
+
void Init_InputStream(VALUE rb_mSFML) {
|
|
250
|
+
rb_cInputStream = rb_define_class_under(rb_mSFML, "InputStream", rb_cObject);
|
|
190
251
|
|
|
191
|
-
|
|
252
|
+
rb_define_alloc_func(rb_cInputStream, InputStream_alloc);
|
|
253
|
+
rb_define_method(rb_cInputStream, "initialize", InputStream_initialize, 1);
|
|
192
254
|
|
|
193
255
|
rb_define_method(rb_cInputStream, "io", InputStream_get_io, 0);
|
|
194
256
|
}
|
|
@@ -197,8 +259,8 @@ VALUE Get_Klass_InputStream(void) {
|
|
|
197
259
|
return rb_cInputStream;
|
|
198
260
|
}
|
|
199
261
|
|
|
200
|
-
sfInputStream
|
|
201
|
-
InputStream
|
|
262
|
+
sfInputStream* Get_InputStream_Struct(VALUE self) {
|
|
263
|
+
InputStream* ptr;
|
|
202
264
|
TypedData_Get_Struct(self, InputStream, &InputStream_data_type, ptr);
|
|
203
265
|
return &ptr->stream;
|
|
204
266
|
}
|
|
@@ -207,7 +269,7 @@ int InputStream_is_stream(VALUE rb_stream) {
|
|
|
207
269
|
return rb_obj_is_kind_of(rb_stream, rb_cInputStream) ? 1 : 0;
|
|
208
270
|
}
|
|
209
271
|
|
|
210
|
-
sfInputStream
|
|
272
|
+
sfInputStream* input_stream_from_rb(VALUE rb_stream, VALUE* holder) {
|
|
211
273
|
if (InputStream_is_stream(rb_stream)) {
|
|
212
274
|
return Get_InputStream_Struct(rb_stream);
|
|
213
275
|
}
|
data/ext/system/sleep.c
CHANGED
|
@@ -5,12 +5,20 @@
|
|
|
5
5
|
#include "system/time.h"
|
|
6
6
|
#include "core/sfml.h"
|
|
7
7
|
|
|
8
|
+
/* call-seq:
|
|
9
|
+
* SFML.sleep(duration) -> duration
|
|
10
|
+
*
|
|
11
|
+
* Blocks the calling thread for +duration+, which may be a Time, a number
|
|
12
|
+
* of seconds, or anything #to_f-convertible.
|
|
13
|
+
*
|
|
14
|
+
* @return [Time, Numeric] +duration+
|
|
15
|
+
*/
|
|
8
16
|
static VALUE Sleep_sleep(VALUE module, VALUE rb_duration) {
|
|
9
17
|
sfSleep(time_from_rb(rb_duration));
|
|
10
18
|
|
|
11
19
|
return rb_duration;
|
|
12
20
|
}
|
|
13
21
|
|
|
14
|
-
void Init_Sleep(VALUE
|
|
15
|
-
rb_define_module_function(
|
|
22
|
+
void Init_Sleep(VALUE rb_mSFML) {
|
|
23
|
+
rb_define_module_function(rb_mSFML, "sleep", Sleep_sleep, 1);
|
|
16
24
|
}
|
data/ext/system/time.c
CHANGED
|
@@ -12,121 +12,240 @@ typedef struct {
|
|
|
12
12
|
|
|
13
13
|
static VALUE rb_cSFTime;
|
|
14
14
|
|
|
15
|
-
static void Time_free(void
|
|
15
|
+
static void Time_free(void* ptr) {
|
|
16
16
|
free(ptr);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
static const rb_data_type_t Time_data_type = {
|
|
20
20
|
.wrap_struct_name = "SFML::Time",
|
|
21
21
|
.function = {.dmark = NULL, .dfree = Time_free, .dsize = NULL},
|
|
22
|
-
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
23
|
-
};
|
|
22
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY};
|
|
24
23
|
|
|
25
24
|
static VALUE Time_wrap(sfTime time) {
|
|
26
|
-
Time
|
|
25
|
+
Time* ptr = malloc(sizeof(Time));
|
|
26
|
+
|
|
27
|
+
if (ptr == NULL) {
|
|
28
|
+
rb_raise(rb_eNoMemError, "failed to allocate time");
|
|
29
|
+
}
|
|
27
30
|
|
|
28
31
|
ptr->time = time;
|
|
29
32
|
|
|
30
33
|
return TypedData_Wrap_Struct(rb_cSFTime, &Time_data_type, ptr);
|
|
31
34
|
}
|
|
32
35
|
|
|
33
|
-
static VALUE
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
static VALUE Time_alloc(VALUE klass) {
|
|
37
|
+
Time* ptr = malloc(sizeof(Time));
|
|
38
|
+
|
|
39
|
+
if (ptr == NULL) {
|
|
40
|
+
rb_raise(rb_eNoMemError, "failed to allocate time");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
ptr->time = sfTime_Zero;
|
|
44
|
+
|
|
45
|
+
return TypedData_Wrap_Struct(klass, &Time_data_type, ptr);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/* call-seq:
|
|
49
|
+
* Time.new -> Time(0)
|
|
50
|
+
* Time.new(seconds) -> Time
|
|
51
|
+
* Time.new(microseconds_integer) -> Time
|
|
52
|
+
* Time.new(other_time) -> copy of +other_time+
|
|
53
|
+
*
|
|
54
|
+
* A Float argument is interpreted as seconds; an Integer argument is
|
|
55
|
+
* interpreted as microseconds. Prefer .seconds/.milliseconds/.microseconds
|
|
56
|
+
* to be explicit.
|
|
57
|
+
*
|
|
58
|
+
* @return [Time]
|
|
59
|
+
* @raise [ArgumentError] if given more than one argument
|
|
60
|
+
*/
|
|
61
|
+
static VALUE Time_initialize(int argc, VALUE* argv, VALUE self) {
|
|
36
62
|
sfTime time = sfTime_Zero;
|
|
37
63
|
|
|
38
64
|
if (argc == 1 && rb_obj_is_kind_of(argv[0], rb_cSFTime)) {
|
|
39
|
-
time = ((Time
|
|
65
|
+
time = ((Time*)Get_Time_Struct(argv[0]))->time;
|
|
40
66
|
} else if (argc == 1 && RB_INTEGER_TYPE_P(argv[0])) {
|
|
41
|
-
time = sfMicroseconds((int64_t)
|
|
67
|
+
time = sfMicroseconds((int64_t)NUM2LL(argv[0]));
|
|
42
68
|
} else if (argc == 1) {
|
|
43
|
-
time = sfSeconds((float)
|
|
69
|
+
time = sfSeconds((float)NUM2DBL(argv[0]));
|
|
44
70
|
} else if (argc != 0) {
|
|
45
71
|
raise_invalid_arguments_excepted(1, argc);
|
|
46
72
|
}
|
|
47
73
|
|
|
48
|
-
|
|
49
|
-
ptr->time = time;
|
|
50
|
-
|
|
51
|
-
self = TypedData_Wrap_Struct(klass, &Time_data_type, ptr);
|
|
74
|
+
((Time*)Get_Time_Struct(self))->time = time;
|
|
52
75
|
|
|
53
76
|
return self;
|
|
54
77
|
}
|
|
55
78
|
|
|
79
|
+
/* call-seq:
|
|
80
|
+
* Time.seconds(value) -> Time
|
|
81
|
+
*
|
|
82
|
+
* Creates a Time of +value+ seconds, where +value+ is any Float-convertible
|
|
83
|
+
* number.
|
|
84
|
+
*
|
|
85
|
+
* @return [Time]
|
|
86
|
+
*/
|
|
56
87
|
static VALUE Time_seconds(VALUE klass, VALUE rb_seconds) {
|
|
57
|
-
return Time_wrap(sfSeconds((float)
|
|
88
|
+
return Time_wrap(sfSeconds((float)NUM2DBL(rb_seconds)));
|
|
58
89
|
}
|
|
59
90
|
|
|
91
|
+
/* call-seq:
|
|
92
|
+
* Time.milliseconds(value) -> Time
|
|
93
|
+
*
|
|
94
|
+
* Creates a Time of +value+ milliseconds.
|
|
95
|
+
*
|
|
96
|
+
* @return [Time]
|
|
97
|
+
*/
|
|
60
98
|
static VALUE Time_milliseconds(VALUE klass, VALUE rb_milliseconds) {
|
|
61
|
-
return Time_wrap(sfMilliseconds((int32_t)
|
|
99
|
+
return Time_wrap(sfMilliseconds((int32_t)NUM2INT(rb_milliseconds)));
|
|
62
100
|
}
|
|
63
101
|
|
|
102
|
+
/* call-seq:
|
|
103
|
+
* Time.microseconds(value) -> Time
|
|
104
|
+
*
|
|
105
|
+
* Creates a Time of +value+ microseconds.
|
|
106
|
+
*
|
|
107
|
+
* @return [Time]
|
|
108
|
+
*/
|
|
64
109
|
static VALUE Time_microseconds(VALUE klass, VALUE rb_microseconds) {
|
|
65
|
-
return Time_wrap(sfMicroseconds((int64_t)
|
|
110
|
+
return Time_wrap(sfMicroseconds((int64_t)NUM2LL(rb_microseconds)));
|
|
66
111
|
}
|
|
67
112
|
|
|
113
|
+
/* call-seq:
|
|
114
|
+
* Time.zero -> Time
|
|
115
|
+
*
|
|
116
|
+
* Returns the zero-duration Time.
|
|
117
|
+
*
|
|
118
|
+
* @return [Time] a zero-duration Time
|
|
119
|
+
*/
|
|
68
120
|
static VALUE Time_zero(VALUE klass) {
|
|
69
121
|
return Time_wrap(sfTime_Zero);
|
|
70
122
|
}
|
|
71
123
|
|
|
124
|
+
/* call-seq: as_seconds -> Float
|
|
125
|
+
*
|
|
126
|
+
* Returns the duration expressed in seconds.
|
|
127
|
+
*
|
|
128
|
+
* @return [Float]
|
|
129
|
+
*/
|
|
72
130
|
static VALUE Time_as_seconds(VALUE self) {
|
|
73
|
-
return DBL2NUM(sfTime_asSeconds(((Time
|
|
131
|
+
return DBL2NUM(sfTime_asSeconds(((Time*)Get_Time_Struct(self))->time));
|
|
74
132
|
}
|
|
75
133
|
|
|
134
|
+
/* call-seq: as_milliseconds -> Integer
|
|
135
|
+
*
|
|
136
|
+
* Returns the duration expressed in whole milliseconds.
|
|
137
|
+
*
|
|
138
|
+
* @return [Integer]
|
|
139
|
+
*/
|
|
76
140
|
static VALUE Time_as_milliseconds(VALUE self) {
|
|
77
|
-
return INT2NUM(sfTime_asMilliseconds(((Time
|
|
141
|
+
return INT2NUM(sfTime_asMilliseconds(((Time*)Get_Time_Struct(self))->time));
|
|
78
142
|
}
|
|
79
143
|
|
|
144
|
+
/* call-seq: as_microseconds -> Integer
|
|
145
|
+
*
|
|
146
|
+
* Returns the duration expressed in whole microseconds.
|
|
147
|
+
*
|
|
148
|
+
* @return [Integer]
|
|
149
|
+
*/
|
|
80
150
|
static VALUE Time_as_microseconds(VALUE self) {
|
|
81
|
-
return LL2NUM(sfTime_asMicroseconds(((Time
|
|
151
|
+
return LL2NUM(sfTime_asMicroseconds(((Time*)Get_Time_Struct(self))->time));
|
|
82
152
|
}
|
|
83
153
|
|
|
154
|
+
/* call-seq: to_f -> Float
|
|
155
|
+
*
|
|
156
|
+
* Alias for #as_seconds.
|
|
157
|
+
*
|
|
158
|
+
* @return [Float]
|
|
159
|
+
*/
|
|
84
160
|
static VALUE Time_to_f(VALUE self) {
|
|
85
161
|
return Time_as_seconds(self);
|
|
86
162
|
}
|
|
87
163
|
|
|
164
|
+
/* call-seq: to_i -> Integer
|
|
165
|
+
*
|
|
166
|
+
* Alias for #as_microseconds.
|
|
167
|
+
*
|
|
168
|
+
* @return [Integer]
|
|
169
|
+
*/
|
|
88
170
|
static VALUE Time_to_i(VALUE self) {
|
|
89
171
|
return Time_as_microseconds(self);
|
|
90
172
|
}
|
|
91
173
|
|
|
174
|
+
/* call-seq:
|
|
175
|
+
* self + other -> Time
|
|
176
|
+
*
|
|
177
|
+
* Adds +other+ to the duration, returning a new Time.
|
|
178
|
+
*
|
|
179
|
+
* @return [Time]
|
|
180
|
+
*/
|
|
92
181
|
static VALUE Time_add(VALUE self, VALUE rb_other) {
|
|
93
|
-
sfTime a = ((Time
|
|
182
|
+
sfTime a = ((Time*)Get_Time_Struct(self))->time;
|
|
94
183
|
sfTime b = time_from_rb(rb_other);
|
|
95
184
|
|
|
96
185
|
return Time_wrap(sfMicroseconds(sfTime_asMicroseconds(a) + sfTime_asMicroseconds(b)));
|
|
97
186
|
}
|
|
98
187
|
|
|
188
|
+
/* call-seq:
|
|
189
|
+
* self - other -> Time
|
|
190
|
+
*
|
|
191
|
+
* Subtracts +other+ from the duration, returning a new Time.
|
|
192
|
+
*
|
|
193
|
+
* @return [Time]
|
|
194
|
+
*/
|
|
99
195
|
static VALUE Time_sub(VALUE self, VALUE rb_other) {
|
|
100
|
-
sfTime a = ((Time
|
|
196
|
+
sfTime a = ((Time*)Get_Time_Struct(self))->time;
|
|
101
197
|
sfTime b = time_from_rb(rb_other);
|
|
102
198
|
|
|
103
199
|
return Time_wrap(sfMicroseconds(sfTime_asMicroseconds(a) - sfTime_asMicroseconds(b)));
|
|
104
200
|
}
|
|
105
201
|
|
|
202
|
+
/* call-seq:
|
|
203
|
+
* self * scalar -> Time
|
|
204
|
+
*
|
|
205
|
+
* Scales the duration by +scalar+, returning a new Time.
|
|
206
|
+
*
|
|
207
|
+
* @return [Time]
|
|
208
|
+
*/
|
|
106
209
|
static VALUE Time_mul(VALUE self, VALUE rb_scalar) {
|
|
107
|
-
sfTime a = ((Time
|
|
210
|
+
sfTime a = ((Time*)Get_Time_Struct(self))->time;
|
|
108
211
|
|
|
109
|
-
return Time_wrap(sfMicroseconds((int64_t)
|
|
212
|
+
return Time_wrap(sfMicroseconds((int64_t)(sfTime_asMicroseconds(a) * NUM2DBL(rb_scalar))));
|
|
110
213
|
}
|
|
111
214
|
|
|
215
|
+
/* call-seq:
|
|
216
|
+
* self / other -> Time or Float
|
|
217
|
+
*
|
|
218
|
+
* Dividing by a Time returns the (unitless) ratio of the two durations as a
|
|
219
|
+
* Float; dividing by a Number scales the duration.
|
|
220
|
+
*
|
|
221
|
+
* @return [Time, Float]
|
|
222
|
+
* @raise [ZeroDivError] if dividing by a zero Time
|
|
223
|
+
*/
|
|
112
224
|
static VALUE Time_div(VALUE self, VALUE rb_other) {
|
|
113
|
-
sfTime a = ((Time
|
|
225
|
+
sfTime a = ((Time*)Get_Time_Struct(self))->time;
|
|
114
226
|
|
|
115
227
|
if (rb_obj_is_kind_of(rb_other, rb_cSFTime)) {
|
|
116
|
-
int64_t b = sfTime_asMicroseconds(((Time
|
|
228
|
+
int64_t b = sfTime_asMicroseconds(((Time*)Get_Time_Struct(rb_other))->time);
|
|
117
229
|
|
|
118
230
|
if (b == 0) {
|
|
119
231
|
rb_raise(rb_eZeroDivError, "divided by 0");
|
|
120
232
|
}
|
|
121
233
|
|
|
122
|
-
return DBL2NUM((double)
|
|
234
|
+
return DBL2NUM((double)sfTime_asMicroseconds(a) / (double)b);
|
|
123
235
|
}
|
|
124
236
|
|
|
125
|
-
return Time_wrap(sfMicroseconds((int64_t)
|
|
237
|
+
return Time_wrap(sfMicroseconds((int64_t)(sfTime_asMicroseconds(a) / NUM2DBL(rb_other))));
|
|
126
238
|
}
|
|
127
239
|
|
|
240
|
+
/* call-seq:
|
|
241
|
+
* self <=> other -> -1, 0 or 1
|
|
242
|
+
*
|
|
243
|
+
* Compares the duration with +other+, which may be a Time or a number.
|
|
244
|
+
*
|
|
245
|
+
* @return [Integer]
|
|
246
|
+
*/
|
|
128
247
|
static VALUE Time_cmp(VALUE self, VALUE rb_other) {
|
|
129
|
-
sfTime a = ((Time
|
|
248
|
+
sfTime a = ((Time*)Get_Time_Struct(self))->time;
|
|
130
249
|
sfTime b = time_from_rb(rb_other);
|
|
131
250
|
int64_t micro_a = sfTime_asMicroseconds(a);
|
|
132
251
|
int64_t micro_b = sfTime_asMicroseconds(b);
|
|
@@ -142,29 +261,52 @@ static VALUE Time_cmp(VALUE self, VALUE rb_other) {
|
|
|
142
261
|
return INT2NUM(0);
|
|
143
262
|
}
|
|
144
263
|
|
|
264
|
+
/* call-seq:
|
|
265
|
+
* self == other -> true or false
|
|
266
|
+
*
|
|
267
|
+
* Returns +true+ if +other+ is a Time holding the same duration.
|
|
268
|
+
*
|
|
269
|
+
* @return [Boolean]
|
|
270
|
+
*/
|
|
145
271
|
static VALUE Time_eql(VALUE self, VALUE rb_other) {
|
|
146
272
|
if (!rb_obj_is_kind_of(rb_other, rb_cSFTime)) {
|
|
147
273
|
return Qfalse;
|
|
148
274
|
}
|
|
149
275
|
|
|
150
|
-
return BOOL2RB(sfTime_asMicroseconds(((Time
|
|
151
|
-
sfTime_asMicroseconds(((Time
|
|
276
|
+
return BOOL2RB(sfTime_asMicroseconds(((Time*)Get_Time_Struct(self))->time) ==
|
|
277
|
+
sfTime_asMicroseconds(((Time*)Get_Time_Struct(rb_other))->time));
|
|
152
278
|
}
|
|
153
279
|
|
|
280
|
+
/* call-seq: to_s -> String
|
|
281
|
+
*
|
|
282
|
+
* Returns the duration formatted as a number of seconds.
|
|
283
|
+
*
|
|
284
|
+
* @return [String] +"N s"+, e.g. +"1.5 s"+
|
|
285
|
+
*/
|
|
154
286
|
static VALUE Time_to_s(VALUE self) {
|
|
155
287
|
char buffer[64];
|
|
156
288
|
|
|
157
|
-
snprintf(buffer, sizeof(buffer), "%g s",
|
|
289
|
+
snprintf(buffer, sizeof(buffer), "%g s",
|
|
290
|
+
sfTime_asSeconds(((Time*)Get_Time_Struct(self))->time));
|
|
158
291
|
|
|
159
292
|
return rb_str_new2(buffer);
|
|
160
293
|
}
|
|
161
294
|
|
|
162
|
-
|
|
163
|
-
|
|
295
|
+
/* Document-class: SFML::Time
|
|
296
|
+
* A time duration, with microsecond precision internally. Used throughout
|
|
297
|
+
* the library wherever a duration or timestamp is needed (Clock#elapsed_time,
|
|
298
|
+
* SoundSource#playing_offset, sleep, animation timers, ...).
|
|
299
|
+
*
|
|
300
|
+
* Includes +Comparable+.
|
|
301
|
+
*/
|
|
302
|
+
void Init_Time(VALUE rb_mSFML) {
|
|
303
|
+
rb_cSFTime = rb_define_class_under(rb_mSFML, "Time", rb_cObject);
|
|
164
304
|
|
|
165
305
|
rb_include_module(rb_cSFTime, rb_mComparable);
|
|
166
306
|
|
|
167
|
-
|
|
307
|
+
rb_define_alloc_func(rb_cSFTime, Time_alloc);
|
|
308
|
+
rb_define_method(rb_cSFTime, "initialize", Time_initialize, -1);
|
|
309
|
+
|
|
168
310
|
rb_define_singleton_method(rb_cSFTime, "seconds", Time_seconds, 1);
|
|
169
311
|
rb_define_singleton_method(rb_cSFTime, "milliseconds", Time_milliseconds, 1);
|
|
170
312
|
rb_define_singleton_method(rb_cSFTime, "microseconds", Time_microseconds, 1);
|
|
@@ -189,23 +331,23 @@ VALUE Get_Klass_Time(void) {
|
|
|
189
331
|
return rb_cSFTime;
|
|
190
332
|
}
|
|
191
333
|
|
|
192
|
-
void
|
|
193
|
-
Time
|
|
334
|
+
void* Get_Time_Struct(VALUE self) {
|
|
335
|
+
Time* ptr;
|
|
194
336
|
TypedData_Get_Struct(self, Time, &Time_data_type, ptr);
|
|
195
337
|
return ptr;
|
|
196
338
|
}
|
|
197
339
|
|
|
198
340
|
sfTime time_from_rb(VALUE rb_time) {
|
|
199
341
|
if (rb_obj_is_kind_of(rb_time, rb_cSFTime)) {
|
|
200
|
-
return ((Time
|
|
342
|
+
return ((Time*)Get_Time_Struct(rb_time))->time;
|
|
201
343
|
}
|
|
202
344
|
|
|
203
345
|
if (RB_INTEGER_TYPE_P(rb_time)) {
|
|
204
|
-
return sfMicroseconds((int64_t)
|
|
346
|
+
return sfMicroseconds((int64_t)NUM2LL(rb_time));
|
|
205
347
|
}
|
|
206
348
|
|
|
207
349
|
if (RB_FLOAT_TYPE_P(rb_time) || RB_TYPE_P(rb_time, T_RATIONAL)) {
|
|
208
|
-
return sfSeconds((float)
|
|
350
|
+
return sfSeconds((float)NUM2DBL(rb_time));
|
|
209
351
|
}
|
|
210
352
|
|
|
211
353
|
raise_invalid_argument_class(rb_cSFTime);
|