sfml3-rb 0.3.0 → 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 (117) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -0
  3. data/README.md +36 -13
  4. data/TODO.md +18 -11
  5. data/ext/audio/music.c +6 -0
  6. data/ext/audio/sound.c +43 -4
  7. data/ext/audio/sound_buffer.c +8 -0
  8. data/ext/audio/sound_buffer_recorder.c +8 -3
  9. data/ext/audio/sound_recorder.c +21 -11
  10. data/ext/audio/sound_source_cone.c +18 -3
  11. data/ext/audio/sound_stream.c +25 -15
  12. data/ext/ext.c +4 -0
  13. data/ext/graphics/blend_mode.c +16 -8
  14. data/ext/graphics/circle.c +30 -13
  15. data/ext/graphics/color.c +17 -8
  16. data/ext/graphics/drawable.c +3 -2
  17. data/ext/graphics/font.c +6 -0
  18. data/ext/graphics/glyph.c +7 -0
  19. data/ext/graphics/image.c +25 -4
  20. data/ext/graphics/polygon.c +31 -11
  21. data/ext/graphics/rect.c +16 -8
  22. data/ext/graphics/rectangle.c +30 -11
  23. data/ext/graphics/render_state.c +8 -10
  24. data/ext/graphics/render_texture.c +27 -11
  25. data/ext/graphics/render_window.c +55 -0
  26. data/ext/graphics/render_window.h +10 -0
  27. data/ext/graphics/shader.c +6 -0
  28. data/ext/graphics/shape.c +23 -16
  29. data/ext/graphics/sprite.c +34 -10
  30. data/ext/graphics/stencil_mode.c +16 -8
  31. data/ext/graphics/target.c +60 -27
  32. data/ext/graphics/target.h +22 -8
  33. data/ext/graphics/text.c +33 -13
  34. data/ext/graphics/texture.c +34 -3
  35. data/ext/graphics/transformable.c +11 -20
  36. data/ext/graphics/vertex.c +18 -3
  37. data/ext/graphics/vertex_array.c +18 -9
  38. data/ext/graphics/vertex_buffer.c +30 -10
  39. data/ext/graphics/view.c +16 -10
  40. data/ext/network/ftp.c +30 -3
  41. data/ext/network/http.c +23 -6
  42. data/ext/network/ip_address.c +25 -14
  43. data/ext/network/packet.c +8 -3
  44. data/ext/network/socket_selector.c +8 -3
  45. data/ext/network/tcp_listener.c +8 -3
  46. data/ext/network/tcp_socket.c +8 -3
  47. data/ext/network/udp_socket.c +8 -3
  48. data/ext/system/buffer.c +13 -11
  49. data/ext/system/clock.c +11 -5
  50. data/ext/system/input_stream.c +21 -11
  51. data/ext/system/time.c +17 -13
  52. data/ext/system/vec2.c +17 -11
  53. data/ext/system/vec3.c +18 -11
  54. data/ext/window/context.c +14 -11
  55. data/ext/window/context_settings.c +16 -4
  56. data/ext/window/cursor.c +6 -0
  57. data/ext/window/event.c +15 -25
  58. data/ext/window/mouse.c +28 -11
  59. data/ext/window/touch.c +12 -10
  60. data/ext/window/video_mode.c +16 -25
  61. data/ext/window/window.c +110 -435
  62. data/ext/window/window.h +4 -4
  63. data/ext/window/window_base.c +251 -0
  64. data/ext/window/window_base.h +43 -0
  65. data/ext/window/window_base.inc +236 -0
  66. data/lib/sfml/version.rb +1 -1
  67. data/sig/audio/sound.rbs +1 -1
  68. data/sig/audio/sound_buffer_recorder.rbs +1 -1
  69. data/sig/audio/sound_recorder.rbs +1 -1
  70. data/sig/audio/sound_source_cone.rbs +1 -1
  71. data/sig/audio/sound_stream.rbs +1 -1
  72. data/sig/graphics/blend_mode.rbs +1 -1
  73. data/sig/graphics/circle.rbs +1 -1
  74. data/sig/graphics/color.rbs +5 -5
  75. data/sig/graphics/image.rbs +1 -1
  76. data/sig/graphics/polygon.rbs +1 -1
  77. data/sig/graphics/rect.rbs +5 -5
  78. data/sig/graphics/rectangle.rbs +1 -1
  79. data/sig/graphics/render_state.rbs +2 -2
  80. data/sig/graphics/render_target.rbs +18 -0
  81. data/sig/graphics/render_texture.rbs +4 -2
  82. data/sig/graphics/render_window.rbs +7 -0
  83. data/sig/graphics/shape.rbs +1 -1
  84. data/sig/graphics/sprite.rbs +2 -2
  85. data/sig/graphics/stencil_mode.rbs +2 -2
  86. data/sig/graphics/target.rbs +1 -3
  87. data/sig/graphics/text.rbs +4 -4
  88. data/sig/graphics/texture.rbs +1 -1
  89. data/sig/graphics/transformable.rbs +1 -1
  90. data/sig/graphics/vertex.rbs +4 -4
  91. data/sig/graphics/vertex_array.rbs +1 -1
  92. data/sig/graphics/vertex_buffer.rbs +4 -4
  93. data/sig/graphics/view.rbs +0 -1
  94. data/sig/network/ftp.rbs +1 -1
  95. data/sig/network/http.rbs +2 -2
  96. data/sig/network/ip_address.rbs +1 -1
  97. data/sig/network/packet.rbs +1 -1
  98. data/sig/network/socket_selector.rbs +1 -1
  99. data/sig/network/tcp_listener.rbs +1 -1
  100. data/sig/network/tcp_socket.rbs +1 -1
  101. data/sig/network/udp_socket.rbs +1 -1
  102. data/sig/sfml/version.rbs +3 -0
  103. data/sig/system/buffer.rbs +1 -1
  104. data/sig/system/clock.rbs +1 -1
  105. data/sig/system/input_stream.rbs +1 -1
  106. data/sig/system/time.rbs +4 -4
  107. data/sig/system/vec2.rbs +4 -4
  108. data/sig/system/vec3.rbs +4 -4
  109. data/sig/window/context.rbs +1 -1
  110. data/sig/window/context_settings.rbs +1 -1
  111. data/sig/window/event.rbs +1 -1
  112. data/sig/window/mouse.rbs +2 -2
  113. data/sig/window/touch.rbs +1 -1
  114. data/sig/window/video_mode.rbs +1 -1
  115. data/sig/window/window.rbs +2 -25
  116. data/sig/window/window_base.rbs +33 -0
  117. metadata +11 -2
