ray 0.1.1 → 0.2.0

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 (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
data/ext/text.c CHANGED
@@ -17,13 +17,19 @@ say_text *ray_rb2text(VALUE obj) {
17
17
  static
18
18
  VALUE ray_text_alloc(VALUE self) {
19
19
  say_text *text = say_text_create();
20
- return Data_Wrap_Struct(self, NULL, say_text_free, text);
20
+ VALUE rb = Data_Wrap_Struct(self, NULL, say_text_free, text);
21
+
22
+ say_drawable_set_shader_proc(text->drawable, ray_drawable_shader_proc);
23
+ say_drawable_set_other_data(text->drawable, (void*)rb);
24
+
25
+ return rb;
21
26
  }
22
27
 
23
28
  static
24
29
  VALUE ray_text_init_copy(VALUE self, VALUE orig) {
25
30
  say_text_copy(ray_rb2text(self), ray_rb2text(orig));
26
31
  rb_iv_set(self, "@font", rb_iv_get(orig, "@font"));
32
+ ray_drawable_copy_attr(self, orig);
27
33
  return self;
28
34
  }
29
35
 
@@ -131,6 +137,39 @@ VALUE ray_text_rect(VALUE self) {
131
137
  return ray_rect2rb(say_text_get_rect(ray_rb2text(self)));
132
138
  }
133
139
 
140
+ /*
141
+ * @return [Ray::Vector2, nil] Auto-centering ratio. Nil when disabled.
142
+ */
143
+ static
144
+ VALUE ray_text_auto_center(VALUE self) {
145
+ say_text *text = ray_rb2text(self);
146
+
147
+ if (say_text_auto_center(text))
148
+ return ray_vector2_to_rb(say_text_get_auto_center_ratio(text));
149
+ else
150
+ return Qnil;
151
+ }
152
+
153
+ /*
154
+ * @overload auto_center=(val)
155
+ * Sets the auto centering ratio. It's a vector2 containing values between 0
156
+ * and 1 (typically, at least) to determine the center of the text when it is
157
+ * resized. (0.5, 1), for example, would set the origin to (middle, bottom).
158
+ *
159
+ * @param [Ray::Vector2, nil] val New auto centering ratio. If nil, disables
160
+ * auto-centering.
161
+ */
162
+ static
163
+ VALUE ray_text_set_auto_center(VALUE self, VALUE center) {
164
+ say_text *text = ray_rb2text(self);
165
+
166
+ if (NIL_P(center))
167
+ say_text_disable_auto_center(text);
168
+ else
169
+ say_text_enable_auto_center(text, ray_convert_to_vector2(center));
170
+
171
+ return center;
172
+ }
134
173
 
135
174
  void Init_ray_text() {
136
175
  ray_cText = rb_define_class_under(ray_mRay, "Text", ray_cDrawable);
@@ -155,6 +194,9 @@ void Init_ray_text() {
155
194
 
156
195
  rb_define_method(ray_cText, "rect", ray_text_rect, 0);
157
196
 
197
+ rb_define_method(ray_cText, "auto_center", ray_text_auto_center, 0);
198
+ rb_define_method(ray_cText, "auto_center=", ray_text_set_auto_center, 1);
199
+
158
200
  rb_define_const(ray_cText, "Normal", INT2FIX(SAY_TEXT_NORMAL));
159
201
  rb_define_const(ray_cText, "Bold", INT2FIX(SAY_TEXT_BOLD));
160
202
  rb_define_const(ray_cText, "Italic", INT2FIX(SAY_TEXT_ITALIC));
data/ext/view.c CHANGED
@@ -63,11 +63,19 @@ VALUE ray_view_init_copy(VALUE self, VALUE orig) {
63
63
  return self;
64
64
  }
65
65
 
66
+ /*
67
+ * @see view=
68
+ */
66
69
  static
67
70
  VALUE ray_view_size(VALUE self) {
68
71
  return ray_vector2_to_rb(say_view_get_size(ray_rb2view(self)));
69
72
  }
70
73
 
74
+ /*
75
+ * @overload size=(val)
76
+ * Sets the size of the visible world
77
+ * @param [Ray::Vector2] val
78
+ */
71
79
  static
72
80
  VALUE ray_view_set_size(VALUE self, VALUE val) {
73
81
  rb_check_frozen(self);
@@ -75,11 +83,19 @@ VALUE ray_view_set_size(VALUE self, VALUE val) {
75
83
  return val;
76
84
  }
77
85
 
86
+ /*
87
+ * @see center=
88
+ */
78
89
  static
79
90
  VALUE ray_view_center(VALUE self) {
80
91
  return ray_vector2_to_rb(say_view_get_center(ray_rb2view(self)));
81
92
  }
82
93
 
94
+ /*
95
+ * @overload center=(center)
96
+ * Sets the center of the world
97
+ * @param [Ray::Vector2] center
98
+ */
83
99
  static
84
100
  VALUE ray_view_set_center(VALUE self, VALUE val) {
85
101
  rb_check_frozen(self);
@@ -87,11 +103,23 @@ VALUE ray_view_set_center(VALUE self, VALUE val) {
87
103
  return val;
88
104
  }
89
105
 
106
+ /*
107
+ * @see viewport=
108
+ */
90
109
  static
91
110
  VALUE ray_view_viewport(VALUE self) {
92
111
  return ray_rect2rb(say_view_get_viewport(ray_rb2view(self)));
93
112
  }
94
113
 
114
+ /*
115
+ * @overload viewport=(rect)
116
+ * Sets the region of the world where rendering will be done
117
+ *
118
+ * All the components of the rects are values between 0 and 1, allowing to use
119
+ * the same rect for two targets of different size
120
+ *
121
+ * @param [Ray::Rect] rect
122
+ */
95
123
  static
96
124
  VALUE ray_view_set_viewport(VALUE self, VALUE val) {
97
125
  rb_check_frozen(self);
@@ -99,18 +127,42 @@ VALUE ray_view_set_viewport(VALUE self, VALUE val) {
99
127
  return val;
100
128
  }
101
129
 
130
+ /*
131
+ * @see matrix=
132
+ */
102
133
  static
103
134
  VALUE ray_view_matrix(VALUE self) {
104
135
  return ray_matrix2rb(say_view_get_matrix(ray_rb2view(self)));
105
136
  }
106
137
 
138
+ /*
139
+ * @overload matrix=(mat)
140
+ * Sets the projection matrix
141
+ *
142
+ * Setting the projection matrix causes the center and the size of the view to
143
+ * be ignored. Passing nil would cancel this.
144
+ *
145
+ * @param [Ray::Matrix, nil] mat New matrix
146
+ */
107
147
  static
108
148
  VALUE ray_view_set_matrix(VALUE self, VALUE val) {
109
149
  rb_check_frozen(self);
110
- say_view_set_matrix(ray_rb2view(self), ray_rb2matrix(val));
150
+
151
+ if (NIL_P(val))
152
+ say_view_set_matrix(ray_rb2view(self), NULL);
153
+ else
154
+ say_view_set_matrix(ray_rb2view(self), ray_rb2matrix(val));
155
+
111
156
  return val;
112
157
  }
113
158
 
159
+ /*
160
+ * Document-class: Ray::View
161
+ *
162
+ * A view is a way to apply some transformations to all the drawables at once,
163
+ * by defining a projection. It also determines the region of the screen where
164
+ * the view will draw.
165
+ */
114
166
  void Init_ray_view() {
115
167
  ray_cView = rb_define_class_under(ray_mRay, "View", rb_cObject);
116
168
  rb_define_alloc_func(ray_cView, ray_view_alloc);
@@ -52,6 +52,10 @@ VALUE ray_window_open(int argc, VALUE *argv, VALUE self) {
52
52
 
53
53
  say_vector2 c_size = ray_convert_to_vector2(size);
54
54
 
55
+ #ifdef SAY_OSX
56
+ say_osx_flip_pool();
57
+ #endif
58
+
55
59
  if (!say_window_open(window, c_size.x, c_size.y,
56
60
  StringValuePtr(title), flags)) {
57
61
  rb_raise(rb_eRuntimeError, "%s", say_error_get_last());
@@ -10,6 +10,7 @@ module Ray
10
10
  #
11
11
  class AnimationList
12
12
  include Enumerable
13
+ include Ray::PP
13
14
 
14
15
  def initialize
15
16
  @animations = []
@@ -26,10 +27,15 @@ module Ray
26
27
  self
27
28
  end
28
29
 
29
- # Updates all the animations, and removes those that are finished.
30
+ # Updates all the animations
30
31
  def update
32
+ @animations.each(&:update)
33
+ self
34
+ end
35
+
36
+ # Removes animations that are no more in use
37
+ def remove_unused
31
38
  @animations.reject! do |anim|
32
- anim.update
33
39
  !anim.running? && !anim.paused?
34
40
  end
35
41
 
@@ -43,8 +49,17 @@ module Ray
43
49
  self
44
50
  end
45
51
 
52
+ # @return [Array<Ray::Animation>]
53
+ attr_reader :animations
54
+
55
+ alias to_a animations
56
+
46
57
  def inspect
47
58
  "#{self.class}#{@animations.inspect}"
48
59
  end
60
+
61
+ def pretty_print(q)
62
+ pretty_print_attributes q, ["animations"]
63
+ end
49
64
  end
50
65
  end
@@ -0,0 +1,11 @@
1
+ module Ray
2
+ class AudioSource
3
+ include Ray::PP
4
+
5
+ def pretty_print(q, other_attr = [])
6
+ attr = ["pos", "relative?", "min_distance", "attenuation",
7
+ "pitch", "status", "volume"]
8
+ pretty_print_attributes q, attr + other_attr
9
+ end
10
+ end
11
+ end
@@ -49,6 +49,20 @@ module Ray
49
49
  "RGBA(#{r}, #{g}, #{b}, #{a})"
50
50
  end
51
51
 
52
+ def pretty_print(q)
53
+ q.text("RGB#{'A' if a != 255}(")
54
+ q.pp r
55
+ q.text ", "
56
+ q.pp g
57
+ q.text ", "
58
+ q.pp b
59
+ if a != 255
60
+ q.text ", "
61
+ q.pp a
62
+ end
63
+ q.text ")"
64
+ end
65
+
52
66
  # @param [Ray::Color] color Another color.
53
67
  # @return [Ray::Color] Sum of two colors, adding component pairs.
54
68
  def +(color)
@@ -1,5 +1,9 @@
1
1
  module Ray
2
2
  class Drawable
3
+ include Ray::PP
4
+
5
+ # @group Transformations
6
+
3
7
  def y
4
8
  pos.y
5
9
  end
@@ -32,6 +36,25 @@ module Ray
32
36
  self.scale = [scale_x, val]
33
37
  end
34
38
 
39
+ # @endgroup
40
+
41
+ def pretty_print(q, other_attributes = [])
42
+ # Note: This doesn't use %w[...] arrays because YARD can't parse them
43
+ attributes = [
44
+ "origin", "pos", "z", "scale", "angle",
45
+ "matrix", "matrix_proc",
46
+ "shader", "shader_attributes",
47
+ "vertex_count", "index_count", "changed?", "textured?",
48
+ "blend_mode"
49
+ ]
50
+
51
+ pretty_print_attributes q, attributes + other_attributes
52
+ end
53
+
54
+ # @return [Hash, nil] Attributes passed to the shader when the object is
55
+ # drawn.
56
+ attr_accessor :shader_attributes
57
+
35
58
  alias zoom scale
36
59
  alias zoom= scale=
37
60
 
@@ -1,14 +1,6 @@
1
1
  module Ray
2
2
  module DSL
3
3
  # Used internally to store event when raise_event is called.
4
- class Event
5
- def initialize(type, args)
6
- @type = type
7
- @args = args
8
- end
9
-
10
- attr_reader :type
11
- attr_reader :args
12
- end
4
+ Event = Struct.new(:type, :args)
13
5
  end
14
6
  end
@@ -7,7 +7,6 @@ module Ray
7
7
  class EventRunner
8
8
  def initialize
9
9
  @handlers = []
10
- @event_list = []
11
10
  @next_events = []
12
11
 
13
12
  @event_groups = Hash.new { |h, k| h[k] = true }
@@ -16,13 +15,13 @@ module Ray
16
15
 
17
16
  # Sends all the known events to our listeners.
18
17
  def run
19
- @event_list = @next_events
18
+ event_list = @next_events
20
19
  @next_events = []
21
20
 
22
21
  handlers = @handlers.select { |o| group_enabled?(o.group) }
23
22
 
24
- @event_list.each do |ev|
25
- handlers.select { |o| o.call(ev) if o.match?(ev) }
23
+ event_list.each do |ev|
24
+ handlers.each { |o| o.call(ev) if o.match?(ev) }
26
25
  end
27
26
  end
28
27
 
@@ -1,4 +1,9 @@
1
1
  module Ray
2
+ class NoKeyError < StandardError
3
+ def initialize(key)
4
+ super "key #{key} doesn't exist"
5
+ end
6
+ end
2
7
  # This is the module including all of your matchers as private methods,
3
8
  # allowing you to use them when you call on.
4
9
  module Matchers
@@ -177,8 +182,17 @@ module Ray
177
182
  end
178
183
  end
179
184
 
185
+ # A Key object can be used as a matcher to check if a key has been pressed or
186
+ # released:
187
+ #
188
+ # on :key_press, Key.new(:+) do
189
+ # # work
190
+ # end
191
+ #
192
+ # @see KeyMod
180
193
  class Key
181
194
  def initialize(name)
195
+ raise NoKeyError, name unless Keys[name]
182
196
  @symbol = name.to_sym
183
197
  end
184
198
 
@@ -199,13 +213,18 @@ module Ray
199
213
  end
200
214
  end
201
215
 
216
+ # A KeyMod object can be used as a matcher to check if some modifiers are held
217
+ # when a key is pressed.
218
+ #
219
+ # @see KeyMod
202
220
  class KeyMod
203
221
  def initialize(name)
222
+ raise NoKeyError, name unless Mod[name]
204
223
  @symbol = name.to_sym
205
224
  end
206
225
 
207
226
  def to_a
208
- MOD[@symbol]
227
+ Mod[@symbol]
209
228
  end
210
229
 
211
230
  def to_sym
@@ -0,0 +1,116 @@
1
+ module Ray
2
+ # Effects are used to generate fragment shaders automatically. They represent
3
+ # one of the transformations applied to the color.
4
+ #
5
+ # Effects must generate a structure to store arguments passed to the effect
6
+ # (structure generation being done through a DSL), and a function to apply the
7
+ # effect (a call to the #code method returns )
8
+ class Effect
9
+ # @overload effect_name(name)
10
+ # Sets the name of the effect
11
+ # @param [String] value
12
+ #
13
+ # @overload effect_name
14
+ # @return [String] Name of the effect
15
+ def self.effect_name(value = nil)
16
+ if value
17
+ @name = value
18
+
19
+ klass = self
20
+ Ray::Helper.send :define_method, @name do |*args|
21
+ klass.new(*args)
22
+ end
23
+ else
24
+ @name
25
+ end
26
+ end
27
+
28
+ # Adds an attribute to the shader. It is an element of the struct
29
+ #
30
+ # @param [String] name Name of the attribute
31
+ # @param [String] type Type of the attribute. Arrays are written using this
32
+ # notation: type[count].
33
+ def self.attribute(name, type)
34
+ attributes[name] = type
35
+ end
36
+
37
+ # @return [Hash] All the attributes of the struct, matched with their type.
38
+ def self.attributes
39
+ @attributes ||= {}
40
+ end
41
+
42
+ # @return [String] Name of the effect
43
+ def name
44
+ self.class.effect_name
45
+ end
46
+
47
+ # @return [String] GLSL code of the struct.
48
+ def struct
49
+ str = "struct ray_#{self.class.effect_name} {\n"
50
+ str << " bool enabled;\n"
51
+
52
+ self.class.attributes.each do |name, type|
53
+ if type =~ /\A(\w+)\[(\d+)\]\z/
54
+ str << " #$1 #{name}[#$2];\n"
55
+ else
56
+ str << " #{type} #{name};\n"
57
+ end
58
+ end
59
+
60
+ str << "};\n"
61
+ end
62
+
63
+ # @abstract
64
+ #
65
+ # @return [String] Code that must be written *before* the definiton of the
66
+ # structure. Just returns an empty string by default.
67
+ def header
68
+ ""
69
+ end
70
+
71
+ # @abstract
72
+ #
73
+ # @return [String]
74
+ # Code of the function. This must contain the header of the function.
75
+ # The name of the function is the name of the effect prepended by
76
+ # "do_". It is passed a ray_#{effect_name} structure and the color, and is
77
+ # expected to return the changed color.
78
+ #
79
+ # @example
80
+ # def code
81
+ # return %{
82
+ # vec4 do_some_effect(ray_some_effect arg, vec4 color) {
83
+ # /* Do magic here. */
84
+ # }
85
+ # }
86
+ # end
87
+ def code
88
+ raise NotImplementedError
89
+ end
90
+
91
+ # @abstract
92
+ #
93
+ # @return [Hash] Default value for each attribute.
94
+ def defaults
95
+ {}
96
+ end
97
+
98
+ # Apply the defaults to a shader.
99
+ # @param [Ray::Shader] shader
100
+ def apply_defaults(shader)
101
+ effect_name = self.class.effect_name
102
+
103
+ shader["#{effect_name}.enabled"] = true
104
+
105
+ defaults.each do |name, value|
106
+ shader["#{effect_name}.#{name}"] = value
107
+ end
108
+ end
109
+ end
110
+ end
111
+
112
+ require 'ray/effect/generator'
113
+
114
+ require 'ray/effect/grayscale'
115
+ require 'ray/effect/color_inversion'
116
+ require 'ray/effect/black_and_white'