ray 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (167) hide show
  1. data/README.md +9 -6
  2. data/Rakefile +1 -5
  3. data/ext/audio.c +25 -19
  4. data/ext/audio_source.c +67 -39
  5. data/ext/color.c +19 -19
  6. data/ext/drawable.c +190 -31
  7. data/ext/extconf.rb +16 -14
  8. data/ext/gl.c +310 -30
  9. data/ext/gl_buffer.c +223 -2
  10. data/ext/gl_index_buffer.c +11 -0
  11. data/ext/gl_int_array.c +24 -22
  12. data/ext/gl_vertex.c +84 -49
  13. data/ext/image.c +115 -51
  14. data/ext/image_target.c +58 -10
  15. data/ext/input.c +73 -6
  16. data/ext/mo.c +583 -0
  17. data/ext/mo.h +189 -0
  18. data/ext/music.c +9 -8
  19. data/ext/pixel_bus.c +349 -0
  20. data/ext/polygon.c +68 -45
  21. data/ext/ray.c +1 -0
  22. data/ext/ray.h +19 -1
  23. data/ext/rect.c +9 -47
  24. data/ext/say.h +1 -2
  25. data/ext/say_all.h +6 -0
  26. data/ext/say_audio.h +3 -0
  27. data/ext/say_audio_context.c +1 -4
  28. data/ext/say_basic_type.c +24 -0
  29. data/ext/say_basic_type.h +4 -0
  30. data/ext/say_buffer.c +217 -88
  31. data/ext/say_buffer.h +20 -5
  32. data/ext/say_buffer_renderer.c +10 -7
  33. data/ext/say_buffer_renderer.h +1 -1
  34. data/ext/say_buffer_slice.c +70 -76
  35. data/ext/say_context.c +109 -22
  36. data/ext/say_context.h +14 -0
  37. data/ext/say_drawable.c +113 -25
  38. data/ext/say_drawable.h +23 -2
  39. data/ext/say_error.c +7 -2
  40. data/ext/say_font.c +30 -27
  41. data/ext/say_font.h +3 -6
  42. data/ext/say_get_proc.c +35 -0
  43. data/ext/say_image.c +102 -27
  44. data/ext/say_image.h +11 -4
  45. data/ext/say_image_target.c +88 -34
  46. data/ext/say_image_target.h +3 -2
  47. data/ext/say_index_buffer.c +31 -19
  48. data/ext/say_index_buffer.h +4 -2
  49. data/ext/say_index_buffer_slice.c +78 -70
  50. data/ext/say_music.c +4 -2
  51. data/ext/say_osx.h +3 -2
  52. data/ext/say_osx_context.h +37 -4
  53. data/ext/say_osx_window.h +32 -37
  54. data/ext/say_pixel_bus.c +163 -0
  55. data/ext/say_pixel_bus.h +44 -0
  56. data/ext/say_polygon.c +2 -2
  57. data/ext/say_shader.c +66 -62
  58. data/ext/say_shader.h +2 -0
  59. data/ext/say_sprite.c +1 -2
  60. data/ext/say_target.c +14 -23
  61. data/ext/say_target.h +3 -1
  62. data/ext/say_text.c +45 -7
  63. data/ext/say_text.h +12 -3
  64. data/ext/say_thread.c +13 -6
  65. data/ext/say_thread.h +1 -1
  66. data/ext/say_thread_variable.c +5 -5
  67. data/ext/say_vertex_type.c +79 -41
  68. data/ext/say_vertex_type.h +6 -2
  69. data/ext/say_view.c +10 -31
  70. data/ext/say_view.h +1 -5
  71. data/ext/say_win.h +2 -2
  72. data/ext/say_win_context.h +49 -11
  73. data/ext/say_win_window.h +30 -27
  74. data/ext/say_window.c +3 -3
  75. data/ext/say_x11.h +3 -1
  76. data/ext/say_x11_context.h +64 -10
  77. data/ext/say_x11_window.h +22 -17
  78. data/ext/shader.c +9 -0
  79. data/ext/sprite.c +7 -1
  80. data/ext/target.c +80 -28
  81. data/ext/text.c +43 -1
  82. data/ext/view.c +53 -1
  83. data/ext/window.c +4 -0
  84. data/lib/ray/animation_list.rb +17 -2
  85. data/lib/ray/audio_source.rb +11 -0
  86. data/lib/ray/color.rb +14 -0
  87. data/lib/ray/drawable.rb +23 -0
  88. data/lib/ray/dsl/event.rb +1 -9
  89. data/lib/ray/dsl/event_runner.rb +3 -4
  90. data/lib/ray/dsl/matcher.rb +20 -1
  91. data/lib/ray/effect.rb +116 -0
  92. data/lib/ray/effect/black_and_white.rb +38 -0
  93. data/lib/ray/effect/color_inversion.rb +16 -0
  94. data/lib/ray/effect/generator.rb +145 -0
  95. data/lib/ray/effect/grayscale.rb +32 -0
  96. data/lib/ray/game.rb +25 -5
  97. data/lib/ray/gl/vertex.rb +105 -26
  98. data/lib/ray/helper.rb +5 -0
  99. data/lib/ray/image.rb +54 -13
  100. data/lib/ray/image_target.rb +7 -0
  101. data/lib/ray/matrix.rb +26 -0
  102. data/lib/ray/music.rb +4 -0
  103. data/lib/ray/pixel_bus.rb +22 -0
  104. data/lib/ray/polygon.rb +17 -0
  105. data/lib/ray/pp.rb +28 -0
  106. data/lib/ray/ray.rb +7 -1
  107. data/lib/ray/rect.rb +7 -13
  108. data/lib/ray/scene.rb +24 -5
  109. data/lib/ray/scene_list.rb +9 -0
  110. data/lib/ray/shader.rb +11 -2
  111. data/lib/ray/sound.rb +4 -0
  112. data/lib/ray/sprite.rb +23 -62
  113. data/lib/ray/target.rb +25 -0
  114. data/lib/ray/text.rb +10 -0
  115. data/lib/ray/turtle.rb +9 -3
  116. data/lib/ray/vector.rb +18 -0
  117. data/lib/ray/vertex.rb +6 -0
  118. data/lib/ray/view.rb +22 -0
  119. data/samples/animation/sprite_motion.rb +0 -60
  120. data/samples/audio/{spacial.rb → spatial.rb} +1 -1
  121. data/samples/buffer/buffer.rb +1 -0
  122. data/samples/buffer/index_buffer.rb +2 -0
  123. data/samples/cptn_ruby/cptn_ruby.rb +6 -7
  124. data/samples/effects/effect.rb +39 -0
  125. data/samples/effects/grayscale.rb +27 -0
  126. data/samples/opengl/image.rb +7 -5
  127. data/samples/opengl/instancing.rb +159 -0
  128. data/samples/opengl/instancing.rbc +3231 -0
  129. data/samples/opengl/obj_loader.rb +9 -8
  130. data/samples/opengl/shader.rb +1 -3
  131. data/samples/shaders/geometry.rb +108 -38
  132. data/samples/shaders/geometry.rbc +2074 -0
  133. data/samples/shaders/shape.rb +2 -2
  134. data/samples/starfighter/starfighter.rb +5 -5
  135. data/samples/window/get_pixel.rb +1 -1
  136. data/test/animation_list_test.rb +18 -4
  137. data/test/drawable_test.rb +70 -1
  138. data/test/effect_generator_test.rb +63 -0
  139. data/test/effect_test.rb +61 -0
  140. data/test/game_test.rb +18 -0
  141. data/test/gl_buffer_test.rb +43 -1
  142. data/test/gl_index_buffer_test.rb +5 -0
  143. data/test/gl_vertex_test.rb +28 -1
  144. data/test/image_test.rb +5 -5
  145. data/test/input_test.rb +49 -0
  146. data/test/pixel_bus_test.rb +28 -0
  147. data/test/rect_test.rb +4 -0
  148. data/{samples/_media → test/res}/Beep.wav +0 -0
  149. data/samples/_media/CptnRuby Gem.png b/data/test/res/CptnRuby → Gem.png +0 -0
  150. data/samples/_media/CptnRuby Map.txt b/data/test/res/CptnRuby → Map.txt +0 -0
  151. data/samples/_media/CptnRuby Tileset.png b/data/test/res/CptnRuby → Tileset.png +0 -0
  152. data/{samples/_media → test/res}/CptnRuby.png +0 -0
  153. data/{samples/_media → test/res}/Space.png +0 -0
  154. data/{samples/_media → test/res}/Star.png +0 -0
  155. data/{samples/_media → test/res}/Starfighter.png +0 -0
  156. data/test/res/cube.obj +28 -0
  157. data/test/res/light3d.c +2 -2
  158. data/test/res/stone.png +0 -0
  159. data/test/scene_test.rb +3 -0
  160. data/test/sprite_test.rb +10 -0
  161. data/test/text_test.rb +31 -2
  162. data/test/view_test.rb +13 -1
  163. metadata +38 -17
  164. data/ext/say_array.c +0 -124
  165. data/ext/say_array.h +0 -34
  166. data/ext/say_table.c +0 -86
  167. data/ext/say_table.h +0 -24
