texplay 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data/CHANGELOG +63 -0
  2. data/README +21 -0
  3. data/README1st +9 -0
  4. data/Rakefile +85 -0
  5. data/examples/basic.rb +48 -0
  6. data/examples/basic2.rb +37 -0
  7. data/examples/benchmark.rb +299 -0
  8. data/examples/common.rb +8 -0
  9. data/examples/example_alpha_blend.rb +31 -0
  10. data/examples/example_bezier.rb +51 -0
  11. data/examples/example_color_control.rb +68 -0
  12. data/examples/example_color_transform.rb +29 -0
  13. data/examples/example_dup.rb +52 -0
  14. data/examples/example_each.rb +42 -0
  15. data/examples/example_effect.rb +35 -0
  16. data/examples/example_fill.rb +49 -0
  17. data/examples/example_fill_old.rb +49 -0
  18. data/examples/example_fluent.rb +31 -0
  19. data/examples/example_gen_eval.rb +34 -0
  20. data/examples/example_hash_arguments.rb +47 -0
  21. data/examples/example_melt.rb +27 -0
  22. data/examples/example_polyline.rb +43 -0
  23. data/examples/example_simple.rb +35 -0
  24. data/examples/example_splice.rb +37 -0
  25. data/examples/example_sync.rb +60 -0
  26. data/examples/example_turtle.rb +40 -0
  27. data/examples/media/empty2.png +0 -0
  28. data/examples/media/gosu.png +0 -0
  29. data/examples/media/maria.png +0 -0
  30. data/examples/media/rose.bmp +0 -0
  31. data/examples/media/sand1.png +0 -0
  32. data/examples/media/sunset.png +0 -0
  33. data/examples/media/texplay.png +0 -0
  34. data/examples/specs.rb +240 -0
  35. data/examples/test.rb +70 -0
  36. data/examples/test2.rb +72 -0
  37. data/lib/texplay-contrib.rb +77 -0
  38. data/lib/texplay.rb +134 -0
  39. data/src/Makefile +181 -0
  40. data/src/TAGS +286 -0
  41. data/src/actions.c +1306 -0
  42. data/src/actions.h +52 -0
  43. data/src/actions.o +0 -0
  44. data/src/bindings.c +1081 -0
  45. data/src/bindings.h +45 -0
  46. data/src/bindings.o +0 -0
  47. data/src/cache.c +132 -0
  48. data/src/cache.h +24 -0
  49. data/src/cache.o +0 -0
  50. data/src/compat.h +23 -0
  51. data/src/ctexplay.so +0 -0
  52. data/src/extconf.rb +18 -0
  53. data/src/gen_eval.c +209 -0
  54. data/src/gen_eval.h +20 -0
  55. data/src/gen_eval.o +0 -0
  56. data/src/mkmf.log +22 -0
  57. data/src/object2module.c +171 -0
  58. data/src/object2module.h +11 -0
  59. data/src/object2module.o +0 -0
  60. data/src/texplay.c +136 -0
  61. data/src/texplay.h +107 -0
  62. data/src/texplay.o +0 -0
  63. data/src/utils.c +959 -0
  64. data/src/utils.h +143 -0
  65. data/src/utils.o +0 -0
  66. metadata +126 -0
