1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
use hex_renderer::{
grids::{GridDraw, HexGrid},
options::{
palettes, CollisionOption, EndPoint, GridOptions, GridPatternOptions, Intersections, Lines,
Marker, OverloadOptions, Point, Triangle, Color
},
pattern_utils::Angle,
Pattern,
};
fn main() {
//patterns to draw
let patterns = "west qqq, west qqq, west qqq, west qqq, NORTH_EAST qeqwqwqwqwqeqssssaeqeaqeqaeqaqdededwaqdedsssssdssess, east eee, east eee, east eee, east eee";
let patterns = patterns
.split(", ")
.map(Pattern::try_from)
.collect::<Result<Vec<Pattern>, _>>()
.expect("Invalid Pattern List!");
let hex_grid = HexGrid::new_normal(patterns, 50).expect("Failed to make grid!");
//When drawing the grid, it takes in a GridOptions type
//it's parameters are as follows:
// 1. line_thickness
// -- thickness of line in comparison to line_width
// -- 0.12 means the line thickness is 12% that of it's length
// 2. pattern_options
// -- two types, Uniform and Changing
// -- Uniform contains specifications for how to draw the lines
// -- of the patterns and the dots to draw on top
//
// -- Changing is a vector of what's in changing
// -- + a set of patterns for when to switch
// -- for instance, go to the next when seeing the intro patten
// -- and going to the previous when seeing the retro pattern
// 3. center_dot
// -- The center dot is a dot put in the center of semi-contained
// -- patterns
// -- it is defined by a point which will be explained later.
//example
let _options = GridOptions {
//line thickness is 12% of line length
line_thickness: 0.12,
//uniform, (all patterns drawn the same)
pattern_options: GridPatternOptions::Uniform(
//no intersections (points) on the grid of the pattern
Intersections::Nothing,
//monocolor renderer
Lines::Monocolor {
//draws the lines with white
color: Color::WHITE,
//corners are bent like in the game
bent: true,
},
),
//no center dot
center_dot: Point::None,
};
//now, on the next step down, you have the line renderers
//this is where there's an acutal distinction in "renderers"
//like mentioned in the previous example, there are 3 types:
// monocolor - single color
// gradient - transitions between colors
// segment - switches between colors on conflict
//each of these takes a color which is imported via tiny_skia
//the color format is RGBA (where A is alpha/transparency)
let color = Color(0, 128, 128, 255);
//the monocolor type just takes in the color and if it's bent
//bent is where the lines bend around corners when multiple
//lines go throguht the same intersection/corner like in game
let _monocolor = Lines::Monocolor { color, bent: true };
//the gradient gradually changes between the colors given
//throughtout the entire pattern
//the segments_per_color parameter is to set a minimum
//amount of segments before transitioning to the next color
//for example if it's set to 10 segments_per_color:
// -- then 1-9 patterns will use 2 colors
// -- 10-19 will use 3 colors
// -- 20-29 will use 4 colors and so on until it's out of colors
//the bent parameter behaves the same as the one in monocolor
let colors = vec![
color,
Color(255, 0, 0, 255),
Color(0, 255, 0, 255),
Color(0, 0, 255, 255),
Color(128, 128, 128, 255),
Color(128, 128, 0, 255),
];
let _gradient = Lines::Gradient {
//colors to transition between
colors,
//minimum segments per switch (starts at 2)
segments_per_color: 10,
//whether to bend the lines at corners line in game
bent: true,
};
//the segment option is by far the most complicated
//like the gradient one, it takes in a list of colors to switch between
//however, it also has options for the triangles (pointers/arrows) that demonstrate the switch
//and what to do when you get collisions (two or more lines between the same 2 points)
//for the triangles/arrows there are several options as follows:
//none, simply don't draw any arrows between color switches
let _none = Triangle::None;
//match simply draws an arrow along color switches
//that is the same color as the color it's switching from
//the radius is a percentage of the line width
let _match = Triangle::Match { radius: 0.16 };
//border_match is the same as match above, except it adds an extra
//bordering triangle around (or inside) the matching triangle
//the smaller radius is drawn on top
let _bordered_match = Triangle::BorderMatch {
match_radius: 0.16,
//the border is a marker which
//simply holds the radius and color of the border
border: Marker {
color: Color::WHITE,
radius: 0.25,
},
};
//lastly, there's border_start_match
//this is exactly the same as border_match, except
//it only draws the border around the starting arrow
let _border_start_match = Triangle::BorderStartMatch {
match_radius: 0.16,
border: Marker {
color: Color::WHITE,
radius: 0.25,
},
};
//then, there's the collision options
//there are several variants as follows:
//matched dashes keeps track of the color of each line passing through it
//and draws the colors as a dashed line in place of a solid line
let _matched_dashes = CollisionOption::MatchedDashes;
//this one draws the first line (before collisions)
//and then draws a dash with the provided color over it
let _dashes = CollisionOption::Dashes(Color(255, 0, 0, 255));
//parallel lines just draws the lines parallel to eachother (while shrinking them)
//so that the colliding lines sort of just push eachother to the side
let _parallel_lines = CollisionOption::ParallelLines;
//lastly, there's overloaded parallel lines
//this is an extension to parallel_lines for cases
//where there are so many colliding lines it's hard to read
//it takes in the number of lines before it switches methods (max_line)
//and the alternate method (overload)
//overlaod has 3 options as follows:
//same as _dashes except it's over the parallel lines
let _dashes_overload = OverloadOptions::Dashes(Color(255, 0, 0, 255));
//same as _matched_dashes
let _matched_dashes_overload = OverloadOptions::MatchedDashes;
//this is an extension to _dashes_overload
//it adds a label off to the side that displays how many colliding lines there are
//the label is a Marker that specifies the color and the radius of the label (circular)
let _labeled_dashes_overload = OverloadOptions::LabeledDashes {
color: Color(255, 0, 0, 255),
label: Marker {
color: Color::WHITE,
radius: 0.4,
},
};
//puting that together, you get the overloaded_parallel_lines
let _overloaded_parallel_lines = CollisionOption::OverloadedParallel {
max_line: 10,
overload: _labeled_dashes_overload,
};
let colors = vec![
color,
Color(255, 0, 0, 255),
Color(0, 255, 0, 255),
Color(0, 0, 255, 255),
Color(128, 128, 128, 255),
Color(128, 128, 0, 255),
];
//and then, all of that can be combined to make the SegmentColor options
let _segment = Lines::SegmentColors {
colors,
triangles: _border_start_match,
collisions: _overloaded_parallel_lines,
};
//then, from there, you have intersections
//the intersections are simply points the points
//on the grid of the pattern
//it has three types as follows:
//nothing which is simply no points at the intersections
let _nothing = Intersections::Nothing;
//uniform points simply uses the same point for every intersection
//where a point has the following variants:
//none which is just nothing
let _none = Point::None;
//single which is just a marker specifying the color and radius
let _single_point = Point::Single(Marker {
color: Color::WHITE,
radius: 0.07,
});
//and finally double which has an inner and outer point defined by two markers
let _double_point = Point::Double {
inner: Marker {
color: Color::WHITE,
radius: 0.07,
},
outer: Marker {
color: Color(255, 255, 0, 255),
radius: 0.1,
},
};
//witht those, the UniformPoint intesection can be defined:
let _uniform_points = Intersections::UniformPoints(_single_point);
//lastly, you have EndAndMiddle
//this takes in an EndPoint for the start and end and a Point for the middle
//the EndPoint is just a modified variation of Point
//that doesn't include the inner color as it's provided by the stating/ending color
//the point variant is just a wrapper for a normal Point
//could alternatively be point.into();
let _simple_end_point = EndPoint::Point(_single_point);
//this is equivalent to _single_point except the color is provided
//from whatever the underlying line color is
let _single_end_point = EndPoint::Match { radius: 0.07 };
//same as _double_end_point but with provided color
let _double_end_point = EndPoint::BorderedMatch {
match_radius: 0.1,
border: Marker {
color: Color::WHITE,
radius: 0.1,
},
};
//then combined into the EndsAndMiddle intersection you can get this:
let _end_and_middle_points = Intersections::EndsAndMiddle {
start: _double_end_point,
end: _simple_end_point,
middle: _single_point,
};
//for the last part of the main GridOptions, there's the collision point
//this is simply a point (the same one mentioned above)
//and is automatically placed in the middle if provided
let _collision_point = Point::Single(Marker {
color: Color::WHITE,
radius: 0.1,
});
//then putting it all together:
let _uniform_options = GridOptions {
line_thickness: 0.12,
pattern_options: GridPatternOptions::Uniform(_end_and_middle_points, _segment.clone()),
center_dot: _collision_point,
};
hex_grid
.draw_grid_to_file("uniform_options_example.png", 50.0, &_uniform_options)
.expect("Failed to write to file!");
//for the changing GridPatternOptions, 2 extra parameters are required:
//a set of pattern_sigs to progress to the next pattern option set
//and a set to go to the previous
//here's the setup for intro/retro
//it only takes in a vector of angle_sigs as the
//starting direction is ignored
let _progress_patterns = vec![vec![Angle::Left, Angle::Left, Angle::Left]];
let _regress_patterns = vec![vec![Angle::Right, Angle::Right, Angle::Right]];
//then for the changing options you just list several intersection/line options and the above patterns
let _changing_options = GridOptions {
line_thickness: 0.12,
pattern_options: GridPatternOptions::Changing {
variations: vec![
(_end_and_middle_points, _segment),
(_uniform_points, _gradient),
(_nothing, _monocolor),
],
intros: _progress_patterns,
retros: _regress_patterns,
},
center_dot: _collision_point,
};
hex_grid
.draw_grid_to_file("changing_options_example.png", 50.0, &_changing_options)
.expect("Failed to write to file!");
//since the changing variant probably only needs to switch colors,
//there are some built in functions for that
//however, they set the intro/retro patterns and don't allow configuration of those
//and if you don't want to program in custom palettes, there's options::palettes
//for monocolor, you just give whether it bends and a vector of colors
//it will generate a variant of monocolor for each color provided
let _changing_monocolor =
GridPatternOptions::gen_changing_monocolor(_nothing, palettes::DARK2.to_vec(), true);
//gen_changing_gradient takes in the intersection
//a vector of vector of colors and whether or not it's bent.
//it generated a gradient for each vector of colors given with the bent condition passed down
let _changing_segment = GridPatternOptions::gen_changing_gradient(
_end_and_middle_points,
palettes::ALL.to_vec(),
true,
);
//same as gradient, except it also takes int he triangles/arrows and collision options
//uses the same triangle/collision settings for all variants (only changes line color)
let _changing_gradient = GridPatternOptions::gen_changing_segment(
_end_and_middle_points,
palettes::ALL.to_vec(),
_border_start_match,
_overloaded_parallel_lines,
);
let _generator_options = GridOptions {
line_thickness: 0.12,
pattern_options: _changing_gradient,
center_dot: _single_point,
};
hex_grid
.draw_grid_to_file("generator_options_example.png", 50.0, &_generator_options)
.expect("Failed to write to file!");
//in addition, if you want to use the defaults for some things,
//all the parts to make the defaults are in hex_renderer::options::defaults
}