@@ -0,0 +1,189 @@
1
+ #ifndef MY_OWN_HEADER_GUARD
2
+ #define MY_OWN_HEADER_GUARD 1
3
+
4
+ /**
5
+ * My Own utilities.
6
+ * (Depending on My Own mood, may mean "Mon_Ouie's utilities")
7
+ *
8
+ * Includes the data stuctures that I usually need when programming in C.
9
+ */
10
+
11
+ #include <stdlib.h>
12
+ #include <stdint.h>
13
+ #include <stdbool.h>
14
+ #include <assert.h>
15
+ #include <string.h>
16
+ #include <stdio.h>
17
+
18
+ /**
19
+ * Function pointer types
20
+ */
21
+
22
+ typedef void (*mo_init)(void *dst);
23
+ typedef void (*mo_release)(void *dst);
24
+ typedef void (*mo_copy)(void *dst, void *src);
25
+ typedef int (*mo_cmp)(const void *a, const void *b);
26
+ typedef int (*mo_hash_func)(void *obj);
27
+
28
+ /**
29
+ * Dynamic array.
30
+ */
31
+
32
+ typedef struct mo_array {
33
+ void *buffer;
34
+ size_t size;
35
+ size_t capa;
36
+ size_t el_size;
37
+
38
+ mo_init init;
39
+ mo_release release;
40
+ mo_copy copy;
41
+ } mo_array;
42
+
43
+ mo_array *mo_array_create(size_t el_size);
44
+ void mo_array_free(mo_array *ary);
45
+
46
+ void mo_array_init(mo_array *ary, size_t el_size);
47
+ void mo_array_release(mo_array *ary);
48
+
49
+ void *mo_array_quick_at(mo_array *ary, size_t i);
50
+ void *mo_array_at(mo_array *ary, size_t i);
51
+
52
+ #define mo_array_get_ptr(ary, i, type) ( (type*)mo_array_at(ary, i))
53
+ #define mo_array_get_as(ary, i, type) (*(type*)mo_array_at(ary, i))
54
+
55
+ void *mo_array_begin(mo_array *ary);
56
+ void *mo_array_end(mo_array *ary);
57
+
58
+ void mo_array_next(mo_array *ary, void **ptr);
59
+
60
+ void mo_array_set(mo_array *ary, size_t i, void *obj);
61
+
62
+ void mo_array_insert(mo_array *ary, size_t i, void *obj);
63
+ void mo_array_push(mo_array *ary, void *obj);
64
+ void mo_array_delete(mo_array *ary, size_t i);
65
+
66
+ mo_array mo_array_dup(mo_array *ary);
67
+ void mo_array_copy(mo_array *dst, mo_array *src);
68
+
69
+ mo_array *mo_array_qsort(mo_array *ary, mo_cmp cmp);
70
+
71
+ void mo_array_resize(mo_array *ary, size_t size);
72
+ void mo_array_reserve(mo_array *ary, size_t size);
73
+ void mo_array_shrink(mo_array *ary);
74
+
75
+ /**
76
+ * Doubly linked list.
77
+ */
78
+
79
+ typedef struct mo_list {
80
+ struct mo_list *prev, *next;
81
+
82
+ mo_release release;
83
+ mo_copy copy;
84
+
85
+ size_t el_size;
86
+ uint8_t data[];
87
+ } mo_list;
88
+
89
+ mo_list *mo_list_create(size_t el_size);
90
+ void mo_list_free(mo_list *list);
91
+
92
+ mo_list *mo_list_prepend(mo_list *list, void *data);
93
+ mo_list *mo_list_insert(mo_list *list, void *data);
94
+ mo_list *mo_list_delete(mo_list *list);
95
+
96
+ void mo_list_set(mo_list *list, void *data);
97
+
98
+ #define mo_list_data_ptr(list, type) ( (type*)list->data)
99
+ #define mo_list_data_as(list, type) (*(type*)list->data)
100
+
101
+ /**
102
+ * Hash table.
103
+ */
104
+
105
+ typedef struct mo_hash {
106
+ mo_array buffer;
107
+
108
+ mo_release release;
109
+ mo_copy copy;
110
+
111
+ mo_release key_release;
112
+ mo_copy key_copy;
113
+ mo_cmp key_cmp;
114
+
115
+ size_t size;
116
+
117
+ size_t el_size;
118
+ size_t key_size;
119
+
120
+ mo_hash_func hash_of;
121
+ } mo_hash;
122
+
123
+ typedef struct mo_hash_it {
124
+ mo_hash *hash;
125
+ mo_list *list;
126
+ size_t id;
127
+ } mo_hash_it;
128
+
129
+ int mo_hash_of_pointer(void *ptr);
130
+ int mo_hash_pointer_cmp(const void *a, const void *b);
131
+
132
+ int mo_hash_of_u32(void *ptr);
133
+ int mo_hash_u32_cmp(const void *a, const void *b);
134
+
135
+ int mo_hash_of_size(void *ptr);
136
+ int mo_hash_size_cmp(const void *a, const void *b);
137
+
138
+ mo_hash *mo_hash_create(size_t key_size, size_t el_size);
139
+ void mo_hash_free(mo_hash *hash);
140
+
141
+ bool mo_hash_has_key(mo_hash *hash, void *key);
142
+
143
+ void *mo_hash_get(mo_hash *hash, void *key);
144
+ void mo_hash_set(mo_hash *hash, void *key, void *data);
145
+ void mo_hash_del(mo_hash *hash, void *key);
146
+
147
+ #define mo_hash_get_ptr(hash, key, type) ( (type*)mo_hash_get(hash, key))
148
+ #define mo_hash_get_as(hash, key, type) (*(type*)mo_hash_get(hash, key))
149
+
150
+ mo_hash_it mo_hash_begin(mo_hash *hash);
151
+
152
+ bool mo_hash_it_is_end(mo_hash_it *it);
153
+
154
+ void *mo_hash_it_key(mo_hash_it *it);
155
+ void *mo_hash_it_val(mo_hash_it *it);
156
+
157
+ #define mo_hash_it_key_ptr(it, type) ( (type*)mo_hash_it_key(it))
158
+ #define mo_hash_it_key_as(it, type) (*(type*)mo_hash_it_key(it))
159
+
160
+ #define mo_hash_it_val_ptr(it, type) ( (type*)mo_hash_it_val(it))
161
+ #define mo_hash_it_val_as(it, type) (*(type*)mo_hash_it_val(it))
162
+
163
+ void mo_hash_it_next(mo_hash_it *it);
164
+
165
+ /**
166
+ * Set (macros atop a hash table).
167
+ */
168
+
169
+ typedef mo_hash mo_set;
170
+ typedef mo_hash_it mo_set_it;
171
+
172
+ #define mo_set_create(size) mo_hash_create(size, 0)
173
+ #define mo_set_free(set) mo_hash_delete(set)
174
+
175
+ #define mo_set_includes(set) mo_hash_has_key(set)
176
+
177
+ #define mo_set_add(set, el) mo_hash_set(set, el, NULL)
178
+ #define mo_set_del(set, el) mo_hash_del(set, el)
179
+
180
+ #define mo_set_begin(set) mo_hash_begin(set)
181
+
182
+ #define mo_set_it_is_end(it) mo_hash_it_is_end(it)
183
+ #define mo_set_it_val(it) mo_hash_it_key(it)
184
+ #define mo_set_it_next(it) mo_hash_it_next(it)
185
+
186
+ #define mo_set_it_val_ptr(it, type) mo_hash_it_key_ptr(it, type)
187
+ #define mo_set_it_val_as(it, type) mo_hash_it_key_as(it, type)
188
+
189
+ #endif /* MY OWN HEADER'S GUARD! */
@@ -21,9 +21,9 @@ VALUE ray_music_alloc(VALUE self) {
21
21
  }
