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.
Files changed (148) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +9 -0
  3. data/CHANGELOG.md +67 -16
  4. data/README.md +123 -32
  5. data/TODO.md +18 -11
  6. data/ext/audio/audio_enums.c +58 -20
  7. data/ext/audio/listener.c +89 -6
  8. data/ext/audio/music.c +212 -5
  9. data/ext/audio/sound.c +218 -9
  10. data/ext/audio/sound_buffer.c +197 -47
  11. data/ext/audio/sound_buffer_recorder.c +90 -18
  12. data/ext/audio/sound_recorder.c +188 -58
  13. data/ext/audio/sound_source_cone.c +127 -33
  14. data/ext/audio/sound_stream.c +204 -21
  15. data/ext/core/exceptions.c +10 -8
  16. data/ext/core/unicode.c +12 -2
  17. data/ext/ext.c +8 -0
  18. data/ext/graphics/blend_mode.c +218 -60
  19. data/ext/graphics/circle.c +300 -16
  20. data/ext/graphics/color.c +253 -94
  21. data/ext/graphics/drawable.c +16 -4
  22. data/ext/graphics/font.c +144 -25
  23. data/ext/graphics/glyph.c +38 -8
  24. data/ext/graphics/image.c +205 -41
  25. data/ext/graphics/polygon.c +317 -30
  26. data/ext/graphics/rect.c +225 -60
  27. data/ext/graphics/rectangle.c +307 -35
  28. data/ext/graphics/render_state.c +124 -12
  29. data/ext/graphics/render_texture.c +191 -14
  30. data/ext/graphics/render_window.c +55 -0
  31. data/ext/graphics/render_window.h +10 -0
  32. data/ext/graphics/shader.c +289 -17
  33. data/ext/graphics/shape.c +265 -32
  34. data/ext/graphics/sprite.c +245 -30
  35. data/ext/graphics/stencil_mode.c +163 -46
  36. data/ext/graphics/target.c +121 -43
  37. data/ext/graphics/target.h +31 -17
  38. data/ext/graphics/text.c +339 -19
  39. data/ext/graphics/texture.c +291 -6
  40. data/ext/graphics/transform.c +178 -5
  41. data/ext/graphics/transformable.c +127 -12
  42. data/ext/graphics/vertex.c +98 -6
  43. data/ext/graphics/vertex_array.c +142 -21
  44. data/ext/graphics/vertex_buffer.c +154 -12
  45. data/ext/graphics/view.c +140 -6
  46. data/ext/network/ftp.c +278 -12
  47. data/ext/network/http.c +179 -44
  48. data/ext/network/ip_address.c +127 -35
  49. data/ext/network/network_enums.c +248 -141
  50. data/ext/network/packet.c +280 -41
  51. data/ext/network/socket_selector.c +98 -21
  52. data/ext/network/tcp_listener.c +82 -18
  53. data/ext/network/tcp_socket.c +135 -27
  54. data/ext/network/udp_socket.c +129 -28
  55. data/ext/ports.rb +7 -0
  56. data/ext/system/buffer.c +47 -16
  57. data/ext/system/clock.c +77 -12
  58. data/ext/system/input_stream.c +113 -51
  59. data/ext/system/sleep.c +10 -2
  60. data/ext/system/time.c +182 -40
  61. data/ext/system/vec2.c +166 -39
  62. data/ext/system/vec3.c +177 -39
  63. data/ext/window/clipboard.c +47 -17
  64. data/ext/window/context.c +66 -13
  65. data/ext/window/context_settings.c +132 -42
  66. data/ext/window/cursor.c +45 -9
  67. data/ext/window/event.c +164 -53
  68. data/ext/window/joystick.c +69 -3
  69. data/ext/window/keyboard.c +168 -116
  70. data/ext/window/mouse.c +64 -13
  71. data/ext/window/sensor.c +28 -2
  72. data/ext/window/touch.c +32 -12
  73. data/ext/window/video_mode.c +93 -31
  74. data/ext/window/vulkan.c +34 -6
  75. data/ext/window/window.c +228 -229
  76. data/ext/window/window.h +4 -4
  77. data/ext/window/window_base.c +251 -0
  78. data/ext/window/window_base.h +43 -0
  79. data/ext/window/window_base.inc +236 -0
  80. data/lib/sfml/version.rb +1 -1
  81. data/sig/audio/audio_enums.rbs +30 -0
  82. data/sig/audio/listener.rbs +16 -0
  83. data/sig/audio/music.rbs +56 -0
  84. data/sig/audio/sound.rbs +51 -0
  85. data/sig/audio/sound_buffer.rbs +17 -0
  86. data/sig/audio/sound_buffer_recorder.rbs +14 -0
  87. data/sig/audio/sound_recorder.rbs +17 -0
  88. data/sig/audio/sound_source_cone.rbs +14 -0
  89. data/sig/audio/sound_stream.rbs +51 -0
  90. data/sig/graphics/blend_mode.rbs +29 -0
  91. data/sig/graphics/circle.rbs +44 -0
  92. data/sig/graphics/color.rbs +39 -0
  93. data/sig/graphics/drawable.rbs +5 -0
  94. data/sig/graphics/font.rbs +20 -0
  95. data/sig/graphics/glyph.rbs +7 -0
  96. data/sig/graphics/image.rbs +22 -0
  97. data/sig/graphics/polygon.rbs +42 -0
  98. data/sig/graphics/rect.rbs +33 -0
  99. data/sig/graphics/rectangle.rbs +42 -0
  100. data/sig/graphics/render_state.rbs +21 -0
  101. data/sig/graphics/render_target.rbs +18 -0
  102. data/sig/graphics/render_texture.rbs +39 -0
  103. data/sig/graphics/render_window.rbs +7 -0
  104. data/sig/graphics/shader.rbs +39 -0
  105. data/sig/graphics/shape.rbs +38 -0
  106. data/sig/graphics/sprite.rbs +34 -0
  107. data/sig/graphics/stencil_mode.rbs +18 -0
  108. data/sig/graphics/target.rbs +8 -0
  109. data/sig/graphics/text.rbs +48 -0
  110. data/sig/graphics/texture.rbs +34 -0
  111. data/sig/graphics/transform.rbs +37 -0
  112. data/sig/graphics/transformable.rbs +25 -0
  113. data/sig/graphics/vertex.rbs +17 -0
  114. data/sig/graphics/vertex_array.rbs +17 -0
  115. data/sig/graphics/vertex_buffer.rbs +22 -0
  116. data/sig/graphics/view.rbs +23 -0
  117. data/sig/network/ftp.rbs +46 -0
  118. data/sig/network/http.rbs +27 -0
  119. data/sig/network/ip_address.rbs +22 -0
  120. data/sig/network/network_enums.rbs +95 -0
  121. data/sig/network/packet.rbs +40 -0
  122. data/sig/network/socket_selector.rbs +14 -0
  123. data/sig/network/tcp_listener.rbs +13 -0
  124. data/sig/network/tcp_socket.rbs +18 -0
  125. data/sig/network/udp_socket.rbs +17 -0
  126. data/sig/sfml/version.rbs +3 -0
  127. data/sig/system/buffer.rbs +11 -0
  128. data/sig/system/clock.rbs +13 -0
  129. data/sig/system/input_stream.rbs +7 -0
  130. data/sig/system/sleep.rbs +3 -0
  131. data/sig/system/time.rbs +28 -0
  132. data/sig/system/vec2.rbs +26 -0
  133. data/sig/system/vec3.rbs +27 -0
  134. data/sig/window/clipboard.rbs +8 -0
  135. data/sig/window/context.rbs +11 -0
  136. data/sig/window/context_settings.rbs +20 -0
  137. data/sig/window/cursor.rbs +6 -0
  138. data/sig/window/event.rbs +20 -0
  139. data/sig/window/joystick.rbs +15 -0
  140. data/sig/window/keyboard.rbs +10 -0
  141. data/sig/window/mouse.rbs +9 -0
  142. data/sig/window/sensor.rbs +8 -0
  143. data/sig/window/touch.rbs +6 -0
  144. data/sig/window/video_mode.rbs +16 -0
  145. data/sig/window/vulkan.rbs +7 -0
  146. data/sig/window/window.rbs +34 -0
  147. data/sig/window/window_base.rbs +33 -0
  148. metadata +76 -3
