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
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'