data/ext/graphics/shape.c CHANGED
@@ -96,20 +96,14 @@ static sfVector2f CustomShape_get_point(size_t index, void* userData) {
96
96
  return vec2f_from_rb(point);
97
97
  }
98
98
 
99
- /* call-seq:
100
- * Shape.new -> Shape
101
- *
102
- * A base class meant to be subclassed: override #point_count and #point(i)
103
- * in Ruby to define the shape's geometry, then call #update! whenever it
104
- * changes.
105
- *
106
- * @return [Shape]
107
- * @raise [RuntimeError] if the underlying shape cannot be created
108
- */
109
- static VALUE CustomShape_new(VALUE klass) {
99
+ static VALUE CustomShape_alloc(VALUE klass) {
110
100
  CustomShape* ptr = malloc(sizeof(CustomShape));
111
101
  VALUE self;
112
102
 
103
+ if (ptr == NULL) {
104
+ rb_raise(rb_eNoMemError, "failed to allocate shape");
105
+ }
106
+
113
107
  ptr->rb_self = Qnil;
114
108
  ptr->rb_texture = Qnil;
115
109
  ptr->shape = sfShape_create(CustomShape_get_point_count, CustomShape_get_point, ptr);
@@ -125,6 +119,19 @@ static VALUE CustomShape_new(VALUE klass) {
125
119
  return self;
126
120
  }
127
121
 
122
+ /* call-seq:
123
+ * Shape.new -> Shape
124
+ *
125
+ * A base class meant to be subclassed: override #point_count and #point(i)
126
+ * in Ruby to define the shape's geometry, then call #update! whenever it
127
+ * changes.
128
+ *
129
+ * @return [Shape]
130
+ */
131
+ static VALUE CustomShape_initialize(VALUE self) {
132
+ return self;
133
+ }
134
+
128
135
  /* call-seq: update! -> self
129
136
  *
130
137
  * Recomputes the shape's geometry by calling back into the subclass's
@@ -443,15 +450,13 @@ static VALUE CustomShape_get_global_bounds(VALUE self) {
443
450
  * @return [nil]
444
451
  */
445
452
  static VALUE CustomShape_draw(VALUE self, VALUE rb_target, VALUE rb_state) {
446
- if (!rb_obj_is_kind_of(rb_target, Get_Klass_Target())) {
447
- raise_invalid_argument_class(Get_Klass_Target());
448
- }
453
+ TargetView view = Get_RenderTarget_View(rb_target);
449
454
 
450
455
  if (!rb_obj_is_kind_of(rb_state, Get_Klass_RenderState())) {
451
456
  raise_invalid_argument_class(Get_Klass_RenderState());
452
457
  }
453
458
 
454
- TARGET_DRAW(Get_Target_Struct(rb_target), sfRenderWindow_drawShape, sfRenderTexture_drawShape,
459
+ TARGET_DRAW(view, sfRenderWindow_drawShape, sfRenderTexture_drawShape,
455
460
  Get_CustomShape_Struct(self), Get_RenderState_Struct(rb_state));
456
461
 
457
462
  return Qnil;
@@ -495,9 +500,11 @@ static VALUE CustomShape_draw(VALUE self, VALUE rb_target, VALUE rb_state) {
495
500
  void Init_Shape(VALUE rb_mSFML) {
496
501
  rb_cCustomShape = rb_define_class_under(rb_mSFML, "Shape", rb_cObject);
497
502
 
503
+ rb_define_alloc_func(rb_cCustomShape, CustomShape_alloc);
504
+
498
505
  rb_include_module(rb_cCustomShape, Get_Module_Drawable());
499
506
 
500
- rb_define_singleton_method(rb_cCustomShape, "new", CustomShape_new, 0);
507
+ rb_define_method(rb_cCustomShape, "initialize", CustomShape_initialize, 0);
501
508
 
502
509
  rb_define_method(rb_cCustomShape, "update!", CustomShape_update, 0);
503
510
  rb_define_method(rb_cCustomShape, "position", CustomShape_get_position, 0);
@@ -26,7 +26,10 @@ static void Sprite_mark(void* ptr) {
26
26
  }
27
27
 
28
28
  static void Sprite_free(void* ptr) {
29
- sfSprite_destroy(((Sprite*)ptr)->sprite);
29
+ if (((Sprite*)ptr)->sprite != NULL) {
30
+ sfSprite_destroy(((Sprite*)ptr)->sprite);
31
+ }
32
+
30
33
  free(ptr);
31
34
  }
32
35
 
@@ -59,6 +62,24 @@ static VALUE Sprite_wrap(VALUE klass, sfSprite* sprite) {
59
62
  return TypedData_Wrap_Struct(klass, &Sprite_data_type, ptr);
60
63
  }
61
64
 
65
+ static VALUE Sprite_initialize_copy(VALUE self, VALUE other) {
66
+ (void)other;
67
+ rb_raise(rb_eTypeError, "can't copy a %s", rb_obj_classname(self));
68
+ }
69
+
70
+ static VALUE Sprite_alloc(VALUE klass) {
71
+ Sprite* ptr = malloc(sizeof(Sprite));
72
+
73
+ if (ptr == NULL) {
74
+ rb_raise(rb_eNoMemError, "failed to allocate sprite");
75
+ }
76
+
77
+ ptr->sprite = NULL;
78
+ ptr->rb_texture = Qnil;
79
+
80
+ return TypedData_Wrap_Struct(klass, &Sprite_data_type, ptr);
81
+ }
82
+
62
83
  /* call-seq:
63
84
  * Sprite.new(texture) -> Sprite
64
85
  *
@@ -69,19 +90,21 @@ static VALUE Sprite_wrap(VALUE klass, sfSprite* sprite) {
69
90
  * @return [Sprite]
70
91
  * @raise [ArgumentError] if +texture+ is not a Texture
71
92
  */
72
- static VALUE Sprite_new(VALUE klass, VALUE rb_texture) {
73
- VALUE self;
93
+ static VALUE Sprite_initialize(VALUE self, VALUE rb_texture) {
74
94
  Sprite* ptr;
75
95
 
76
96
  if (!rb_obj_is_kind_of(rb_texture, Get_Klass_Texture())) {
77
97
  raise_invalid_argument_class(Get_Klass_Texture());
78
98
  }
79
99
 
80
- ptr = malloc(sizeof(Sprite));
100
+ TypedData_Get_Struct(self, Sprite, &Sprite_data_type, ptr);
101
+
81
102
  ptr->sprite = sfSprite_create(Get_Texture_Struct(rb_texture));
82
103
  ptr->rb_texture = rb_texture;
83
104
 
84
- self = TypedData_Wrap_Struct(klass, &Sprite_data_type, ptr);
105
+ if (ptr->sprite == NULL) {
106
+ rb_raise(rb_eRuntimeError, "failed to create sprite");
107
+ }
85
108
 
86
109
  return self;
87
110
  }
@@ -356,15 +379,13 @@ static VALUE Sprite_get_global_bounds(VALUE self) {
356
379
  * RenderState
357
380
  */
358
381
  static VALUE Sprite_draw(VALUE self, VALUE rb_target, VALUE rb_state) {
359
- if (!rb_obj_is_kind_of(rb_target, Get_Klass_Target())) {
360
- raise_invalid_argument_class(Get_Klass_Target());
361
- }
382
+ TargetView view = Get_RenderTarget_View(rb_target);
362
383
 
363
384
  if (!rb_obj_is_kind_of(rb_state, Get_Klass_RenderState())) {
364
385
  raise_invalid_argument_class(Get_Klass_RenderState());
365
386
  }
366
387
 
367
- TARGET_DRAW(Get_Target_Struct(rb_target), sfRenderWindow_drawSprite, sfRenderTexture_drawSprite,
388
+ TARGET_DRAW(view, sfRenderWindow_drawSprite, sfRenderTexture_drawSprite,
368
389
  Get_Sprite_Struct(self), Get_RenderState_Struct(rb_state));
369
390
 
370
391
  return Qnil;
@@ -402,9 +423,12 @@ static VALUE Sprite_draw(VALUE self, VALUE rb_target, VALUE rb_state) {
402
423
  void Init_Sprite(VALUE rb_mSFML) {
403
424
  rb_cSprite = rb_define_class_under(rb_mSFML, "Sprite", rb_cObject);
404
425
 
426
+ rb_define_alloc_func(rb_cSprite, Sprite_alloc);
427
+
405
428
  rb_include_module(rb_cSprite, Get_Module_Drawable());
406
429
 
407
- rb_define_singleton_method(rb_cSprite, "new", Sprite_new, 1);
430
+ rb_define_method(rb_cSprite, "initialize", Sprite_initialize, 1);
431
+ rb_define_private_method(rb_cSprite, "initialize_copy", Sprite_initialize_copy, 1);
408
432
 
409
433
  rb_define_method(rb_cSprite, "copy", Sprite_copy, 0);
410
434
 
@@ -78,6 +78,18 @@ static sfStencilUpdateOperation operation_from_rb(VALUE rb_value) {
78
78
  return sfStencilUpdateOperationKeep;
79
79
  }
80
80
 
81
+ static VALUE StencilMode_alloc(VALUE klass) {
82
+ StencilMode* ptr = malloc(sizeof(StencilMode));
83
+
84
+ if (ptr == NULL) {
85
+ rb_raise(rb_eNoMemError, "failed to allocate stencil mode");
86
+ }
87
+
88
+ ptr->mode = sfStencilMode_default;
89
+
90
+ return TypedData_Wrap_Struct(klass, &StencilMode_data_type, ptr);
91
+ }
92
+
81
93
  /* call-seq:
82
94
  * StencilMode.new -> StencilMode
83
95
  * StencilMode.new(comparison, update_operation, reference, mask, stencil_only) -> StencilMode
@@ -90,9 +102,7 @@ static sfStencilUpdateOperation operation_from_rb(VALUE rb_value) {
90
102
  * @return [StencilMode]
91
103
  * @raise [ArgumentError] if given an argument count other than 0 or 5
92
104
  */
93
- static VALUE StencilMode_new(int argc, VALUE* argv, VALUE klass) {
94
- VALUE self;
95
- StencilMode* ptr;
105
+ static VALUE StencilMode_initialize(int argc, VALUE* argv, VALUE self) {
96
106
  sfStencilMode mode = sfStencilMode_default;
97
107
 
98
108
  if (argc == 5) {
@@ -105,10 +115,7 @@ static VALUE StencilMode_new(int argc, VALUE* argv, VALUE klass) {
105
115
  raise_invalid_arguments_excepted(5, argc);
106
116
  }
107
117
 
108
- ptr = malloc(sizeof(StencilMode));
109
- ptr->mode = mode;
110
-
111
- self = TypedData_Wrap_Struct(klass, &StencilMode_data_type, ptr);
118
+ ((StencilMode*)Get_StencilMode_Struct(self))->mode = mode;
112
119
 
113
120
  return self;
114
121
  }
@@ -280,7 +287,8 @@ static VALUE StencilMode_eql(VALUE self, VALUE rb_other) {
280
287
  void Init_StencilMode(VALUE rb_mSFML) {
281
288
  rb_cStencilMode = rb_define_class_under(rb_mSFML, "StencilMode", rb_cObject);
282
289
 
283
- rb_define_singleton_method(rb_cStencilMode, "new", StencilMode_new, -1);
290
+ rb_define_alloc_func(rb_cStencilMode, StencilMode_alloc);
291
+ rb_define_method(rb_cStencilMode, "initialize", StencilMode_initialize, -1);
284
292
 
285
293
  rb_define_method(rb_cStencilMode, "comparison", StencilMode_get_comparison, 0);
286
294
  rb_define_method(rb_cStencilMode, "update_operation", StencilMode_get_operation, 0);
@@ -5,16 +5,22 @@
5
5
 
6
6
  #include "graphics/render_state.h"
7
7
  #include "graphics/render_texture.h"
8
+ #include "graphics/render_window.h"
8
9
  #include "graphics/view.h"
9
10
  #include "window/window.h"
10
11
  #include "core/exceptions.h"
11
12
  #include "core/macros.h"
12
13
 
13
14
  static VALUE rb_cTarget;
15
+ static VALUE rb_mRenderTarget;
14
16
 
15
17
  static Target* Target_create(TargetType type, void* handle, VALUE rb_source) {
16
18
  Target* target = malloc(sizeof(Target));
17
19
 
20
+ if (target == NULL) {
21
+ rb_raise(rb_eNoMemError, "failed to allocate render target");
22
+ }
23
+
18
24
  target->type = type;
19
25
  target->handle = handle;
20
26
  target->rb_source = rb_source;
@@ -35,6 +41,15 @@ static const rb_data_type_t RenderTarget_data_type = {
35
41
  .function = {.dmark = RenderTarget_mark, .dfree = RenderTarget_free, .dsize = NULL},
36
42
  .flags = RUBY_TYPED_FREE_IMMEDIATELY};
37
43
 
44
+ static VALUE RenderTarget_wrap(VALUE klass, TargetType type, void* handle, VALUE rb_source) {
45
+ return TypedData_Wrap_Struct(klass, &RenderTarget_data_type,
46
+ Target_create(type, handle, rb_source));
47
+ }
48
+
49
+ static VALUE RenderTarget_alloc(VALUE klass) {
50
+ return RenderTarget_wrap(klass, SFML_TARGET_WINDOW, NULL, Qnil);
51
+ }
52
+
38
53
  /* call-seq:
39
54
  * Target.new(window) -> Target
40
55
  *
@@ -43,26 +58,21 @@ static const rb_data_type_t RenderTarget_data_type = {
43
58
  * @return [Target]
44
59
  * @raise [TypeError] if +window+ is not a Window
45
60
  */
46
- static VALUE RenderTarget_new(VALUE klass, VALUE rb_window) {
47
- VALUE self;
61
+ static VALUE RenderTarget_initialize(VALUE self, VALUE rb_window) {
48
62
  Target* target;
49
63
 
50
64
  if (!rb_obj_is_kind_of(rb_window, Get_Klass_Window())) {
51
65
  raise_invalid_argument_class(Get_Klass_Window());
52
66
  }
53
67
 
54
- target = Target_create(SFML_TARGET_WINDOW, Get_Window_Struct(rb_window), rb_window);
55
- self = TypedData_Wrap_Struct(klass, &RenderTarget_data_type, target);
56
-
57
- rb_obj_call_init(self, 0, NULL);
68
+ target = Get_Target_Struct(self);
69
+ target->type = SFML_TARGET_WINDOW;
70
+ target->handle = Get_Window_Struct(rb_window);
71
+ target->rb_source = rb_window;
58
72
 
59
73
  return self;
60
74
  }
61
75
 
62
- static VALUE RenderTarget_init(VALUE self) {
63
- return self;
64
- }
65
-
66
76
  /* call-seq:
67
77
  * draw(drawable, state) -> void
68
78
  *
@@ -123,22 +133,51 @@ static VALUE RenderTarget_get_view(VALUE self) {
123
133
  return Get_Casting_View(view);
124
134
  }
125
135
 
136
+ TargetView Get_RenderTarget_View(VALUE self) {
137
+ TargetView view;
138
+
139
+ if (rb_obj_is_kind_of(self, Get_Klass_Target())) {
140
+ Target* target = Get_Target_Struct(self);
141
+
142
+ view.type = target->type;
143
+ view.handle = target->handle;
144
+ return view;
145
+ }
146
+
147
+ if (rb_obj_is_kind_of(self, rb_mRenderTarget)) {
148
+ if (rb_obj_is_kind_of(self, Get_Klass_RenderWindow())) {
149
+ view.type = SFML_TARGET_WINDOW;
150
+ view.handle = Get_Window_Struct(self);
151
+ } else {
152
+ view.type = SFML_TARGET_TEXTURE;
153
+ view.handle = Get_RenderTexture_Struct(self);
154
+ }
155
+ return view;
156
+ }
157
+
158
+ rb_raise(rb_eArgError, "expected a RenderTarget (RenderWindow or RenderTexture)");
159
+ }
160
+
126
161
  /* Document-class: SFML::Target
127
- * A generic handle onto whatever can be drawn to -- a Window or a
162
+ * A legacy generic handle onto whatever can be drawn to -- a Window or a
128
163
  * RenderTexture -- used by Drawable#draw so drawable objects don't need to
129
164
  * know which concrete kind of target they're being drawn onto.
130
165
  *
166
+ * New code should pass a SFML::RenderWindow or SFML::RenderTexture (both
167
+ * include SFML::RenderTarget) straight to a drawable's #draw.
168
+ *
131
169
  * @!attribute view
132
170
  * The target's current view.
133
171
  * @return [View]
134
172
  */
135
173
  void Init_Target(VALUE rb_mSFML) {
136
174
  rb_cTarget = rb_define_class_under(rb_mSFML, "Target", rb_cObject);
175
+ rb_mRenderTarget = rb_define_module_under(rb_mSFML, "RenderTarget");
137
176
 
138
- rb_define_singleton_method(rb_cTarget, "new", RenderTarget_new, 1);
177
+ rb_define_alloc_func(rb_cTarget, RenderTarget_alloc);
139
178
 
140
179
  // methods
141
- rb_define_method(rb_cTarget, "initialize", RenderTarget_init, 0);
180
+ rb_define_method(rb_cTarget, "initialize", RenderTarget_initialize, 1);
142
181
  rb_define_method(rb_cTarget, "draw", RenderTarget_draw, 2);
143
182
 
144
183
  // setters
@@ -152,6 +191,10 @@ VALUE Get_Klass_Target(void) {
152
191
  return rb_cTarget;
153
192
  }
154
193
 
194
+ VALUE Get_Module_RenderTarget(void) {
195
+ return rb_mRenderTarget;
196
+ }
197
+
155
198
  Target* Get_Target_Struct(VALUE self) {
156
199
  Target* ptr;
157
200
  TypedData_Get_Struct(self, Target, &RenderTarget_data_type, ptr);
@@ -159,20 +202,10 @@ Target* Get_Target_Struct(VALUE self) {
159
202
  }
160
203
 
161
204
  VALUE Get_New_Target(VALUE rb_window) {
162
- return RenderTarget_new(Get_Klass_Target(), rb_window);
163
- }
164
-
165
- VALUE Get_New_Target_From_RenderTexture(VALUE rb_render_texture) {
166
- VALUE self;
167
- Target* target;
168
-
169
- if (!rb_obj_is_kind_of(rb_render_texture, Get_Klass_RenderTexture())) {
170
- raise_invalid_argument_class(Get_Klass_RenderTexture());
205
+ if (!rb_obj_is_kind_of(rb_window, Get_Klass_Window())) {
206
+ raise_invalid_argument_class(Get_Klass_Window());
171
207
  }
172
208
 
173
- target = Target_create(SFML_TARGET_TEXTURE, Get_RenderTexture_Struct(rb_render_texture),
174
- rb_render_texture);
175
- self = TypedData_Wrap_Struct(rb_cTarget, &RenderTarget_data_type, target);
176
-
177
- return self;
209
+ return RenderTarget_wrap(Get_Klass_Target(), SFML_TARGET_WINDOW, Get_Window_Struct(rb_window),
210
+ rb_window);
178
211
  }
@@ -7,23 +7,32 @@
7
7
 
8
8
  typedef enum { SFML_TARGET_WINDOW, SFML_TARGET_TEXTURE } TargetType;
9
9
 
10
+ /* A borrowed view onto whatever a draw call is headed for: the kind plus the
11
+ opaque handle. Built on the stack by Get_RenderTarget_View, never owned. */
10
12
  typedef struct {
11
13
  TargetType type;
12
14
  void* handle;
13
- /* The Window/RenderTexture `handle` is borrowed from, kept alive for as
14
- long as this Target references it -- see Target_mark in target.c. */
15
+ } TargetView;
16
+
17
+ /* The legacy generic wrapper behind SFML::Target. It owns only the borrow, so
18
+ it keeps its source alive for as long as it references it. */
19
+ typedef struct {
20
+ TargetType type;
21
+ void* handle;
22
+ /* The Window/RenderWindow/RenderTexture `handle` is borrowed from, kept
23
+ alive for as long as this Target references it -- see Target_mark. */
15
24
  VALUE rb_source;
16
25
  } Target;
17
26
 
18
- /* Dispatch a draw call to whichever underlying render surface this target
27
+ /* Dispatch a draw call to whichever underlying render surface this view
19
28
  wraps. Pass NULL states to use the defaults; never hand CSFML a NULL. */
20
- #define TARGET_DRAW(target, window_fn, texture_fn, object, states) \
29
+ #define TARGET_DRAW(view, window_fn, texture_fn, object, states) \
21
30
  do { \
22
31
  const sfRenderStates* sfml_states = (states) ? (states) : &sfRenderStates_default; \
23
- if ((target)->type == SFML_TARGET_WINDOW) { \
24
- window_fn((sfRenderWindow*)(target)->handle, (object), sfml_states); \
32
+ if ((view).type == SFML_TARGET_WINDOW) { \
33
+ window_fn((sfRenderWindow*)(view).handle, (object), sfml_states); \
25
34
  } else { \
26
- texture_fn((sfRenderTexture*)(target)->handle, (object), sfml_states); \
35
+ texture_fn((sfRenderTexture*)(view).handle, (object), sfml_states); \
27
36
  } \
28
37
  } while (0)
29
38
 
@@ -35,6 +44,11 @@ Target* Get_Target_Struct(VALUE self);
35
44
 
36
45
  VALUE Get_New_Target(VALUE rb_window);
37
46
 
38
- VALUE Get_New_Target_From_RenderTexture(VALUE rb_render_texture);
47
+ /* The SFML::RenderTarget module, included by RenderWindow and RenderTexture. */
48
+ VALUE Get_Module_RenderTarget(void);
49
+
50
+ /* Resolves any accepted draw target -- a legacy Target, a RenderWindow or a
51
+ RenderTexture -- to its kind and handle, raising TypeError otherwise. */
52
+ TargetView Get_RenderTarget_View(VALUE self);
39
53
 
40
54
  #endif // SFML_RB_GRAPHICS_TARGET_H
data/ext/graphics/text.c CHANGED
@@ -28,7 +28,10 @@ static void Text_mark(void* ptr) {
28
28
  }
29
29
 
30
30
  static void Text_free(void* ptr) {
31
- sfText_destroy(((Text*)ptr)->text);
31
+ if (((Text*)ptr)->text != NULL) {
32
+ sfText_destroy(((Text*)ptr)->text);
33
+ }
34
+
32
35
  free(ptr);
33
36
  }
34
37
 
@@ -61,6 +64,24 @@ static VALUE Text_wrap(VALUE klass, sfText* text) {
61
64
  return TypedData_Wrap_Struct(klass, &Text_data_type, ptr);
62
65
  }
63
66
 
67
+ static VALUE Text_initialize_copy(VALUE self, VALUE other) {
68
+ (void)other;
69
+ rb_raise(rb_eTypeError, "can't copy a %s", rb_obj_classname(self));
70
+ }
71
+
72
+ static VALUE Text_alloc(VALUE klass) {
73
+ Text* ptr = malloc(sizeof(Text));
74
+
75
+ if (ptr == NULL) {
76
+ rb_raise(rb_eNoMemError, "failed to allocate text");
77
+ }
78
+
79
+ ptr->text = NULL;
80
+ ptr->rb_font = Qnil;
81
+
82
+ return TypedData_Wrap_Struct(klass, &Text_data_type, ptr);
83
+ }
84
+
64
85
  /* call-seq:
65
86
  * Text.new(font) -> Text
66
87
  * Text.new(font, string) -> Text
@@ -73,8 +94,8 @@ static VALUE Text_wrap(VALUE klass, sfText* text) {
73
94
  * @return [Text]
74
95
  * @raise [ArgumentError] if +font+ is not a Font
75
96
  */
76
- static VALUE Text_new(int argc, VALUE* argv, VALUE klass) {
77
- VALUE rb_font, rb_string, rb_size, self;
97
+ static VALUE Text_initialize(int argc, VALUE* argv, VALUE self) {
98
+ VALUE rb_font, rb_string, rb_size;
78
99
  Text* ptr;
79
100
 
80
101
  rb_scan_args(argc, argv, "12", &rb_font, &rb_string, &rb_size);
@@ -83,17 +104,15 @@ static VALUE Text_new(int argc, VALUE* argv, VALUE klass) {
83
104
  raise_invalid_argument_class(Get_Klass_Font());
84
105
  }
85
106
 
86
- ptr = malloc(sizeof(Text));
107
+ TypedData_Get_Struct(self, Text, &Text_data_type, ptr);
108
+
87
109
  ptr->text = sfText_create(Get_Font_Struct(rb_font));
88
110
  ptr->rb_font = rb_font;
89
111
 
90
112
  if (ptr->text == NULL) {
91
- free(ptr);
92
113
  rb_raise(rb_eRuntimeError, "failed to create text");
93
114
  }
94
115
 
95
- self = TypedData_Wrap_Struct(klass, &Text_data_type, ptr);
96
-
97
116
  if (!NIL_P(rb_string)) {
98
117
  sfText_setString(ptr->text, StringValueCStr(rb_string));
99
118
  }
@@ -531,16 +550,14 @@ static VALUE Text_get_global_bounds(VALUE self) {
531
550
  * RenderState
532
551
  */
533
552
  static VALUE Text_draw(VALUE self, VALUE rb_target, VALUE rb_state) {
534
- if (!rb_obj_is_kind_of(rb_target, Get_Klass_Target())) {
535
- raise_invalid_argument_class(Get_Klass_Target());
536
- }
553
+ TargetView view = Get_RenderTarget_View(rb_target);
537
554
 
538
555
  if (!rb_obj_is_kind_of(rb_state, Get_Klass_RenderState())) {
539
556
  raise_invalid_argument_class(Get_Klass_RenderState());
540
557
  }
541
558
 
542
- TARGET_DRAW(Get_Target_Struct(rb_target), sfRenderWindow_drawText, sfRenderTexture_drawText,
543
- Get_Text_Struct(self), Get_RenderState_Struct(rb_state));
559
+ TARGET_DRAW(view, sfRenderWindow_drawText, sfRenderTexture_drawText, Get_Text_Struct(self),
560
+ Get_RenderState_Struct(rb_state));
544
561
 
545
562
  return Qnil;
546
563
  }
@@ -594,9 +611,12 @@ static VALUE Text_draw(VALUE self, VALUE rb_target, VALUE rb_state) {
594
611
  void Init_Text(VALUE rb_mSFML) {
595
612
  rb_cText = rb_define_class_under(rb_mSFML, "Text", rb_cObject);
596
613
 
614
+ rb_define_alloc_func(rb_cText, Text_alloc);
615
+
597
616
  rb_include_module(rb_cText, Get_Module_Drawable());
598
617
 
599
- rb_define_singleton_method(rb_cText, "new", Text_new, -1);
618
+ rb_define_method(rb_cText, "initialize", Text_initialize, -1);
619
+ rb_define_private_method(rb_cText, "initialize_copy", Text_initialize_copy, 1);
600
620
 
601
621
  rb_define_method(rb_cText, "copy", Text_copy, 0);
602
622
  rb_define_method(rb_cText, "font", Text_get_font, 0);
@@ -76,6 +76,24 @@ static const sfIntRect* Texture_area_ptr(VALUE rb_area, sfIntRect* storage) {
76
76
  return storage;
77
77
  }
78
78
 
79
+ static VALUE Texture_initialize_copy(VALUE self, VALUE other) {
80
+ (void)other;
81
+ rb_raise(rb_eTypeError, "can't copy a %s", rb_obj_classname(self));
82
+ }
83
+
84
+ static VALUE Texture_alloc(VALUE klass) {
85
+ Texture* ptr = malloc(sizeof(Texture));
86
+
87
+ if (ptr == NULL) {
88
+ rb_raise(rb_eNoMemError, "failed to allocate texture");
89
+ }
90
+
91
+ ptr->texture = NULL;
92
+ ptr->owns = false;
93
+
94
+ return TypedData_Wrap_Struct(klass, &Texture_data_type, ptr);
95
+ }
96
+
79
97
  /* call-seq:
80
98
  * Texture.new(size) -> Texture
81
99
  *
@@ -84,8 +102,19 @@ static const sfIntRect* Texture_area_ptr(VALUE rb_area, sfIntRect* storage) {
84
102
  * @return [Texture] an empty texture of +size+ (a Vector2 or 2-element Array)
85
103
  * @raise [RuntimeError] if creation fails
86
104
  */
87
- static VALUE Texture_new(VALUE klass, VALUE rb_size) {
88
- return Texture_wrap(klass, sfTexture_create(vec2u_from_rb(rb_size)));
105
+ static VALUE Texture_initialize(VALUE self, VALUE rb_size) {
106
+ Texture* ptr;
107
+ sfTexture* texture = sfTexture_create(vec2u_from_rb(rb_size));
108
+
109
+ if (texture == NULL) {
110
+ rb_raise(rb_eRuntimeError, "failed to create texture");
111
+ }
112
+
113
+ TypedData_Get_Struct(self, Texture, &Texture_data_type, ptr);
114
+ ptr->texture = texture;
115
+ ptr->owns = true;
116
+
117
+ return self;
89
118
  }
90
119
 
91
120
  /* call-seq:
@@ -590,7 +619,9 @@ static VALUE Texture_maximum_size(VALUE klass) {
590
619
  void Init_Texture(VALUE rb_mSFML) {
591
620
  rb_cTexture = rb_define_class_under(rb_mSFML, "Texture", rb_cObject);
592
621
 
593
- rb_define_singleton_method(rb_cTexture, "new", Texture_new, 1);
622
+ rb_define_alloc_func(rb_cTexture, Texture_alloc);
623
+ rb_define_method(rb_cTexture, "initialize", Texture_initialize, 1);
624
+ rb_define_private_method(rb_cTexture, "initialize_copy", Texture_initialize_copy, 1);
594
625
  rb_define_singleton_method(rb_cTexture, "from_file", Texture_from_file, -1);
595
626
  rb_define_singleton_method(rb_cTexture, "from_memory", Texture_from_memory, -1);
596
627
  rb_define_singleton_method(rb_cTexture, "from_stream", Texture_from_stream, -1);
@@ -24,31 +24,22 @@ static const rb_data_type_t Transformable_data_type = {
24
24
  .function = {.dmark = NULL, .dfree = Transformable_free, .dsize = NULL},
25
25
  .flags = RUBY_TYPED_FREE_IMMEDIATELY};
26
26
 
27
- /* call-seq:
28
- * Transformable.new -> Transformable
29
- *
30
- * Creates a transformable object with a default position, rotation and scale.
31
- *
32
- * @return [Transformable]
33
- */
34
- static VALUE Transformable_new(VALUE klass) {
35
- VALUE self;
36
- sfTransformable* transformable;
27
+ static VALUE Transformable_alloc(VALUE klass) {
28
+ sfTransformable* transformable = Transformable_create();
37
29
 
38
- transformable = Transformable_create();
39
- self = TypedData_Wrap_Struct(klass, &Transformable_data_type, transformable);
30
+ if (transformable == NULL) {
31
+ rb_raise(rb_eRuntimeError, "failed to create transformable");
32
+ }
40
33
 
41
- rb_obj_call_init(self, 0, NULL);
42
-
43
- return self;
34
+ return TypedData_Wrap_Struct(klass, &Transformable_data_type, transformable);
44
35
  }
45
36
 
46
- /* call-seq: initialize -> self
37
+ /* call-seq:
38
+ * Transformable.new -> Transformable
47
39
  *
48
- * Initializes the transformable state, including position, rotation and scale.
40
+ * Creates a transformable object with a default position, rotation and scale.
49
41
  *
50
- * @private No-op; called internally by .new.
51
- * @return [self]
42
+ * @return [Transformable]
52
43
  */
53
44
  static VALUE Transformable_init(VALUE self) {
54
45
  return self;
@@ -258,7 +249,7 @@ static VALUE Transformable_copy(VALUE self) {
258
249
  void Init_Transformable(VALUE rb_mSFML) {
259
250
  rb_cTransformable = rb_define_class_under(rb_mSFML, "Transformable", rb_cObject);
260
251
 
261
- rb_define_singleton_method(rb_cTransformable, "new", Transformable_new, 0);
252
+ rb_define_alloc_func(rb_cTransformable, Transformable_alloc);
262
253
  rb_define_method(rb_cTransformable, "initialize", Transformable_init, 0);
263
254
 
264
255
  rb_define_method(rb_cTransformable, "position=", Transformable_set_position, 1);