12 #[derive(Debug, Clone)] |
12 #[derive(Debug, Clone)] |
13 pub struct EdgeDescription { |
13 pub struct EdgeDescription { |
14 pub name: String, |
14 pub name: String, |
15 pub reversed: Option<bool>, |
15 pub reversed: Option<bool>, |
16 pub symmetrical: Option<bool>, |
16 pub symmetrical: Option<bool>, |
|
17 pub hard_match: Option<bool>, |
17 } |
18 } |
18 |
19 |
19 #[derive(Debug, Clone)] |
20 #[derive(Debug, Clone)] |
20 pub struct EdgesDescription { |
21 pub struct EdgesDescription { |
21 pub top: EdgeDescription, |
22 pub top: EdgeDescription, |
204 ] |
205 ] |
205 .map(|opt| opt.map(|d| [&d.begin, &d.fill, &d.end].map(|e| e.as_ref().map(Into::into)))); |
206 .map(|opt| opt.map(|d| [&d.begin, &d.fill, &d.end].map(|e| e.as_ref().map(Into::into)))); |
206 |
207 |
207 let mut rules = Vec::<CollapseRule>::new(); |
208 let mut rules = Vec::<CollapseRule>::new(); |
208 |
209 |
209 let default_connection = HashSet::from_iter(vec![Tile::Empty].into_iter()); |
|
210 for (i, tile) in tiles.iter().enumerate() { |
210 for (i, tile) in tiles.iter().enumerate() { |
211 let mut right = default_connection.clone(); |
211 let mut top = HashSet::new(); |
212 let mut bottom = default_connection.clone(); |
212 let mut right = HashSet::new(); |
213 let mut left = default_connection.clone(); |
213 let mut bottom = HashSet::new(); |
214 let mut top = default_connection.clone(); |
214 let mut left = HashSet::new(); |
215 |
215 |
216 let iteration = [ |
216 let iteration = [ |
217 (&grid_top_edge, tile.edge_set().top(), &mut top), |
217 (&grid_top_edge, tile.edge_set().top(), &mut top), |
218 (&grid_right_edge, tile.edge_set().right(), &mut right), |
218 (&grid_right_edge, tile.edge_set().right(), &mut right), |
219 (&grid_bottom_edge, tile.edge_set().bottom(), &mut bottom), |
219 (&grid_bottom_edge, tile.edge_set().bottom(), &mut bottom), |
220 (&grid_left_edge, tile.edge_set().left(), &mut left), |
220 (&grid_left_edge, tile.edge_set().left(), &mut left), |
221 ]; |
221 ]; |
222 |
222 |
223 // compatibility with grid edges |
223 // compatibility with grid edges |
224 for (edge, tile_edge, set) in iteration { |
224 for (edge, tile_edge, set) in iteration { |
|
225 if !tile_edge.hard_match() { |
|
226 set.insert(Tile::Empty); |
|
227 } |
|
228 |
225 for (is_compatible, tile) in edge |
229 for (is_compatible, tile) in edge |
226 .as_ref() |
230 .as_ref() |
227 .map(|e| { |
231 .map(|e| { |
228 e.clone().map(|ed| { |
232 e.clone().map(|ed| { |
229 ed.as_ref() |
233 ed.as_ref() |
397 } |
401 } |
398 } |
402 } |
399 |
403 |
400 impl From<&EdgeDescription> for Edge<String> { |
404 impl From<&EdgeDescription> for Edge<String> { |
401 fn from(val: &EdgeDescription) -> Self { |
405 fn from(val: &EdgeDescription) -> Self { |
402 let edge = Edge::new(val.name.clone(), val.symmetrical.unwrap_or_default()); |
406 let edge = Edge::new( |
|
407 val.name.clone(), |
|
408 val.symmetrical.unwrap_or_default(), |
|
409 val.hard_match.unwrap_or_default(), |
|
410 ); |
403 |
411 |
404 if val.reversed.unwrap_or_default() { |
412 if val.reversed.unwrap_or_default() { |
405 edge.reversed() |
413 edge.reversed() |
406 } else { |
414 } else { |
407 edge |
415 edge |
411 |
419 |
412 impl<T: AsRef<str>> From<T> for EdgeDescription { |
420 impl<T: AsRef<str>> From<T> for EdgeDescription { |
413 fn from(val: T) -> Self { |
421 fn from(val: T) -> Self { |
414 use std::cmp::Ordering; |
422 use std::cmp::Ordering; |
415 |
423 |
416 let reversed = val.as_ref().chars().rev().collect::<String>(); |
424 let mut chars = val.as_ref().chars(); |
417 |
425 let hard_match = chars.next() == Some('!'); |
418 match val.as_ref().cmp(&reversed) { |
426 |
|
427 let (name, reversed): (String, String) = if hard_match { |
|
428 (chars.clone().collect(), chars.rev().collect()) |
|
429 } else { |
|
430 ( |
|
431 val.as_ref().chars().collect(), |
|
432 val.as_ref().chars().rev().collect(), |
|
433 ) |
|
434 }; |
|
435 |
|
436 match name.cmp(&reversed) { |
419 Ordering::Less => EdgeDescription { |
437 Ordering::Less => EdgeDescription { |
420 name: val.as_ref().to_owned(), |
438 name, |
421 symmetrical: Some(false), |
439 symmetrical: Some(false), |
422 reversed: Some(false), |
440 reversed: Some(false), |
|
441 hard_match: Some(hard_match), |
423 }, |
442 }, |
424 Ordering::Equal => EdgeDescription { |
443 Ordering::Equal => EdgeDescription { |
425 name: reversed, |
444 name: reversed, |
426 symmetrical: Some(true), |
445 symmetrical: Some(true), |
427 reversed: Some(false), |
446 reversed: Some(false), |
|
447 hard_match: Some(hard_match), |
428 }, |
448 }, |
429 Ordering::Greater => EdgeDescription { |
449 Ordering::Greater => EdgeDescription { |
430 name: reversed, |
450 name: reversed, |
431 symmetrical: Some(false), |
451 symmetrical: Some(false), |
432 reversed: Some(true), |
452 reversed: Some(true), |
|
453 hard_match: Some(hard_match), |
433 }, |
454 }, |
434 } |
455 } |
435 } |
456 } |
436 } |
457 } |