@@ -0,0 +1,52 @@
1
+ #ifndef GUARD_ACTIONS_H
2
+ #define GUARD_ACTIONS_H
3
+
4
+
5
+ /* lines */
6
+ void line_do_action(int, int, int, int, texture_info *, VALUE, sync, bool primary, action_struct * payload);
7
+
8
+ /* circles */
9
+ void circle_do_action(int, int, int, texture_info *, VALUE, sync, bool primary, action_struct * payload);
10
+
11
+ /* pixels */
12
+ void pixel_do_action(int, int, texture_info *, VALUE, sync, bool primary, action_struct * payload);
13
+
14
+ /* rectangles */
15
+ void rect_do_action(int x1, int y1, int x2, int y2, texture_info * tex, VALUE hash_arg,
16
+ sync sync_mode, bool primary, action_struct * payload);
17
+
18
+ /* flood fill */
19
+ void flood_fill_do_action(int x, int y, texture_info * tex, VALUE hash_arg, sync sync_mode, bool primary,
20
+ action_struct * payload);
21
+
22
+ /* glow fill */
23
+ void glow_fill_do_action(int x, int y, texture_info * tex, VALUE hash_arg, sync sync_mode, bool primary,
24
+ action_struct * payload);
25
+
26
+ /* scan fill */
27
+ void scan_fill_do_action(int x, int y, texture_info * tex, VALUE hash_arg,
28
+ sync sync_mode, bool primary, action_struct * payload);
29
+
30
+ /* polyline */
31
+ void polyline_do_action(VALUE points, texture_info * tex, VALUE hash_arg, sync sync_mode, bool primary,
32
+ action_struct * payload);
33
+
34
+ /* bezier */
35
+ void bezier_do_action(VALUE points, texture_info * tex, VALUE hash_arg, sync sync_mode, bool primary,
36
+ action_struct * payload);
37
+
38
+ /* ngon */
39
+ void ngon_do_action(int x, int y, int r, int num_sides, texture_info * tex, VALUE hash_arg,
40
+ sync sync_mode, bool primary, action_struct * payload);
41
+
42
+
43
+ /* splice */
44
+ void splice_do_action(int x0,int y0, int cx1, int cy1, int cx2, int cy2, texture_info * splice_tex,
45
+ texture_info * tex, VALUE hash_arg, sync sync_mode,
46
+ bool primary, action_struct * payload);
47
+
48
+ /* each iterator */
49
+ void each_pixel_do_action(int x1, int y1, int x2, int y2, VALUE proc, texture_info * tex, VALUE hash_arg,
50
+ sync sync_mode, bool primary, action_struct * payload);
51
+
52
+ #endif
Binary file
@@ -0,0 +1,1081 @@
1
+ #include <ruby.h>
2
+ #include <stdio.h>
3
+ #include <string.h>
4
+ #include <ctype.h>
5
+ #include <math.h>
6
+ #include <stdlib.h>
7
+ #include <assert.h>
8
+ #include <stdarg.h>
9
+
10
+ #ifdef __APPLE__
11
+ # include <glut.h>
12
+ #else
13
+ # include <GL/glut.h>
14
+ #endif
15
+
16
+ #include "texplay.h"
17
+ #include "utils.h"
18
+ #include "bindings.h"
19
+ #include "actions.h"
20
+ #include "cache.h"
21
+ #include "compat.h"
22
+
23
+ /* associated with gen_eval */
24
+ #include "object2module.h"
25
+ #include "gen_eval.h"
26
+
27
+ /* syncing mode */
28
+ /* lazy_sync = sync at end of paint block */
29
+ /* eager_sync = sync immediately (after action) */
30
+ /* no_sync = do not sync at all */
31
+ sync sync_mode = eager_sync;
32
+
33
+ static void
34
+ process_x_y_pairs(VALUE image, int num_pairs, VALUE * argv, ...)
35
+ {
36
+ va_list ap;
37
+ int i;
38
+ int draw_offset_x;
39
+ int draw_offset_y;
40
+ VALUE offset_val;
41
+
42
+ offset_val = get_image_local(image, DRAW_OFFSET);
43
+
44
+ draw_offset_x = NUM2INT(get_from_array(offset_val, 0));
45
+ draw_offset_y = NUM2INT(get_from_array(offset_val, 1));
46
+
47
+ va_start(ap, argv);
48
+ if(is_a_point(argv[0])) {
49
+ for(i = 0; i < num_pairs; i++) {
50
+ int *x_ptr, *y_ptr;
51
+
52
+ x_ptr = va_arg(ap, int*);
53
+ y_ptr = va_arg(ap, int*);
54
+
55
+ *x_ptr = NUM2INT(rb_funcall(argv[i], rb_intern("x"), 0)) + draw_offset_x;
56
+ *y_ptr = NUM2INT(rb_funcall(argv[i], rb_intern("y"), 0)) + draw_offset_y;
57
+ }
58
+ }
59
+ else {
60
+ for(i = 0; i < (num_pairs * 2); i+=2) {
61
+ int *x_ptr, *y_ptr;
62
+
63
+ x_ptr = va_arg(ap, int*);
64
+ y_ptr = va_arg(ap, int*);
65
+
66
+ *x_ptr = NUM2INT(argv[i]) + draw_offset_x;
67
+ *y_ptr = NUM2INT(argv[i + 1]) + draw_offset_y;
68
+ }
69
+ }
70
+ va_end(ap);
71
+ }
72
+
73
+
74
+ /* singleton methods */
75
+
76
+ /* responsible for creating macros */
77
+ VALUE
78
+ M_create_macro(VALUE self, VALUE method_name)
79
+ {
80
+ VALUE proc;
81
+
82
+ rb_need_block();
83
+
84
+ /* convert the block to a proc */
85
+ proc = rb_block_proc();
86
+
87
+ /* define the method in the TexPlay class so that it is accessible to 'instances' */
88
+ rb_funcall(self, rb_intern("define_method"), 2, method_name, proc);
89
+
90
+ return Qnil;
91
+ }
92
+
93
+
94
+ /* responsible for removing macros */
95
+ VALUE
96
+ M_remove_macro(VALUE self, VALUE method_name)
97
+ {
98
+
99
+ /* remove the method in the TexPlay class */
100
+ rb_funcall(self, rb_intern("remove_method"), 1, method_name);
101
+
102
+ return Qnil;
103
+ }
104
+
105
+ /* responsible for refreshing all entries in cache */
106
+ VALUE
107
+ M_refresh_cache_all(VALUE self)
108
+ {
109
+ cache_refresh_all();
110
+
111
+ return Qnil;
112
+ }
113
+
114
+ /* creates a blank image */
115
+ VALUE
116
+ M_create_blank(VALUE self, VALUE window, VALUE width, VALUE height)
117
+ {
118
+ VALUE fresh_image;
119
+
120
+ fresh_image = create_image(window, NUM2INT(width), NUM2INT(height));
121
+
122
+ return fresh_image;
123
+ }
124
+ /** end singleton methods **/
125
+
126
+ /* some helper methods */
127
+ static void
128
+ rb_lazy_bounds_to_image_bounds(VALUE image, image_bounds * bounds)
129
+ {
130
+ VALUE lazy_bounds;
131
+
132
+ lazy_bounds = get_image_local(image, LAZY_BOUNDS);
133
+
134
+ Check_Type(lazy_bounds, T_ARRAY);
135
+
136
+ bounds->xmin = FIX2INT(get_from_array(lazy_bounds, 0));
137
+ bounds->ymin = FIX2INT(get_from_array(lazy_bounds, 1));
138
+ bounds->xmax = FIX2INT(get_from_array(lazy_bounds, 2));
139
+ bounds->ymax = FIX2INT(get_from_array(lazy_bounds, 3));
140
+ }
141
+
142
+ static VALUE
143
+ parse_sync_mode(VALUE user_sync_mode)
144
+ {
145
+ sync mode;
146
+
147
+ Check_Type(user_sync_mode, T_SYMBOL);
148
+
149
+ if(user_sync_mode == string2sym("lazy_sync"))
150
+ mode = lazy_sync;
151
+ else if(user_sync_mode == string2sym("eager_sync"))
152
+ mode = eager_sync;
153
+ else if(user_sync_mode == string2sym("no_sync"))
154
+ mode = no_sync;
155
+ else
156
+ rb_raise(rb_eArgError, "unrecognized sync mode: %s\n. Allowable modes are "
157
+ ":lazy_sync, :eager_sync, :no_sync.",
158
+ sym2string(user_sync_mode));
159
+
160
+ return mode;
161
+ }
162
+ /* end helpers */
163
+
164
+ /* entry point for TexPlay paint actions */
165
+ VALUE
166
+ m_paint(int argc, VALUE * argv, VALUE self)
167
+ {
168
+ texture_info tex;
169
+ VALUE options;
170
+ image_bounds bounds;
171
+ int arity;
172
+
173
+ ADJUST_SELF(self);
174
+
175
+ rb_scan_args(argc, argv, "01", &options);
176
+
177
+ /* get texture info from image */
178
+ get_texture_info(self, &tex);
179
+
180
+ /* set default sync_mode to lazy */
181
+ sync_mode = lazy_sync;
182
+
183
+ /* parse sync_mode, overriding lazy sync mode? */
184
+ if(has_optional_hash_arg(options, "sync_mode")) {
185
+ VALUE user_sync_mode = get_from_hash(options, "sync_mode");
186
+ sync_mode = parse_sync_mode(user_sync_mode);
187
+ }
188
+
189
+ /* if no block then just sync */
190
+ if(!rb_block_given_p()) {
191
+
192
+ rb_lazy_bounds_to_image_bounds(self, &bounds);
193
+
194
+ create_subtexture_and_sync_to_gl(&bounds, &tex);
195
+
196
+ /* reset the LAZY_BOUNDS now we've sync'd */
197
+ set_image_local(self, LAZY_BOUNDS, Qnil);
198
+
199
+ sync_mode = eager_sync;
200
+
201
+ return self;
202
+ }
203
+
204
+ /* find arity of block */
205
+ arity = FIX2INT(rb_funcall(rb_block_proc(), rb_intern("arity"), 0));
206
+
207
+ /* yield self if the arity is 1, else gen_eval the block */
208
+ switch(arity) {
209
+ case -1:
210
+ case 0:
211
+ rb_gen_eval(0, 0, self);
212
+ break;
213
+ case 1:
214
+ rb_yield(self);
215
+ break;
216
+ default:
217
+ rb_raise(rb_eArgError, "block arity must be either 1 or -1 or 0, received arity of: %d", arity);
218
+ }
219
+
220
+ /* if lazy sync is selected then sync now..as the paint block has finished executing the draw actions*/
221
+ if(sync_mode == lazy_sync) {
222
+
223
+ rb_lazy_bounds_to_image_bounds(self, &bounds);
224
+
225
+ create_subtexture_and_sync_to_gl(&bounds, &tex);
226
+
227
+ /* reset the LAZY_BOUNDS now we've sync'd */
228
+ set_image_local(self, LAZY_BOUNDS, Qnil);
229
+
230
+ }
231
+
232
+ /* now we've finished the paint block we reset the default sync_mode back to eager */
233
+ sync_mode = eager_sync;
234
+
235
+ return self;
236
+ }
237
+
238
+ VALUE
239
+ m_force_sync(VALUE self, VALUE ary)
240
+ {
241
+ image_bounds bounds;
242
+ texture_info tex;
243
+
244
+ ADJUST_SELF(self);
245
+
246
+ Check_Type(ary, T_ARRAY);
247
+
248
+ get_texture_info(self, &tex);
249
+
250
+ bounds.xmin = NUM2INT(get_from_array(ary, 0));
251
+ bounds.ymin = NUM2INT(get_from_array(ary, 1));
252
+ bounds.xmax = NUM2INT(get_from_array(ary, 2));
253
+ bounds.ymax = NUM2INT(get_from_array(ary, 3));
254
+
255
+ create_subtexture_and_sync_to_gl(&bounds, &tex);
256
+
257
+ return Qnil;
258
+ }
259
+
260
+ VALUE
261
+ m_dup_image(VALUE self)
262
+ {
263
+ texture_info tex, dup_tex;
264
+ VALUE dupped_image;
265
+ VALUE window;
266
+
267
+ ADJUST_SELF(self);
268
+
269
+ get_texture_info(self, &tex);
270
+
271
+ window = rb_funcall(self, rb_intern("__window__"), 0);
272
+
273
+ /* create a new blank image with the height/width of the current image */
274
+ dupped_image = create_image(window, tex.width, tex.height);
275
+
276
+ /* get the new image's data */
277
+ get_texture_info(dupped_image, &dup_tex);
278
+
279
+ /* splice into the new image content from the current image, and sync it to gl */
280
+ splice_do_action(0, 0, 0, 0, XMAX_OOB, YMAX_OOB, &tex, &dup_tex, Qnil, eager_sync, true, NULL);
281
+
282
+ /* copy across the ivars too! */
283
+ rb_copy_generic_ivar(dupped_image, self);
284
+
285
+ /* we now have a full dup of the current image, return it */
286
+ return dupped_image;
287
+ }
288
+
289
+ VALUE
290
+ m_clone_image(VALUE self)
291
+ {
292
+ VALUE cloned_image;
293
+
294
+ ADJUST_SELF(self);
295
+
296
+ cloned_image = m_dup_image(self);
297
+
298
+ /* the main diff b/w clone and dup is that clone also dups the singleton */
299
+ KLASS_OF(cloned_image) = rb_singleton_class_clone(self);
300
+
301
+ return cloned_image;
302
+ }
303
+
304
+ VALUE
305
+ m_user_set_options(VALUE self, VALUE options)
306
+ {
307
+ ADJUST_SELF(self);
308
+
309
+ if(!is_a_hash(options))
310
+ rb_raise(rb_eArgError, "only a single hash argument is accepted");
311
+
312
+ set_image_local(self, USER_DEFAULTS, options);
313
+
314
+ return Qnil;
315
+ }
316
+
317
+ VALUE
318
+ m_user_delete_options(VALUE self)
319
+ {
320
+
321
+ ADJUST_SELF(self);
322
+
323
+ set_image_local(self, USER_DEFAULTS, Qnil);
324
+
325
+ return Qnil;
326
+ }
327
+
328
+ VALUE
329
+ m_get_options(VALUE self)
330
+ {
331
+ ADJUST_SELF(self);
332
+
333
+ return get_image_local(self, USER_DEFAULTS);
334
+ }
335
+
336
+ /* return the pixel colour for the given x, y */
337
+ VALUE
338
+ m_getpixel(int argc, VALUE * argv, VALUE self)
339
+ {
340
+ int x1, y1;
341
+ texture_info tex;
342
+ rgba pix;
343
+
344
+ /* change self to hidden self if using gen_eval */
345
+ ADJUST_SELF(self);
346
+
347
+ process_x_y_pairs(self, 1, argv, &x1, &y1);
348
+
349
+ /* get texture info */
350
+ get_texture_info(self, &tex);
351
+
352
+ /* locate the desired pixel; */
353
+ pix = get_pixel_color(&tex, x1, y1);
354
+
355
+ if(not_a_color(pix))
356
+ return Qnil;
357
+ else
358
+ return convert_rgba_to_rb_color(&pix);
359
+ }
360
+
361
+ /* circle action */
362
+ VALUE
363
+ m_circle(int argc, VALUE * argv, VALUE self)
364
+ {
365
+ int x1, y1, r;
366
+ int last = argc - 1;
367
+ VALUE options;
368
+ texture_info tex;
369
+
370
+ ADJUST_SELF(self);
371
+
372
+ if(argc < 1) rb_raise(rb_eArgError, "circle action needs at least 1 parameter");
373
+
374
+ process_x_y_pairs(self, 1, argv, &x1, &y1);
375
+
376
+ if(is_a_point(argv[0]))
377
+ r = NUM2INT(argv[1]);
378
+ else
379
+ r = NUM2INT(argv[2]);
380
+
381
+ options = argv[last];
382
+
383
+ get_texture_info(self, &tex);
384
+
385
+ circle_do_action(x1, y1, r, &tex, options, sync_mode, true, NULL);
386
+
387
+ return self;
388
+ }
389
+
390
+ /* ngon */
391
+ VALUE
392
+ m_ngon(int argc, VALUE * argv, VALUE self)
393
+ {
394
+ int x1, y1, r, n;
395
+ int last = argc - 1;
396
+ VALUE options;
397
+ texture_info tex;
398
+
399
+ ADJUST_SELF(self);
400
+
401
+ if(argc < 4) rb_raise(rb_eArgError, "ngon requires at least 4 parameters (x, y, radius, num_sides)");
402
+
403
+ process_x_y_pairs(self, 1, argv, &x1, &y1);
404
+
405
+ options = argv[last];
406
+
407
+ get_texture_info(self, &tex);
408
+
409
+ r = NUM2INT(argv[2]);
410
+ n = NUM2INT(argv[3]);
411
+
412
+ ngon_do_action(x1, y1, r, n, &tex, options, sync_mode, true, NULL);
413
+
414
+ return self;
415
+ }
416
+
417
+
418
+ /* flood fill action */
419
+ VALUE
420
+ m_flood_fill(int argc, VALUE * argv, VALUE self)
421
+ {
422
+ int x1, y1;
423
+ int last = argc - 1;
424
+ VALUE options;
425
+ texture_info tex;
426
+ bool iter = false, glow = false;
427
+
428
+ ADJUST_SELF(self);
429
+
430
+ if (argc < 1) rb_raise(rb_eArgError, "flood fill action needs at least 1 parameter");
431
+
432
+ process_x_y_pairs(self, 1, argv, &x1, &y1);
433
+
434
+ options = argv[last];
435
+
436
+ get_texture_info(self, &tex);
437
+
438
+ if(is_a_hash(options)) {
439
+ if(RTEST(get_from_hash(options, "iter")))
440
+ iter = true;
441
+ if(RTEST(get_from_hash(options, "glow")))
442
+ glow = true;
443
+ }
444
+
445
+ if(iter) {
446
+ flood_fill_do_action(x1, y1, &tex, options, sync_mode, true, NULL);
447
+ }
448
+ else if(glow) {
449
+ glow_fill_do_action(x1, y1, &tex, options, sync_mode, true, NULL);
450
+
451
+ }
452
+ /* this is the default fill */
453
+ else {
454
+ scan_fill_do_action(x1, y1, &tex, options, sync_mode, true, NULL);
455
+ }
456
+
457
+ return self;
458
+ }
459
+
460
+
461
+ /* line action */
462
+ VALUE
463
+ m_line(int argc, VALUE * argv, VALUE self)
464
+ {
465
+ int x1, y1, x2, y2;
466
+ int last = argc - 1;
467
+ VALUE options;
468
+ texture_info tex;
469
+
470
+ ADJUST_SELF(self);
471
+
472
+ if(argc < 2) rb_raise(rb_eArgError, "line action needs at least 2 parameters");
473
+
474
+ process_x_y_pairs(self, 2, argv, &x1, &y1, &x2, &y2);
475
+
476
+ options = argv[last];
477
+
478
+ get_texture_info(self, &tex);
479
+
480
+ line_do_action(x1, y1, x2, y2, &tex, options, sync_mode, true, NULL);
481
+
482
+ return self;
483
+ }
484
+
485
+ /* box action */
486
+ VALUE
487
+ m_rect(int argc, VALUE * argv, VALUE self)
488
+ {
489
+
490
+ int x1, y1, x2, y2;
491
+ int last = argc - 1;
492
+ VALUE options;
493
+ texture_info tex;
494
+
495
+ ADJUST_SELF(self);
496
+
497
+ if(argc < 2) rb_raise(rb_eArgError, "rect action needs at least 2 parameters");
498
+
499
+ process_x_y_pairs(self, 2, argv, &x1, &y1, &x2, &y2);
500
+
501
+ options = argv[last];
502
+
503
+ get_texture_info(self, &tex);
504
+
505
+ rect_do_action(x1, y1, x2, y2, &tex, options, sync_mode, true, NULL);
506
+
507
+ return self;
508
+ }
509
+
510
+
511
+ /* pixel action */
512
+ VALUE
513
+ m_pixel(int argc, VALUE * argv, VALUE self)
514
+ {
515
+ int x1, y1;
516
+ int last = argc - 1;
517
+ VALUE options;
518
+ texture_info tex;
519
+
520
+ ADJUST_SELF(self);
521
+
522
+ if(argc < 1) rb_raise(rb_eArgError, "pixel action needs 1 parameter");
523
+
524
+ process_x_y_pairs(self, 1, argv, &x1, &y1);
525
+
526
+ options = argv[last];
527
+
528
+ get_texture_info(self, &tex);
529
+
530
+ pixel_do_action(x1, y1, &tex, options, sync_mode, true, NULL);
531
+
532
+ return self;
533
+ }
534
+
535
+ /* bezier curve */
536
+ VALUE
537
+ m_bezier(int argc, VALUE * argv, VALUE self)
538
+ {
539
+ VALUE points = Qnil;
540
+ VALUE options = Qnil;
541
+ int last = argc - 1;
542
+ texture_info tex;
543
+
544
+ ADJUST_SELF(self);
545
+
546
+ if(argc < 1) rb_raise(rb_eArgError, "bezier action needs at least 1 parameter");
547
+
548
+ /* get array of points */
549
+ points = argv[0];
550
+ Check_Type(points, T_ARRAY);
551
+
552
+ options = argv[last];
553
+
554
+ get_texture_info(self, &tex);
555
+
556
+ bezier_do_action(points, &tex, options, sync_mode, true, NULL);
557
+
558
+ return self;
559
+ }
560
+
561
+ /* bezier curve */
562
+ VALUE
563
+ m_polyline(int argc, VALUE * argv, VALUE self)
564
+ {
565
+ VALUE points = Qnil;
566
+ VALUE options = Qnil;
567
+ int last = argc - 1;
568
+ texture_info tex;
569
+
570
+ ADJUST_SELF(self);
571
+
572
+ if(argc < 1) rb_raise(rb_eArgError, "polyline action needs at least 1 parameter");
573
+
574
+ /* get array of points */
575
+ points = argv[0];
576
+ Check_Type(points, T_ARRAY);
577
+
578
+ options = argv[last];
579
+
580
+ get_texture_info(self, &tex);
581
+
582
+ polyline_do_action(points, &tex, options, sync_mode, true, NULL);
583
+
584
+ return self;
585
+ }
586
+
587
+
588
+
589
+ /* splice action */
590
+ VALUE
591
+ m_splice(int argc, VALUE * argv, VALUE self)
592
+ {
593
+ int x0, y0;
594
+ int cx1 = 0, cy1 = 0, cx2 = XMAX_OOB, cy2 = YMAX_OOB;
595
+ texture_info splice_tex;
596
+ int last = argc - 1;
597
+ texture_info tex;
598
+ VALUE options;
599
+
600
+ ADJUST_SELF(self);
601
+
602
+ if(argc < 3) rb_raise(rb_eArgError, "splice action needs at least 3 parameters");
603
+
604
+ if(!is_gosu_image(argv[0]))
605
+ rb_raise(rb_eArgError, "first parameter must be a valid Gosu::Image");
606
+
607
+ /* get the splice image */
608
+ get_texture_info(argv[0], &splice_tex);
609
+
610
+ /* add 1 to argv to skip the Image parameter */
611
+ process_x_y_pairs(self, 1, argv + 1, &x0, &y0);
612
+
613
+ /* get the hash args */
614
+ options = argv[last];
615
+
616
+ get_texture_info(self, &tex);
617
+
618
+ /* get the crop boundaries */
619
+ if(is_a_hash(options))
620
+ if(RTEST(get_from_hash(options, "crop"))) {
621
+ VALUE c = get_from_hash(options, "crop");
622
+ Check_Type(c, T_ARRAY);
623
+ cx1 = NUM2INT(get_from_array(c, 0));
624
+ cy1 = NUM2INT(get_from_array(c, 1));
625
+ cx2 = NUM2INT(get_from_array(c, 2));
626
+ cy2 = NUM2INT(get_from_array(c, 3));
627
+ }
628
+
629
+ splice_do_action(x0, y0, cx1, cy1, cx2, cy2, &splice_tex,
630
+ &tex, options, sync_mode, true, NULL);
631
+
632
+ return self;
633
+ }
634
+
635
+
636
+ /* clear action - really just an alias for box */
637
+ VALUE
638
+ m_clear(int argc, VALUE * argv, VALUE self)
639
+ {
640
+ VALUE parms[4];
641
+
642
+ parms[0] = INT2NUM(0);
643
+ parms[1] = INT2NUM(0);
644
+ parms[2] = INT2NUM(XMAX_OOB);
645
+ parms[3] = INT2NUM(YMAX_OOB);
646
+
647
+ // m_box(ARY_SIZE(parms), parms, self);
648
+
649
+ return self;
650
+ }
651
+
652
+ /* offset function */
653
+ VALUE
654
+ m_offset(int argc, VALUE * argv, VALUE self)
655
+ {
656
+ char * try_offset;
657
+
658
+ ADJUST_SELF(self);
659
+
660
+ if(argc == 0)
661
+ return get_image_local(self, DRAW_OFFSET);
662
+
663
+ switch(TYPE(argv[0])) {
664
+
665
+ case T_ARRAY:
666
+
667
+ set_image_local(self, DRAW_OFFSET, argv[0]);
668
+ break;
669
+ case T_SYMBOL:
670
+ try_offset = sym2string(argv[0]);
671
+
672
+ if(!strcmp("default", try_offset)) {
673
+ set_image_local(self, DRAW_OFFSET, Qnil);
674
+ }
675
+ else {
676
+ rb_raise(rb_eArgError, "no such offset defined: %s\n", try_offset);
677
+ }
678
+
679
+ break;
680
+ default:
681
+ rb_raise(rb_eArgError, "invalid offset. please use an array or :default.");
682
+ }
683
+ return Qnil;
684
+ }
685
+
686
+ /* color change */
687
+ VALUE
688
+ m_color(int argc, VALUE * argv, VALUE self)
689
+ {
690
+ VALUE first;
691
+ rgba new_color;
692
+
693
+ ADJUST_SELF(self);
694
+
695
+ /* if no params then return action current color */
696
+ if(argc == 0)
697
+ return get_image_local(self, IMAGE_COLOR);
698
+
699
+ /* otherwise set the action color */
700
+ /* NB: we cannot just set image_local_color to 'first' because first may not be an array,
701
+ it could also be a symbol */
702
+
703
+ first = argv[0];
704
+
705
+ new_color = convert_rb_color_to_rgba(first);
706
+
707
+ /* im quite sure i DO want to set the color even if it is not_a_color.
708
+ why ? consistency only
709
+ (NB: not_a_color_v is skipped by the set_pixel_color routine */
710
+
711
+ /* if(is_a_color(new_color)) */
712
+
713
+ save_rgba_to_image_local_color(self, new_color);
714
+
715
+ return Qnil;
716
+ }
717
+
718
+ /* this function manages all other method calls */
719
+ VALUE
720
+ m_missing(int argc, VALUE * argv, VALUE self)
721
+ {
722
+ char * action_name = lowercase(sym2string(argv[0]));
723
+
724
+ /* try case insensitive version of action name */
725
+ if(rb_respond_to(self, rb_intern(action_name))) {
726
+ rb_funcall2(self, rb_intern(action_name), --argc, ++argv);
727
+ }
728
+ /* still no match? then method does not exist */
729
+ else {
730
+ rb_raise (rb_eRuntimeError, "unrecognized action: %s\n", action_name);
731
+ }
732
+
733
+ return self;
734
+ }
735
+
736
+ /* refreshes the cache */
737
+ VALUE
738
+ m_cache_refresh(VALUE self)
739
+ {
740
+ texture_info tex;
741
+
742
+ ADJUST_SELF(self);
743
+
744
+ get_texture_info(self, &tex);
745
+
746
+ cache_refresh_entry(tex.tname);
747
+
748
+ return self;
749
+ }
750
+
751
+ /* check whether img quad is already cached */
752
+ VALUE
753
+ m_quad_cached(VALUE self)
754
+ {
755
+ VALUE info, gc_state_off;
756
+ int tex_name;
757
+ cache_entry * entry;
758
+
759
+ ADJUST_SELF(self);
760
+
761
+ /* prevent weird segfault bug */
762
+ gc_state_off = rb_gc_disable();
763
+
764
+ /* ensure gl_tex_info returns non nil */
765
+ info = check_for_texture_info(self);
766
+
767
+ tex_name = FIX2INT(rb_funcall(info, rb_intern("tex_name"), 0));
768
+
769
+ entry = find_in_cache(tex_name);
770
+
771
+ /* only enable gc if was enabled on function entry */
772
+ if(!gc_state_off) rb_gc_enable();
773
+
774
+ return entry ? Qtrue : Qfalse;
775
+ }
776
+
777
+ /** m_each **/
778
+ VALUE
779
+ m_each(int argc, VALUE * argv, VALUE self)
780
+ {
781
+ int x1 = 0, y1 = 0, x2 = XMAX_OOB, y2 = YMAX_OOB;
782
+ texture_info tex;
783
+ VALUE proc;
784
+ VALUE options = Qnil;
785
+
786
+ rb_need_block();
787
+
788
+ ADJUST_SELF(self);
789
+
790
+ get_texture_info(self, &tex);
791
+
792
+ if(argc >= 1) {
793
+ options = argv[0];
794
+ Check_Type(options, T_HASH);
795
+ if(RTEST(get_from_hash(options, "region"))) {
796
+ VALUE region = get_from_hash(options, "region");
797
+ Check_Type(region, T_ARRAY);
798
+
799
+ if(RARRAY_LEN(region) < 4)
800
+ rb_raise(rb_eArgError, "region requires 4 elements");
801
+
802
+ x1 = NUM2INT(get_from_array(region, 0));
803
+ y1 = NUM2INT(get_from_array(region, 1));
804
+ x2 = NUM2INT(get_from_array(region, 2));
805
+ y2 = NUM2INT(get_from_array(region, 3));
806
+
807
+ }
808
+
809
+ }
810
+
811
+ constrain_boundaries(&x1, &y1,
812
+ &x2, &y2, tex.width, tex.height);
813
+
814
+ proc = rb_block_proc();
815
+
816
+ each_pixel_do_action(x1, y1, x2, y2, proc, &tex, options, sync_mode, true, NULL);
817
+
818
+ return self;
819
+ }
820
+ /** end of each **/
821
+
822
+ /** turtle drawing functions **/
823
+ /* static VALUE */
824
+ /* m_turtle_move_to */
825
+
826
+ /* VALUE */
827
+ /* m_bezier(int argc, VALUE * argv, VALUE self) */
828
+ /* { */
829
+ /* VALUE points = Qnil; */
830
+ /* VALUE options = Qnil; */
831
+ /* int last = argc - 1; */
832
+ /* texture_info tex; */
833
+
834
+ /* ADJUST_SELF(self); */
835
+
836
+ /* if(argc < 1) rb_raise(rb_eArgError, "bezier action needs at least 1 parameter"); */
837
+
838
+ /* /\* get array of points *\/ */
839
+ /* points = argv[0]; */
840
+ /* Check_Type(points, T_ARRAY); */
841
+
842
+ /* options = argv[last]; */
843
+
844
+ /* get_texture_info(self, &tex); */
845
+
846
+ /* bezier_do_action(points, &tex, options, sync_mode, true, NULL); */
847
+
848
+ /* return self; */
849
+ /* } */
850
+
851
+ /** end turtle drawing **/
852
+
853
+
854
+ /* below is yucky old code that needs to be updated */
855
+ /* each_pixel iterator */
856
+
857
+
858
+ /* VALUE */
859
+ /* m_each(int argc, VALUE * argv, VALUE self) */
860
+ /* { */
861
+ /* int x0, y0, x1, y1, xbound, ybound, arity; */
862
+ /* VALUE options, region, pixel_data[2], yield_vals; */
863
+ /* register int x, y; */
864
+ /* texture_info tex; */
865
+ /* image_bounds bounds; */
866
+
867
+ /* rb_need_block(); */
868
+
869
+ /* arity = FIX2INT(rb_funcall(rb_block_proc(), rb_intern("arity"), 0)); */
870
+ /* if(arity != 1 && arity != 3) */
871
+ /* rb_raise(rb_eRuntimeError, "block arity must be either 1 or 3"); */
872
+
873
+ /* /\* ADJUST_SELF(self); *\/ */
874
+
875
+ /* /\* rb_scan_args(argc, argv, "01", &options); *\/ */
876
+
877
+ /* /\* /\\* get texture info *\\/ *\/ */
878
+ /* /\* get_texture_info(self, &tex); *\/ */
879
+
880
+ /* /\* /\\* default values for region *\\/ *\/ */
881
+ /* /\* x0 = 0; y0 = 0; x1 = tex.width; y1 = tex.height; *\/ */
882
+
883
+ /* /\* if(has_optional_hash_arg(options, "region")) { *\/ */
884
+ /* /\* region = get_from_hash(options, "region"); *\/ */
885
+
886
+ /* /\* x0 = NUM2INT(get_from_array(region, 0)); *\/ */
887
+ /* /\* y0 = NUM2INT(get_from_array(region, 1)); *\/ */
888
+ /* /\* x1 = NUM2INT(get_from_array(region, 2)); *\/ */
889
+ /* /\* y1 = NUM2INT(get_from_array(region, 3)); *\/ */
890
+
891
+ /* /\* constrain_boundaries(&x0, &y0, &x1, &y1, tex.width, tex.height); *\/ */
892
+ /* /\* } *\/ */
893
+
894
+ /* /\* /\\* width and height of action *\\/ *\/ */
895
+ /* /\* xbound = x1 - x0; *\/ */
896
+ /* /\* ybound = y1 - y0; *\/ */
897
+
898
+ /* /\* yield_vals = rb_ary_new(); *\/ */
899
+
900
+ /* /\* for(y = 0; y < ybound; y++) *\/ */
901
+ /* /\* for(x = 0; x < xbound; x++) { *\/ */
902
+ /* /\* VALUE pixel_color; *\/ */
903
+ /* /\* rgba old_color; *\/ */
904
+
905
+ /* /\* /\\* adjusted x and y *\\/ *\/ */
906
+ /* /\* register int ax = x + x0, ay = y + y0; *\/ */
907
+
908
+ /* /\* pixel_data[0] = INT2FIX(ax); *\/ */
909
+ /* /\* pixel_data[1] = INT2FIX(ay); *\/ */
910
+
911
+ /* /\* pixel_color = m_getpixel(self, INT2FIX(ax), INT2FIX(ay)); *\/ */
912
+
913
+ /* /\* if(arity == 1) { *\/ */
914
+ /* /\* rb_yield(pixel_color); *\/ */
915
+ /* /\* } *\/ */
916
+ /* /\* else if(arity == 3) { *\/ */
917
+ /* /\* rb_ary_store(yield_vals, 0, pixel_color); *\/ */
918
+ /* /\* rb_ary_store(yield_vals, 1, INT2FIX(x)); *\/ */
919
+ /* /\* rb_ary_store(yield_vals, 2, INT2FIX(y)); *\/ */
920
+
921
+ /* /\* rb_yield(yield_vals); *\/ */
922
+ /* /\* } *\/ */
923
+
924
+ /* /\* m_color(1, &pixel_color, self); *\/ */
925
+ /* /\* // process_action(pixel, self, 2, pixel_data, false); *\/ */
926
+ /* /\* // color_struct = old_color; *\/ */
927
+ /* /\* } *\/ */
928
+
929
+ /* /\* bounds.xmin = x0; *\/ */
930
+ /* /\* bounds.ymin = y0; *\/ */
931
+ /* /\* bounds.xmax = x1; *\/ */
932
+ /* /\* bounds.ymax = y1; *\/ */
933
+
934
+ /* /\* create_subtexture_and_sync_to_gl(&bounds, &tex); *\/ */
935
+
936
+ /* /\* return self; *\/ */
937
+ /* /\* } *\/ */
938
+
939
+ /* /\** end each_pixel algorithm **\/} */
940
+ /* /\** end each_pixel algorithm **\/ */
941
+
942
+
943
+ /* /\* VALUE *\/ */
944
+ /* /\* m_lshift(int argc, VALUE * argv, VALUE self) *\/ */
945
+ /* /\* { *\/ */
946
+ /* /\* int y,x, step, yoffset; *\/ */
947
+ /* /\* VALUE options, loop; *\/ */
948
+ /* /\* register int offset; *\/ */
949
+ /* /\* texture_info tex; *\/ */
950
+ /* /\* image_bounds bounds; *\/ */
951
+
952
+ /* /\* ADJUST_SELF(self); *\/ */
953
+
954
+ /* /\* rb_scan_args(argc, argv, "01", &options); *\/ */
955
+
956
+ /* /\* /\\* default values for other params *\\/ *\/ */
957
+ /* /\* step = 1; loop = Qfalse; *\/ */
958
+
959
+ /* /\* if(TYPE(options) == T_HASH) { *\/ */
960
+ /* /\* step = NUM2INT(get_from_hash(options, "step")); *\/ */
961
+ /* /\* loop = get_from_hash(options, "loop"); *\/ */
962
+ /* /\* } *\/ */
963
+ /* /\* else if(options != Qnil) { *\/ */
964
+ /* /\* rb_raise(rb_eArgError, "argument must be a hash"); *\/ */
965
+ /* /\* } *\/ */
966
+
967
+ /* /\* /\\* get texture info *\\/ *\/ */
968
+ /* /\* get_texture_info(self, &tex); *\/ */
969
+
970
+ /* /\* for(y = 0; y < tex.height; y++) { *\/ */
971
+ /* /\* for(x = 0; x < tex.width; x++) { *\/ */
972
+ /* /\* offset = calc_pixel_offset(&tex, x, y); *\/ */
973
+
974
+ /* /\* if((x + step) < tex.width) { *\/ */
975
+ /* /\* color_copy(tex.td_array + offset + step * 4, tex.td_array + offset); *\/ */
976
+ /* /\* } *\/ */
977
+ /* /\* else { *\/ */
978
+ /* /\* if(loop == Qtrue) { *\/ */
979
+ /* /\* yoffset = calc_pixel_offset(&tex, x + step - tex.width, y); *\/ */
980
+
981
+ /* /\* color_copy(tex.td_array + yoffset, tex.td_array + offset); *\/ */
982
+ /* /\* } *\/ */
983
+ /* /\* else { *\/ */
984
+
985
+ /* /\* zero_color(tex.td_array + offset); *\/ */
986
+ /* /\* } *\/ */
987
+ /* /\* } *\/ */
988
+
989
+ /* /\* } *\/ */
990
+ /* /\* } *\/ */
991
+
992
+ /* /\* bounds.xmin = 0; *\/ */
993
+ /* /\* bounds.xmax = tex.width; *\/ */
994
+ /* /\* bounds.ymin = 0; *\/ */
995
+ /* /\* bounds.ymax = tex.height; *\/ */
996
+
997
+ /* /\* create_subtexture_and_sync_to_gl(&bounds, &tex); *\/ */
998
+
999
+ /* /\* return Qnil; *\/ */
1000
+ /* /\* } *\/ */
1001
+
1002
+ /* /\* VALUE *\/ */
1003
+ /* /\* m_rshift(int argc, VALUE * argv, VALUE self) *\/ */
1004
+ /* /\* { *\/ */
1005
+ /* /\* int y,x, step, yoffset; *\/ */
1006
+ /* /\* VALUE options, loop; *\/ */
1007
+ /* /\* register int offset; *\/ */
1008
+ /* /\* texture_info tex; *\/ */
1009
+ /* /\* image_bounds bounds; *\/ */
1010
+
1011
+ /* /\* ADJUST_SELF(self); *\/ */
1012
+
1013
+ /* /\* rb_scan_args(argc, argv, "01", &options); *\/ */
1014
+
1015
+ /* /\* /\\* default values for other params *\\/ *\/ */
1016
+ /* /\* step = 1; loop = Qfalse; *\/ */
1017
+
1018
+ /* /\* if(TYPE(options) == T_HASH) { *\/ */
1019
+ /* /\* step = NUM2INT(get_from_hash(options, "step")); *\/ */
1020
+ /* /\* loop = get_from_hash(options, "loop"); *\/ */
1021
+ /* /\* } *\/ */
1022
+ /* /\* else if(options != Qnil) { *\/ */
1023
+ /* /\* rb_raise(rb_eArgError, "argument must be a hash"); *\/ */
1024
+ /* /\* } *\/ */
1025
+
1026
+ /* /\* /\\* get texture info *\\/ *\/ */
1027
+ /* /\* get_texture_info(self, &tex); *\/ */
1028
+
1029
+ /* /\* for(y = 0; y < tex.height; y++) { *\/ */
1030
+ /* /\* for(x = tex.width - 1; x > -1; x--) { *\/ */
1031
+ /* /\* offset = calc_pixel_offset(&tex, x, y); *\/ */
1032
+
1033
+ /* /\* if((x - step) > -1) { *\/ */
1034
+ /* /\* color_copy(tex.td_array + offset - step * 4, tex.td_array + offset); *\/ */
1035
+ /* /\* } *\/ */
1036
+ /* /\* else { *\/ */
1037
+ /* /\* if(loop == Qtrue) { *\/ */
1038
+ /* /\* yoffset = calc_pixel_offset(&tex, x + tex.width - step, y); *\/ */
1039
+ /* /\* color_copy(tex.td_array + yoffset, tex.td_array + offset); *\/ */
1040
+ /* /\* } *\/ */
1041
+ /* /\* else { *\/ */
1042
+ /* /\* zero_color(tex.td_array + offset); *\/ */
1043
+ /* /\* } *\/ */
1044
+ /* /\* } *\/ */
1045
+
1046
+ /* /\* } *\/ */
1047
+ /* /\* } *\/ */
1048
+
1049
+ /* /\* bounds.xmin = 0; *\/ */
1050
+ /* /\* bounds.xmax = tex.width; *\/ */
1051
+ /* /\* bounds.ymin = 0; *\/ */
1052
+ /* /\* bounds.ymax = tex.height; *\/ */
1053
+
1054
+ /* /\* create_subtexture_and_sync_to_gl(&bounds, &tex); *\/ */
1055
+
1056
+ /* /\* return Qnil; *\/ */
1057
+ /* /\* } *\/ */
1058
+
1059
+ /* /\* /\\* special pixel action for image[]= *\\/ *\/ */
1060
+ /* /\* VALUE *\/ */
1061
+ /* /\* m_special_pixel(int argc, VALUE * argv, VALUE self) *\/ */
1062
+ /* /\* { *\/ */
1063
+
1064
+ /* /\* rgba old_color; *\/ */
1065
+
1066
+ /* /\* ADJUST_SELF(self); *\/ */
1067
+
1068
+ /* /\* if(argc < 3) rb_raise(rb_eArgError, "[]= action needs 3 parameters"); *\/ */
1069
+
1070
+ /* /\* m_color(1, &argv[2], self); *\/ */
1071
+
1072
+ /* /\* m_pixel(2, argv, self); *\/ */
1073
+
1074
+ /* /\* // color_struct = old_color; *\/ */
1075
+
1076
+
1077
+ /* /\* return Qnil; *\/ */
1078
+ /* /\* } *\/ */
1079
+
1080
+ /* /\* /\\* instance methods *\\/ *\/ */
1081
+