texplay 0.2.800 → 0.2.900
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.
- data/CHANGELOG +138 -119
- data/README.markdown +43 -41
- data/Rakefile +68 -68
- data/examples/common.rb +8 -8
- data/examples/example_alpha_blend.rb +31 -31
- data/examples/example_bezier.rb +42 -42
- data/examples/example_color_control.rb +69 -69
- data/examples/example_color_transform.rb +64 -67
- data/examples/example_color_transform_circle.rb +65 -0
- data/examples/example_dup.rb +75 -75
- data/examples/example_each.rb +42 -42
- data/examples/example_effect.rb +35 -35
- data/examples/example_fill.rb +44 -44
- data/examples/example_fill_old.rb +49 -49
- data/examples/example_fluent.rb +31 -31
- data/examples/example_gen_eval.rb +34 -34
- data/examples/example_hash_arguments.rb +47 -47
- data/examples/example_light.rb +77 -0
- data/examples/example_lsystem.rb +61 -61
- data/examples/example_melt.rb +27 -27
- data/examples/example_meyet.rb +64 -0
- data/examples/example_polyline.rb +43 -43
- data/examples/example_scale.rb +29 -29
- data/examples/example_simple.rb +48 -38
- data/examples/example_sync.rb +60 -60
- data/examples/example_trace.rb +1 -1
- data/examples/example_turtle.rb +40 -40
- data/examples/example_weird.rb +3 -1
- data/examples/media/Thumbs.db +0 -0
- data/ext/texplay/actions.c +999 -1001
- data/ext/texplay/actions.h +60 -60
- data/ext/texplay/bindings.c +1162 -1149
- data/ext/texplay/bindings.h +46 -46
- data/ext/texplay/cache.c +118 -118
- data/ext/texplay/cache.h +24 -24
- data/ext/texplay/compat.h +27 -27
- data/ext/texplay/extconf.rb +28 -28
- data/ext/texplay/gen_eval.c +211 -211
- data/ext/texplay/gen_eval.h +20 -20
- data/ext/texplay/graphics_utils.c +188 -63
- data/ext/texplay/graphics_utils.h +0 -1
- data/ext/texplay/object2module.c +171 -171
- data/ext/texplay/object2module.h +11 -11
- data/ext/texplay/texplay.c +169 -169
- data/ext/texplay/texplay.h +147 -130
- data/ext/texplay/utils.c +816 -752
- data/ext/texplay/utils.h +151 -145
- data/lib/texplay-contrib.rb +171 -171
- data/lib/texplay.rb +162 -137
- data/lib/texplay/version.rb +1 -1
- metadata +9 -5
data/ext/texplay/utils.h
CHANGED
@@ -1,145 +1,151 @@
|
|
1
|
-
#ifndef GUARD_UTILS_H
|
2
|
-
#define GUARD_UTILS_H
|
3
|
-
|
4
|
-
|
5
|
-
/* for use with get_image_local, and set_image_local */
|
6
|
-
#define DRAW_OFFSET 0
|
7
|
-
#define LAZY_BOUNDS 1
|
8
|
-
#define IMAGE_COLOR 2
|
9
|
-
#define USER_DEFAULTS 3
|
10
|
-
|
11
|
-
/* shared global */
|
12
|
-
extern const rgba not_a_color_v;
|
13
|
-
|
14
|
-
/* color and pixel related functions */
|
15
|
-
rgba find_color_from_string(char * try_color);
|
16
|
-
bool cmp_color(rgba color1, rgba color2);
|
17
|
-
void color_copy(float * source, float * dest);
|
18
|
-
rgba get_pixel_color(texture_info * tex, int x, int y) ;
|
19
|
-
float* get_pixel_data(texture_info * tex, int x, int y);
|
20
|
-
void set_pixel_color(rgba * pixel_color, texture_info * tex, int x, int y);
|
21
|
-
void zero_color(float * tex);
|
22
|
-
bool not_a_color(rgba color1);
|
23
|
-
bool is_a_color(rgba color1);
|
24
|
-
VALUE convert_rgba_to_rb_color(rgba * pix);
|
25
|
-
rgba convert_rb_color_to_rgba(VALUE cval);
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
VALUE
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
/* is a
|
43
|
-
bool
|
44
|
-
|
45
|
-
/*
|
46
|
-
|
47
|
-
|
48
|
-
/* a
|
49
|
-
|
50
|
-
|
51
|
-
/*
|
52
|
-
VALUE
|
53
|
-
|
54
|
-
/*
|
55
|
-
|
56
|
-
|
57
|
-
/*
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
/*
|
68
|
-
VALUE
|
69
|
-
|
70
|
-
/*
|
71
|
-
|
72
|
-
|
73
|
-
/*
|
74
|
-
VALUE
|
75
|
-
|
76
|
-
/*
|
77
|
-
|
78
|
-
|
79
|
-
/*
|
80
|
-
|
81
|
-
|
82
|
-
/*
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
/*
|
105
|
-
|
106
|
-
|
107
|
-
/*
|
108
|
-
|
109
|
-
|
110
|
-
/*
|
111
|
-
|
112
|
-
|
113
|
-
/*
|
114
|
-
|
115
|
-
|
116
|
-
/*
|
117
|
-
|
118
|
-
|
119
|
-
/*
|
120
|
-
void
|
121
|
-
|
122
|
-
/*
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
1
|
+
#ifndef GUARD_UTILS_H
|
2
|
+
#define GUARD_UTILS_H
|
3
|
+
|
4
|
+
|
5
|
+
/* for use with get_image_local, and set_image_local */
|
6
|
+
#define DRAW_OFFSET 0
|
7
|
+
#define LAZY_BOUNDS 1
|
8
|
+
#define IMAGE_COLOR 2
|
9
|
+
#define USER_DEFAULTS 3
|
10
|
+
|
11
|
+
/* shared global */
|
12
|
+
extern const rgba not_a_color_v;
|
13
|
+
|
14
|
+
/* color and pixel related functions */
|
15
|
+
rgba find_color_from_string(char * try_color);
|
16
|
+
bool cmp_color(rgba color1, rgba color2);
|
17
|
+
void color_copy(float * source, float * dest);
|
18
|
+
rgba get_pixel_color(texture_info * tex, int x, int y) ;
|
19
|
+
float* get_pixel_data(texture_info * tex, int x, int y);
|
20
|
+
void set_pixel_color(rgba * pixel_color, texture_info * tex, int x, int y);
|
21
|
+
void zero_color(float * tex);
|
22
|
+
bool not_a_color(rgba color1);
|
23
|
+
bool is_a_color(rgba color1);
|
24
|
+
VALUE convert_rgba_to_rb_color(rgba * pix);
|
25
|
+
rgba convert_rb_color_to_rgba(VALUE cval);
|
26
|
+
bool is_gosu_color(VALUE try_color);
|
27
|
+
bool is_rb_raw_color(VALUE cval);
|
28
|
+
bool not_rb_raw_color(VALUE cval);
|
29
|
+
rgba convert_gosu_to_rgba_color(VALUE gcolor);
|
30
|
+
VALUE convert_rgba_to_gosu_color(rgba * pix);
|
31
|
+
|
32
|
+
|
33
|
+
VALUE save_rgba_to_image_local_color(VALUE image, rgba color);
|
34
|
+
rgba convert_image_local_color_to_rgba(VALUE image);
|
35
|
+
|
36
|
+
|
37
|
+
/* string/symbol related functions */
|
38
|
+
char* lowercase(char*);
|
39
|
+
char* sym2string(VALUE);
|
40
|
+
VALUE string2sym(char*);
|
41
|
+
|
42
|
+
/* is it a hash? */
|
43
|
+
bool is_a_hash(VALUE try_hash);
|
44
|
+
|
45
|
+
/* is an array? */
|
46
|
+
bool is_an_array(VALUE try_array);
|
47
|
+
|
48
|
+
/* is a num? */
|
49
|
+
bool is_a_num(VALUE try_num);
|
50
|
+
|
51
|
+
/* helpful C wrapper for rb_hash_aref */
|
52
|
+
VALUE get_from_hash(VALUE hash, char * sym);
|
53
|
+
|
54
|
+
/* a wrapper for rb_hash_aset */
|
55
|
+
VALUE set_hash_value(VALUE hash, char * sym, VALUE val);
|
56
|
+
|
57
|
+
/* a wrapper for rb_hash_delete */
|
58
|
+
VALUE delete_from_hash(VALUE hash, char * sym);
|
59
|
+
|
60
|
+
/* does the hash key 'sym' map to value 'val'? */
|
61
|
+
bool hash_value_is(VALUE hash, char * sym, VALUE val);
|
62
|
+
|
63
|
+
/* determine whether (1) hash is a T_HASH (2) the sym exists in the hash */
|
64
|
+
bool has_optional_hash_arg(VALUE hash, char * sym);
|
65
|
+
|
66
|
+
|
67
|
+
/* helpful C wrapper for rb_array_store */
|
68
|
+
VALUE set_array_value(VALUE array, int index, VALUE val);
|
69
|
+
|
70
|
+
/* helpful C wrapper for rb_array_entry */
|
71
|
+
VALUE get_from_array(VALUE array, int index);
|
72
|
+
|
73
|
+
/* set the lazy_bounds ivar for an image */
|
74
|
+
VALUE set_ivar_array(VALUE obj, char * ivar, int argc, ...);
|
75
|
+
|
76
|
+
/* initialize lazy_bounds */
|
77
|
+
void init_lazy_bounds(VALUE image);
|
78
|
+
|
79
|
+
/* initialize the image_local var array */
|
80
|
+
VALUE init_image_local(VALUE image);
|
81
|
+
|
82
|
+
/* return an image local variable */
|
83
|
+
VALUE get_image_local(VALUE image, int name);
|
84
|
+
|
85
|
+
/* set an image local variable */
|
86
|
+
void set_image_local(VALUE image, int name, VALUE val);
|
87
|
+
|
88
|
+
/* error checking functions */
|
89
|
+
void check_mask(VALUE mask);
|
90
|
+
|
91
|
+
void check_image(VALUE image);
|
92
|
+
|
93
|
+
/* is try_image a Gosu::Image ? */
|
94
|
+
bool is_gosu_image(VALUE try_image);
|
95
|
+
|
96
|
+
|
97
|
+
/* make boundaries sane */
|
98
|
+
void constrain_boundaries(int * x0, int * y0, int * x1, int * y1, int width, int height);
|
99
|
+
|
100
|
+
/* line clipping */
|
101
|
+
void cohen_sutherland_clip (int * x0, int * y0,int * x1, int * y1, int xmin, int ymin,
|
102
|
+
int xmax, int ymax);
|
103
|
+
|
104
|
+
/* check if point is bound by rect and inner thickness */
|
105
|
+
bool bound_by_rect_and_inner(int x, int y, int x0, int y0, int x1, int y1, int inner);
|
106
|
+
|
107
|
+
/* check if point is bound by rect */
|
108
|
+
bool bound_by_rect(int x, int y, int x0, int y0, int x1, int y1);
|
109
|
+
|
110
|
+
/* calculate the array offset for a given pixel */
|
111
|
+
int calc_pixel_offset(texture_info * tex, int x, int y);
|
112
|
+
|
113
|
+
/* calculate the array offset for a given pixel in an action context */
|
114
|
+
int calc_pixel_offset_for_action(action_struct * cur, texture_info * tex, int x, int y);
|
115
|
+
|
116
|
+
/* return a pointer to a new texture */
|
117
|
+
float* allocate_texture(int width, int height);
|
118
|
+
|
119
|
+
/* other function prototypes, get info for a texture */
|
120
|
+
void get_texture_info(VALUE image, texture_info * tex);
|
121
|
+
|
122
|
+
/* ensure gl_tex_info returns non nil */
|
123
|
+
VALUE check_for_texture_info(VALUE image);
|
124
|
+
|
125
|
+
/* responsible for syncing a subimage to gl */
|
126
|
+
void sync_to_gl(int tex_name, int x_offset, int y_offset, int width, int height, void * sub);
|
127
|
+
|
128
|
+
/* create a subtexture and sync to gl */
|
129
|
+
void create_subtexture_and_sync_to_gl(image_bounds * img_bounds, texture_info * tex);
|
130
|
+
|
131
|
+
float * get_image_chunk(texture_info * tex, int xmin, int ymin, int xmax, int ymax);
|
132
|
+
|
133
|
+
rgba get_pixel_color_from_chunk(float * chunk, int width, int height, int x, int y);
|
134
|
+
|
135
|
+
/* from Texture.cpp in Gosu Graphics folder */
|
136
|
+
unsigned max_quad_size(void);
|
137
|
+
|
138
|
+
/* point utils */
|
139
|
+
bool is_a_point(VALUE try_point);
|
140
|
+
VALUE point_x(VALUE point);
|
141
|
+
VALUE point_y(VALUE point);
|
142
|
+
|
143
|
+
/* mathematical utils, used by bezier curves */
|
144
|
+
double power(float base, int exp);
|
145
|
+
unsigned fact(int n);
|
146
|
+
unsigned comb(int n, int k);
|
147
|
+
unsigned perm(int n, int r);
|
148
|
+
|
149
|
+
double bernstein(int n, int k, float u);
|
150
|
+
|
151
|
+
#endif
|
data/lib/texplay-contrib.rb
CHANGED
@@ -1,171 +1,171 @@
|
|
1
|
-
begin
|
2
|
-
require 'rubygems'
|
3
|
-
rescue LoadError
|
4
|
-
end
|
5
|
-
|
6
|
-
require 'texplay'
|
7
|
-
|
8
|
-
# to bring in String#each_char for 1.8
|
9
|
-
if RUBY_VERSION =~ /1.8/
|
10
|
-
require 'jcode'
|
11
|
-
end
|
12
|
-
|
13
|
-
# setup will be executed straight after Gosu::Image instantiation
|
14
|
-
TexPlay::on_setup do
|
15
|
-
@turtle_pos = TexPlay::TPPoint.new(width / 2, height / 2 )
|
16
|
-
@turtle_angle = 0
|
17
|
-
end
|
18
|
-
|
19
|
-
|
20
|
-
TexPlay::create_macro(:move_to) do |x, y|
|
21
|
-
capture {
|
22
|
-
@turtle_pos.x = x
|
23
|
-
@turtle_pos.y = y
|
24
|
-
}
|
25
|
-
end
|
26
|
-
|
27
|
-
TexPlay::create_macro(:move_rel) do |dx, dy|
|
28
|
-
capture {
|
29
|
-
@turtle_pos.x += dx
|
30
|
-
@turtle_pos.y += dy
|
31
|
-
}
|
32
|
-
end
|
33
|
-
|
34
|
-
TexPlay::create_macro(:line_to) do |x, y, *other|
|
35
|
-
capture {
|
36
|
-
line(@turtle_pos.x, @turtle_pos.y, x, y, *other)
|
37
|
-
|
38
|
-
@turtle_pos.x, @turtle_pos.y = x, y
|
39
|
-
}
|
40
|
-
end
|
41
|
-
|
42
|
-
TexPlay::create_macro(:line_rel) do |dx, dy, *other|
|
43
|
-
capture {
|
44
|
-
x = @turtle_pos.x + dx
|
45
|
-
y = @turtle_pos.y + dy
|
46
|
-
|
47
|
-
line(@turtle_pos.x, @turtle_pos.y, x, y, *other)
|
48
|
-
|
49
|
-
@turtle_pos.x, @turtle_pos.y = x, y
|
50
|
-
}
|
51
|
-
end
|
52
|
-
|
53
|
-
TexPlay::create_macro(:turn_to) do |a|
|
54
|
-
capture {
|
55
|
-
@turtle_angle = a
|
56
|
-
}
|
57
|
-
end
|
58
|
-
|
59
|
-
TexPlay::create_macro(:turn) do |da|
|
60
|
-
capture {
|
61
|
-
@turtle_angle += da
|
62
|
-
}
|
63
|
-
end
|
64
|
-
|
65
|
-
TexPlay::create_macro(:forward) do |dist, *other|
|
66
|
-
capture {
|
67
|
-
visible = other.shift
|
68
|
-
|
69
|
-
radians_per_degree = 0.0174532925199433
|
70
|
-
|
71
|
-
x = @turtle_pos.x + dist * Math::cos(radians_per_degree * @turtle_angle)
|
72
|
-
y = @turtle_pos.y + dist * Math::sin(radians_per_degree * @turtle_angle)
|
73
|
-
|
74
|
-
if(visible) then
|
75
|
-
line_to(x, y, *other)
|
76
|
-
else
|
77
|
-
move_to(x, y)
|
78
|
-
end
|
79
|
-
}
|
80
|
-
end
|
81
|
-
|
82
|
-
# L-System code
|
83
|
-
# adding LSystem class to TexPlay module
|
84
|
-
class TexPlay::LSystem
|
85
|
-
def initialize(&block)
|
86
|
-
@rules = {}
|
87
|
-
|
88
|
-
instance_eval(&block) if block
|
89
|
-
end
|
90
|
-
|
91
|
-
def rule(new_rule)
|
92
|
-
@rules.merge!(new_rule)
|
93
|
-
end
|
94
|
-
|
95
|
-
def atom(new_atom)
|
96
|
-
@atom = new_atom
|
97
|
-
end
|
98
|
-
|
99
|
-
def angle(new_angle=nil)
|
100
|
-
return @angle if !new_angle
|
101
|
-
@angle = new_angle
|
102
|
-
end
|
103
|
-
|
104
|
-
def produce_string(order)
|
105
|
-
order = order[:order]
|
106
|
-
string = @atom.dup
|
107
|
-
|
108
|
-
order.times do
|
109
|
-
i = 0
|
110
|
-
while(i < string.length)
|
111
|
-
sub = @rules[string[i, 1]]
|
112
|
-
|
113
|
-
string[i] = sub if sub
|
114
|
-
|
115
|
-
i += sub ? sub.length : 1
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
string
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
# L-System macro
|
124
|
-
TexPlay::create_macro(:lsystem) do |x, y, system, options|
|
125
|
-
capture {
|
126
|
-
theta = system.angle
|
127
|
-
turtle_stack = []
|
128
|
-
move_to(x, y)
|
129
|
-
line_length = options[:line_length] || 1
|
130
|
-
|
131
|
-
system.produce_string(options).each_char do |v|
|
132
|
-
|
133
|
-
case v
|
134
|
-
when "F"
|
135
|
-
forward(line_length, true)
|
136
|
-
when "+"
|
137
|
-
turn(theta)
|
138
|
-
when "-"
|
139
|
-
turn(-theta)
|
140
|
-
when "["
|
141
|
-
turtle_stack.push([@turtle_pos.dup, @turtle_angle])
|
142
|
-
when "]"
|
143
|
-
@turtle_pos, @turtle_angle = turtle_stack.pop
|
144
|
-
end
|
145
|
-
end
|
146
|
-
}
|
147
|
-
end
|
148
|
-
|
149
|
-
# Scaling
|
150
|
-
# uses nearest-neighbour
|
151
|
-
TexPlay::create_macro(:splice_and_scale) do |img, cx, cy, *options|
|
152
|
-
options = options.first ? options.first : {}
|
153
|
-
|
154
|
-
options = {
|
155
|
-
:color_control => proc do |c1, c2, x, y|
|
156
|
-
factor = options[:factor] || 1
|
157
|
-
factor_x = options[:factor_x] || factor
|
158
|
-
factor_y = options[:factor_y] || factor
|
159
|
-
|
160
|
-
x = factor_x * (x - cx) + cx
|
161
|
-
y = factor_y * (y - cy) + cy
|
162
|
-
|
163
|
-
rect x, y, x + factor_x, y + factor_y, :color => c2, :fill => true
|
164
|
-
:none
|
165
|
-
end
|
166
|
-
}.merge!(options)
|
167
|
-
|
168
|
-
splice img, cx, cy, options
|
169
|
-
|
170
|
-
self
|
171
|
-
end
|
1
|
+
begin
|
2
|
+
require 'rubygems'
|
3
|
+
rescue LoadError
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'texplay'
|
7
|
+
|
8
|
+
# to bring in String#each_char for 1.8
|
9
|
+
if RUBY_VERSION =~ /1.8/
|
10
|
+
require 'jcode'
|
11
|
+
end
|
12
|
+
|
13
|
+
# setup will be executed straight after Gosu::Image instantiation
|
14
|
+
TexPlay::on_setup do
|
15
|
+
@turtle_pos = TexPlay::TPPoint.new(width / 2, height / 2 )
|
16
|
+
@turtle_angle = 0
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
TexPlay::create_macro(:move_to) do |x, y|
|
21
|
+
capture {
|
22
|
+
@turtle_pos.x = x
|
23
|
+
@turtle_pos.y = y
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
TexPlay::create_macro(:move_rel) do |dx, dy|
|
28
|
+
capture {
|
29
|
+
@turtle_pos.x += dx
|
30
|
+
@turtle_pos.y += dy
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
TexPlay::create_macro(:line_to) do |x, y, *other|
|
35
|
+
capture {
|
36
|
+
line(@turtle_pos.x, @turtle_pos.y, x, y, *other)
|
37
|
+
|
38
|
+
@turtle_pos.x, @turtle_pos.y = x, y
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
TexPlay::create_macro(:line_rel) do |dx, dy, *other|
|
43
|
+
capture {
|
44
|
+
x = @turtle_pos.x + dx
|
45
|
+
y = @turtle_pos.y + dy
|
46
|
+
|
47
|
+
line(@turtle_pos.x, @turtle_pos.y, x, y, *other)
|
48
|
+
|
49
|
+
@turtle_pos.x, @turtle_pos.y = x, y
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
TexPlay::create_macro(:turn_to) do |a|
|
54
|
+
capture {
|
55
|
+
@turtle_angle = a
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
TexPlay::create_macro(:turn) do |da|
|
60
|
+
capture {
|
61
|
+
@turtle_angle += da
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
TexPlay::create_macro(:forward) do |dist, *other|
|
66
|
+
capture {
|
67
|
+
visible = other.shift
|
68
|
+
|
69
|
+
radians_per_degree = 0.0174532925199433
|
70
|
+
|
71
|
+
x = @turtle_pos.x + dist * Math::cos(radians_per_degree * @turtle_angle)
|
72
|
+
y = @turtle_pos.y + dist * Math::sin(radians_per_degree * @turtle_angle)
|
73
|
+
|
74
|
+
if(visible) then
|
75
|
+
line_to(x, y, *other)
|
76
|
+
else
|
77
|
+
move_to(x, y)
|
78
|
+
end
|
79
|
+
}
|
80
|
+
end
|
81
|
+
|
82
|
+
# L-System code
|
83
|
+
# adding LSystem class to TexPlay module
|
84
|
+
class TexPlay::LSystem
|
85
|
+
def initialize(&block)
|
86
|
+
@rules = {}
|
87
|
+
|
88
|
+
instance_eval(&block) if block
|
89
|
+
end
|
90
|
+
|
91
|
+
def rule(new_rule)
|
92
|
+
@rules.merge!(new_rule)
|
93
|
+
end
|
94
|
+
|
95
|
+
def atom(new_atom)
|
96
|
+
@atom = new_atom
|
97
|
+
end
|
98
|
+
|
99
|
+
def angle(new_angle=nil)
|
100
|
+
return @angle if !new_angle
|
101
|
+
@angle = new_angle
|
102
|
+
end
|
103
|
+
|
104
|
+
def produce_string(order)
|
105
|
+
order = order[:order]
|
106
|
+
string = @atom.dup
|
107
|
+
|
108
|
+
order.times do
|
109
|
+
i = 0
|
110
|
+
while(i < string.length)
|
111
|
+
sub = @rules[string[i, 1]]
|
112
|
+
|
113
|
+
string[i] = sub if sub
|
114
|
+
|
115
|
+
i += sub ? sub.length : 1
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
string
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# L-System macro
|
124
|
+
TexPlay::create_macro(:lsystem) do |x, y, system, options|
|
125
|
+
capture {
|
126
|
+
theta = system.angle
|
127
|
+
turtle_stack = []
|
128
|
+
move_to(x, y)
|
129
|
+
line_length = options[:line_length] || 1
|
130
|
+
|
131
|
+
system.produce_string(options).each_char do |v|
|
132
|
+
|
133
|
+
case v
|
134
|
+
when "F"
|
135
|
+
forward(line_length, true)
|
136
|
+
when "+"
|
137
|
+
turn(theta)
|
138
|
+
when "-"
|
139
|
+
turn(-theta)
|
140
|
+
when "["
|
141
|
+
turtle_stack.push([@turtle_pos.dup, @turtle_angle])
|
142
|
+
when "]"
|
143
|
+
@turtle_pos, @turtle_angle = turtle_stack.pop
|
144
|
+
end
|
145
|
+
end
|
146
|
+
}
|
147
|
+
end
|
148
|
+
|
149
|
+
# Scaling
|
150
|
+
# uses nearest-neighbour
|
151
|
+
TexPlay::create_macro(:splice_and_scale) do |img, cx, cy, *options|
|
152
|
+
options = options.first ? options.first : {}
|
153
|
+
|
154
|
+
options = {
|
155
|
+
:color_control => proc do |c1, c2, x, y|
|
156
|
+
factor = options[:factor] || 1
|
157
|
+
factor_x = options[:factor_x] || factor
|
158
|
+
factor_y = options[:factor_y] || factor
|
159
|
+
|
160
|
+
x = factor_x * (x - cx) + cx
|
161
|
+
y = factor_y * (y - cy) + cy
|
162
|
+
|
163
|
+
rect x, y, x + factor_x, y + factor_y, :color => c2, :fill => true
|
164
|
+
:none
|
165
|
+
end
|
166
|
+
}.merge!(options)
|
167
|
+
|
168
|
+
splice img, cx, cy, options
|
169
|
+
|
170
|
+
self
|
171
|
+
end
|