@@ -16,21 +16,20 @@ typedef struct {
16
16
 
17
17
  static VALUE rb_cInputStream;
18
18
 
19
- static void InputStream_mark(void *ptr) {
20
- InputStream *stream = ptr;
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 *ptr) {
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 *data;
40
+ void* data;
42
41
  int64_t result;
43
42
  } ReadContext;
44
43
 
45
44
  static VALUE InputStream_read_body(VALUE v) {
46
- ReadContext *ctx = (ReadContext *) v;
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) length > ctx->size) {
59
- length = (long) ctx->size;
57
+ if ((size_t)length > ctx->size) {
58
+ length = (long)ctx->size;
60
59
  }
61
60
 
62
61
  if (length > 0) {
63
- memcpy(ctx->data, RSTRING_PTR(str), (size_t) length);
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) length;
71
+ ctx->result = (int64_t)length;
67
72
 
68
73
  return Qnil;
69
74
  }
70
75
 
71
- static int64_t InputStream_read(void *data, size_t size, void *userData) {
72
- InputStream *stream = userData;
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) &ctx, &state);
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 *ctx = (SeekContext *) v;
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) ctx->position;
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 *userData) {
102
- InputStream *stream = userData;
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) &ctx, &state);
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
- VALUE io = (VALUE) v;
134
+ Int64Context* ctx = (Int64Context*)v;
135
+ VALUE result;
118
136
 
119
- if (rb_respond_to(io, rb_intern("tell"))) {
120
- return rb_funcall(io, rb_intern("tell"), 0);
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
- return rb_funcall(io, rb_intern("pos"), 0);
143
+ ctx->result = NUM2LL(result);
144
+
145
+ return Qnil;
124
146
  }