22
22
 
23
23
  /*
24
- @overload open(filename)
25
- @param [String] filename Name of the file containing the music to load.
26
- */
24
+ * @overload open(filename)
25
+ * @param [String] filename Name of the file containing the music to load.
26
+ */
27
27
  static
28
28
  VALUE ray_music_open(VALUE self, VALUE arg) {
29
29
  say_music *music = ray_rb2music(self);
@@ -48,10 +48,10 @@ VALUE ray_music_set_looping(VALUE self, VALUE val) {
48
48
  }
49
49
 
50
50
  /*
51
- @overload seek(time)
52
- Seeks to a specific time in the music.
53
- @param [Float] time Time in seconds
54
- */
51
+ * @overload seek(time)
52
+ * Seeks to a specific time in the music
53
+ * @param [Float] time Time in seconds
54
+ */
55
55
  static
56
56
  VALUE ray_music_seek(VALUE self, VALUE time) {
57
57
  say_music_seek(ray_rb2music(self), NUM2DBL(time));
@@ -64,7 +64,8 @@ VALUE ray_music_time(VALUE self) {
64
64
  return rb_float_new(say_music_get_time(ray_rb2music(self)));
65
65
  }
66
66
 
67
- /* @return [Float] Duration of the music. 0 when no buffer is attached to the
67
+ /*
68
+ * @return [Float] Duration of the music. 0 when no buffer is attached to the
68
69
  * music.
69
70
  */
70
71
  static
@@ -0,0 +1,349 @@
1
+ #include "ray.h"
2
+
3
+ VALUE ray_cPixelBus = Qnil;
4
+
5
+ say_pixel_bus *ray_rb2pixel_bus(VALUE obj) {
6
+ if (!rb_obj_is_kind_of(obj, rb_path2class("Ray::PixelBus"))) {
7
+ rb_raise(rb_eTypeError, "can't convert %s into Ray::PixelBus",
8
+ RAY_OBJ_CLASSNAME(obj));
9
+ }
10
+
11
+ say_pixel_bus **ptr = NULL;
12
+ Data_Get_Struct(obj, say_pixel_bus*, ptr);
13
+
14
+ if (!*ptr)
15
+ rb_raise(rb_eRuntimeError, "trying to use uninitialized pixel bus");
16
+
17
+ return *ptr;
18
+ }
19
+
20
+ static
21
+ void ray_pixel_bus_free(say_pixel_bus **ptr) {
22
+ if (*ptr) say_pixel_bus_free(*ptr);
23
+ }
24
+
25
+ static
26
+ VALUE ray_pixel_bus_alloc(VALUE self) {
27
+ say_pixel_bus **obj = malloc(sizeof(say_pixel_bus*));
28
+ *obj = NULL;
29
+
30
+ return Data_Wrap_Struct(self, NULL, ray_pixel_bus_free, obj);
31
+ }
32
+
33
+ /*
34
+ * @overload initialize(type = :stream)
35
+ * @param type (see Ray::BufferRenderer#initialize)
36
+ */
37
+ static
38
+ VALUE ray_pixel_bus_init(int argc, VALUE *argv, VALUE self) {
39
+ if (!say_pixel_bus_is_available())
40
+ rb_raise(rb_eRuntimeError, "pixel buses aren't available on this platform");
41
+
42
+ GLenum mode = SAY_STREAM;
43
+
44
+ VALUE rb_mode = Qnil;
45
+ rb_scan_args(argc, argv, "01", &rb_mode);
46
+
47
+ if (!NIL_P(rb_mode)) mode = ray_buf_type(rb_mode);
48
+
49
+ say_pixel_bus **ptr = NULL;
50
+ Data_Get_Struct(self, say_pixel_bus*, ptr);
51
+
52
+ *ptr = say_pixel_bus_create(mode);
53
+
54
+ return self;
55
+ }
56
+
57
+ /*
58
+ * @return [Boolean] True if pixel buses are available on this platform
59
+ */
60
+ static
61
+ VALUE ray_pixel_bus_available(VALUE self) {
62
+ return say_pixel_bus_is_available() ? Qtrue : Qfalse;
63
+ }
64
+
65
+ /*
66
+ * @return [Integer] The capacity of the pixel bus, in pixels
67
+ */
68
+ static
69
+ VALUE ray_pixel_bus_size(VALUE self) {
70
+ return ULONG2NUM(say_pixel_bus_get_size(ray_rb2pixel_bus(self)));
71
+ }
72
+
73
+ /*
74
+ * @overload resize(new_size)
75
+ * Changes the capacity of the buffer
76
+ *
77
+ * This method needs to copy the buffers content onto client memory, and is
78
+ * thus signinficantly slower than {#resize!}. It should not be called if the
79
+ * current content of the buffer doesn't need to be read anymore.
80
+ *
81
+ * @param [Integer] new_size New capacity of the buffer
82
+ * @see PixelBus#resize!
83
+ */
84
+ static
85
+ VALUE ray_pixel_bus_resize(VALUE self, VALUE size) {
86
+ say_pixel_bus_resize(ray_rb2pixel_bus(self), NUM2ULONG(size));
87
+ return self;
88
+ }
89
+
90
+ /*
91
+ * @overload resize!(new_size)
92
+ * Changes the capacity of the buffer without preserving content
93
+ *
94
+ * This method allows to quickly resize the buffer used by the pixel bus. The
95
+ * content of the buffer is however undefined after this call.
96
+ *
97
+ * @param new_size (see #resize)
98
+ * @see PixelBus#resize
99
+ */
100
+ static
101
+ VALUE ray_pixel_bus_resize_fast(VALUE self, VALUE size) {
102
+ say_pixel_bus_resize_fast(ray_rb2pixel_bus(self), NUM2ULONG(size));
103
+ return self;
104
+ }
105
+
106
+ /*
107
+ * @overload pull(object, opts = {})
108
+ * Pulls data from an object
109
+ *
110
+ * This method reads a rectangle from an image on a target and stores it in
111
+ * the buffer, at a given offset. A rect can optionally be specified for
112
+ * targets. Otherwise, the whole object will be copied.
113
+ *
114
+ * @param [Ray::Image, Ray::Target] object Object to read pixels from
115
+ * @option opts [Integer] :offset (0) Offset from the buffer
116
+ * @option opts [Ray::Rect, nil] :rect Rect of pixels to read for targets
117
+ *
118
+ * @raise [RangeError] If this method attempts to write outside of the buffer
119
+ * boundaries.
120
+ *
121
+ * @return [Integer] Offset of the last read element, plus one.
122
+ */
123
+ static
124
+ VALUE ray_pixel_bus_pull(int argc, VALUE *argv, VALUE self) {
125
+ say_pixel_bus *bus = ray_rb2pixel_bus(self);
126
+
127
+ VALUE object, opts = Qnil;
128
+ rb_scan_args(argc, argv, "11", &object, &opts);
129
+
130
+ say_rect rect = say_make_rect(0, 0, 0, 0);
131
+ size_t offset = 0;
132
+
133
+ say_target *target = NULL;
134
+ say_image *image = NULL;
135
+
136
+ if (RAY_IS_A(object, rb_path2class("Ray::Target")))
137
+ target = ray_rb2target(object);
138
+ else
139
+ image = ray_rb2image(object);
140
+
141
+ say_vector2 size;
142
+
143
+ if (target)
144
+ size = say_target_get_size(target);
145
+ else
146
+ size = say_image_get_size(image);
147
+
148
+ if (!NIL_P(opts)) {
149
+ if (!RAY_IS_A(opts, rb_cHash)) {
150
+ rb_raise(rb_eTypeError, "can't convert %s into Hash",
151
+ RAY_OBJ_CLASSNAME(opts));
152
+ }
153
+
154
+ VALUE rb_rect = rb_hash_aref(opts, RAY_SYM("rect"));
155
+ VALUE rb_offset = rb_hash_aref(opts, RAY_SYM("offset"));
156
+
157
+ if (target) {
158
+ if (!NIL_P(rb_rect))
159
+ rect = ray_convert_to_rect(rb_rect);
160
+ else
161
+ rect = say_make_rect(0, 0, size.x, size.y);
162
+ }
163
+
164
+ if (!NIL_P(rb_offset))
165
+ offset = NUM2ULONG(rb_offset);
166
+ }
167
+ else if (target) {
168
+ say_vector2 size = say_target_get_size(target);
169
+ rect = say_make_rect(0, 0, size.x, size.y);
170
+ }
171
+
172
+ size_t ret = offset + (size_t)size.x * (size_t)size.y;
173
+ if (ret > say_pixel_bus_get_size(bus))
174
+ rb_raise(rb_eRangeError, "trying to write outside of buffer boundaries");
175
+
176
+ if (target) {
177
+ say_pixel_bus_pull_target(bus, target, offset,
178
+ rect.x, rect.y, rect.w, rect.h);
179
+ }
180
+ else {
181
+ say_pixel_bus_pull_image(bus, image, offset);
182
+ }
183
+
184
+ return ULONG2NUM(ret);
185
+ }
186
+
187
+ /*
188
+ * @overload push(image, opts = {})
189
+ * Pushes data from the buffer onto an image
190
+ *
191
+ * This method reads pixels from the buffer at a given offset, and copies them
192
+ * onto an image. A rect of pixels that must be replaced can be
193
+ * specifed. Otherwise, the whole texture will be replaced.
194
+ *
195
+ * @param [Ray::Image] image Image to copy the rect to
196
+ * @option opts :offset (see #pull)
197
+ * @option opts [Ray::Rect] :rect Rect of pixels to replace in the image
198
+ *
199
+ * @return [Ray::PixelBus] self
200
+ *
201
+ * @raise [RangeError] If this method tries to read pixels outside of the
202
+ * buffer boundaries or to write oustide of the image boundaries.
203
+ */
204
+ static
205
+ VALUE ray_pixel_bus_push(int argc, VALUE *argv, VALUE self) {
206
+ say_pixel_bus *bus = ray_rb2pixel_bus(self);
207
+
208
+ VALUE object, opts = Qnil;
209
+ rb_scan_args(argc, argv, "11", &object, &opts);
210
+
211
+ say_image *image = ray_rb2image(object);
212
+
213
+ say_vector2 size = say_image_get_size(image);
214
+
215
+ size_t offset = 0;
216
+ say_rect rect = say_make_rect(0, 0, size.x, size.y);
217
+
218
+ if (!NIL_P(opts)) {
219
+ if (!RAY_IS_A(opts, rb_cHash)) {
220
+ rb_raise(rb_eTypeError, "can't convert %s into Hash",
221
+ RAY_OBJ_CLASSNAME(opts));
222
+ }
223
+
224
+ VALUE rb_rect = rb_hash_aref(opts, RAY_SYM("rect"));
225
+ VALUE rb_offset = rb_hash_aref(opts, RAY_SYM("offset"));
226
+
227
+ if (!NIL_P(rb_rect))
228
+ rect = ray_convert_to_rect(rb_rect);
229
+
230
+ if (!NIL_P(rb_offset))
231
+ offset = NUM2ULONG(rb_offset);
232
+ }
233
+
234
+ size_t ret = offset + ((size_t)rect.w * (size_t)rect.h);
235
+ if (ret > say_pixel_bus_get_size(bus))
236
+ rb_raise(rb_eRangeError, "trying to read outside of pixel bus boundaries");
237
+
238
+ if (rect.x + rect.w > size.x || rect.y + rect.h > size.y)
239
+ rb_raise(rb_eRangeError, "trying to write outsied of image boundaries");
240
+
241
+ say_pixel_bus_push_image(bus, image, offset, rect.x, rect.y, rect.w, rect.h);
242
+ return self;
243
+ }
244
+
245
+ /*
246
+ * Binds the pixel bus for packing and unpacking
247
+ */
248
+ static
249
+ VALUE ray_pixel_bus_bind(VALUE self) {
250
+ say_pixel_bus_bind(ray_rb2pixel_bus(self));
251
+ return self;
252
+ }
253
+
254
+ /*
255
+ * Binds the pixel bus for packing
256
+ */
257
+ static
258
+ VALUE ray_pixel_bus_bind_pack(VALUE self) {
259
+ say_pixel_bus_bind_pack(ray_rb2pixel_bus(self));
260
+ return self;
261
+ }
262
+
263
+ /*
264
+ * Binds the pixel bus for unpacking
265
+ */
266
+ static
267
+ VALUE ray_pixel_bus_bind_unpack(VALUE self) {
268
+ say_pixel_bus_bind_unpack(ray_rb2pixel_bus(self));
269
+ return self;
270
+ }
271
+
272
+ /*
273
+ * Unbinds any pixel bus bound for either packing or unpacking
274
+ */
275
+ static
276
+ VALUE ray_pixel_bus_unbind(VALUE self) {
277
+ say_pixel_bus_unbind();
278
+ return Qnil;
279
+ }
280
+
281
+ /*
282
+ * Unbinds any pixel bus bound for packing
283
+ */
284
+ static
285
+ VALUE ray_pixel_bus_unbind_pack(VALUE self) {
286
+ say_pixel_bus_unbind_pack();
287
+ return Qnil;
288
+ }
289
+
290
+ /*
291
+ * Unbinds any pixel bus bound for unpacking
292
+ */
293
+ static
294
+ VALUE ray_pixel_bus_unbind_unpack(VALUE self) {
295
+ say_pixel_bus_unbind_unpack();
296
+ return Qnil;
297
+ }
298
+
299
+ /*
300
+ * @return [Integer] The identifier of the OpenGL buffer used by the PixelBus.
301
+ */
302
+ static
303
+ VALUE ray_pixel_bus_pbo(VALUE self) {
304
+ return ULONG2NUM(say_pixel_bus_get_pbo(ray_rb2pixel_bus(self)));
305
+ }
306
+
307
+ /*
308
+ * Document-class: Ray::PixelBus
309
+ *
310
+ * Pixel buses are a way to copy pixels from a target or an image onto an image
311
+ * without having to copy them to client memory, and possibly
312
+ * asynchronously. They may unfortunately not be available on some platforms.
313
+ *
314
+ * Notice that pixels are stored from bottom to top in the buffer. You may have
315
+ * to rely on this when computing offsets manually.
316
+ */
317
+ void Init_ray_pixel_bus() {
318
+ ray_cPixelBus = rb_define_class_under(ray_mRay, "PixelBus", rb_cObject);
319
+
320
+ rb_define_alloc_func(ray_cPixelBus, ray_pixel_bus_alloc);
321
+ rb_define_method(ray_cPixelBus, "initialize", ray_pixel_bus_init, -1);
322
+
323
+ rb_define_singleton_method(ray_cPixelBus, "available?",
324
+ ray_pixel_bus_available, 0);
325
+
326
+ /* @group Manipulating buffer size */
327
+ rb_define_method(ray_cPixelBus, "size", ray_pixel_bus_size, 0);
328
+ rb_define_method(ray_cPixelBus, "resize", ray_pixel_bus_resize, 1);
329
+ rb_define_method(ray_cPixelBus, "resize!", ray_pixel_bus_resize_fast, 1);
330
+ /* @endgroup */
331
+
332
+ /* @group Copying data */
333
+ rb_define_method(ray_cPixelBus, "pull", ray_pixel_bus_pull, -1);
334
+ rb_define_method(ray_cPixelBus, "push", ray_pixel_bus_push, -1);
335
+ /* @endgroup */
336
+
337
+ /* @group OpenGL access */
338
+ rb_define_method(ray_cPixelBus, "bind", ray_pixel_bus_bind, 0);
339
+ rb_define_method(ray_cPixelBus, "bind_pack", ray_pixel_bus_bind_pack, 0);
340
+ rb_define_method(ray_cPixelBus, "bind_unpack", ray_pixel_bus_bind_unpack, 0);
341
+ rb_define_method(ray_cPixelBus, "pbo", ray_pixel_bus_pbo, 0);
342
+
343
+ rb_define_singleton_method(ray_cPixelBus, "unbind", ray_pixel_bus_unbind, 0);
344
+ rb_define_singleton_method(ray_cPixelBus, "unbind_pack",
345
+ ray_pixel_bus_unbind_pack, 0);
346
+ rb_define_singleton_method(ray_cPixelBus, "unbind_unpack",
347
+ ray_pixel_bus_unbind_unpack, 0);
348
+ /* @endgroup */
349
+ }