125
147
 
126
- static int64_t InputStream_tell(void *userData) {
127
- InputStream *stream = userData;
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
- VALUE result = rb_protect(InputStream_tell_body, stream->rb_io, &state);
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 NUM2LL(result);
160
+ return ctx.result;
137
161
  }
138
162
 
139
163
  static VALUE InputStream_get_size_body(VALUE v) {
140
- VALUE io = (VALUE) v;
164
+ Int64Context* ctx = (Int64Context*)v;
165
+ VALUE result;
141
166
 
142
- if (rb_respond_to(io, rb_intern("size"))) {
143
- return rb_funcall(io, rb_intern("size"), 0);
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
- return rb_funcall(io, rb_intern("length"), 0);
173
+ ctx->result = NUM2LL(result);
174
+
175
+ return Qnil;
147
176
  }
148
177
 
149
- static int64_t InputStream_get_size(void *userData) {
150
- InputStream *stream = userData;
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
- VALUE result = rb_protect(InputStream_get_size_body, stream->rb_io, &state);
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 NUM2LL(result);
190
+ return ctx.result;
160
191
  }
161
192
 
162
- static VALUE InputStream_new(VALUE klass, VALUE rb_io) {
163
- VALUE self;
164
- InputStream *stream;
193
+ static VALUE InputStream_alloc(VALUE klass) {
194
+ InputStream* stream = malloc(sizeof(InputStream));
165
195
 
166
- if (!rb_respond_to(rb_io, rb_intern("read"))) {
167
- rb_raise(rb_eArgError, "stream object must respond to #read");
196
+ if (stream == NULL) {
197
+ rb_raise(rb_eNoMemError, "failed to allocate input stream");
168
198
  }
169
199
 
170
- stream = malloc(sizeof(InputStream));
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
- self = TypedData_Wrap_Struct(klass, &InputStream_data_type, stream);
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 *) Get_InputStream_Struct(self))->rb_io;
241
+ return ((InputStream*)Get_InputStream_Struct(self))->rb_io;
186
242
  }
187
243
 
188
- void Init_InputStream(VALUE rb_module) {
189
- rb_cInputStream = rb_define_class_under(rb_module, "InputStream", rb_cObject);
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
- rb_define_singleton_method(rb_cInputStream, "new", InputStream_new, 1);
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 *Get_InputStream_Struct(VALUE self) {
201
- InputStream *ptr;
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 *input_stream_from_rb(VALUE rb_stream, VALUE *holder) {
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 rb_module) {
15
- rb_define_module_function(rb_module, "sleep", Sleep_sleep, 1);
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 *ptr) {
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 *ptr = malloc(sizeof(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 Time_new(int argc, VALUE *argv, VALUE klass) {
34
- VALUE self;
35
- Time *ptr;
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 *) Get_Time_Struct(argv[0]))->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) NUM2LL(argv[0]));
67
+ time = sfMicroseconds((int64_t)NUM2LL(argv[0]));
42
68
  } else if (argc == 1) {
43
- time = sfSeconds((float) NUM2DBL(argv[0]));
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
- ptr = malloc(sizeof(Time));
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) NUM2DBL(rb_seconds)));
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) NUM2INT(rb_milliseconds)));
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) NUM2LL(rb_microseconds)));
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 *) Get_Time_Struct(self))->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 *) Get_Time_Struct(self))->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 *) Get_Time_Struct(self))->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 *) Get_Time_Struct(self))->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 *) Get_Time_Struct(self))->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 *) Get_Time_Struct(self))->time;
210
+ sfTime a = ((Time*)Get_Time_Struct(self))->time;
108
211
 
109
- return Time_wrap(sfMicroseconds((int64_t) (sfTime_asMicroseconds(a) * NUM2DBL(rb_scalar))));
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 *) Get_Time_Struct(self))->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 *) Get_Time_Struct(rb_other))->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) sfTime_asMicroseconds(a) / (double) b);
234
+ return DBL2NUM((double)sfTime_asMicroseconds(a) / (double)b);
123
235
  }
124
236
 
125
- return Time_wrap(sfMicroseconds((int64_t) (sfTime_asMicroseconds(a) / NUM2DBL(rb_other))));
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 *) Get_Time_Struct(self))->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 *) Get_Time_Struct(self))->time) ==
151
- sfTime_asMicroseconds(((Time *) Get_Time_Struct(rb_other))->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", sfTime_asSeconds(((Time *) Get_Time_Struct(self))->time));
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
- void Init_Time(VALUE rb_module) {
163
- rb_cSFTime = rb_define_class_under(rb_module, "Time", rb_cObject);
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
- rb_define_singleton_method(rb_cSFTime, "new", Time_new, -1);
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 *Get_Time_Struct(VALUE self) {
193
- Time *ptr;
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 *) Get_Time_Struct(rb_time))->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) NUM2LL(rb_time));
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) NUM2DBL(rb_time));
350
+ return sfSeconds((float)NUM2DBL(rb_time));
209
351
  }
210
352
 
211
353
  raise_invalid_argument_class(rb_cSFTime);