diff --git a/src/main.rs b/src/main.rs index 4198e58..1741b35 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ pub mod convert; pub mod pattern; +pub mod transform; mod error; mod printer; @@ -17,6 +18,7 @@ pub use vec::*; use crate::convert::*; use crate::pattern::*; +use crate::transform::*; use clap::{Parser, ValueEnum}; use crossterm::style::Color; use crossterm::style::Color::*; @@ -43,6 +45,8 @@ struct Args { colors: Vec, #[clap(long, value_enum)] color_pattern: Vec, + #[clap(long)] + color_shift: Option, } #[derive(ValueEnum, Clone)] @@ -81,13 +85,100 @@ enum PatternEnum { Wheel, } +#[derive(derive_more::Constructor)] +struct PatternConfig<'a> { + patterns: &'a Vec, + shift: Option, +} + +impl Args { + fn char_config(&self) -> PatternConfig { + PatternConfig::new(&self.char_pattern, Some(true)) + } + + fn color_config(&self) -> PatternConfig { + PatternConfig::new(&self.color_pattern, self.color_shift) + } + + fn pallet(&self, rand: &mut impl Rng) -> Vec { + match choose(&self.colors, rand) { + PalletEnum::Red => vec![DarkRed, Red, White], + PalletEnum::Yellow => vec![DarkYellow, Yellow, White], + PalletEnum::Green => vec![DarkGreen, Green, White], + PalletEnum::Blue => vec![DarkBlue, Blue, White], + PalletEnum::Magenta => vec![DarkMagenta, Magenta, White], + PalletEnum::Cyan => vec![DarkCyan, Cyan, White], + PalletEnum::Rainbow => vec![Red, Yellow, Green, Blue, Cyan, Magenta], + + PalletEnum::DarkRed => vec![Black, DarkRed, Red], + PalletEnum::DarkYellow => vec![Black, DarkYellow, Yellow], + PalletEnum::DarkGreen => vec![Black, DarkGreen, Green], + PalletEnum::DarkBlue => vec![Black, DarkBlue, Blue], + PalletEnum::DarkMagenta => vec![Black, DarkMagenta, Magenta], + PalletEnum::DarkCyan => vec![Black, DarkCyan, Cyan], + PalletEnum::DarkRainbow => vec![ + DarkRed, + DarkYellow, + DarkGreen, + DarkBlue, + DarkCyan, + DarkMagenta, + ], + + PalletEnum::RedYellow => vec![Red, DarkRed, DarkYellow, Yellow], + PalletEnum::YellowGreen => vec![Yellow, DarkYellow, DarkGreen, Green], + PalletEnum::GreenBlue => vec![Green, DarkGreen, DarkBlue, Blue], + PalletEnum::BlueCyan => vec![Blue, DarkBlue, DarkCyan, Cyan], + PalletEnum::CyanMagenta => vec![Cyan, DarkCyan, DarkMagenta, Magenta], + PalletEnum::MagentaRed => vec![Magenta, DarkMagenta, DarkRed, Red], + + PalletEnum::Gray => vec![Black, DarkGrey, Grey, White], + } + } +} + +impl<'a> PatternConfig<'a> { + fn create_base(&self, rand: &mut impl Rng) -> Box { + match choose(self.patterns, rand) { + PatternEnum::Circle => Box::new(CircleFactory::default()), + PatternEnum::Line => Box::new(LineFactory::default()), + PatternEnum::Rhombus => Box::new(RhombusFactory::default()), + PatternEnum::Wheel => Box::new(WheelFactory::default()), + } + } + + fn create(&self, rand: &mut impl Rng) -> Box { + let mut pattern = self.create_base(rand); + + if self.shift.unwrap_or(rand.gen()) { + pattern = Box::new(ShiftFactory::new(pattern)) + } + pattern + } +} + +fn choose( + options: &Vec, + rand: &mut TRand, +) -> TValue { + if options.is_empty() { + TValue::value_variants() + .iter() + .choose(rand) + .unwrap() + .clone() + } else { + options.iter().choose(rand).unwrap().clone() + } +} + fn main() -> Result<(), Error> { let args = Args::parse(); let rand = &mut thread_rng(); - let char: Box = create_pattern(choose(args.char_pattern, rand)); - let color: Box = create_pattern(choose(args.color_pattern, rand)); - let pallet = create_pallet(choose(args.colors, rand)); + let char = args.char_config().create(rand); + let color = args.color_config().create(rand); + let pallet = args.pallet(rand); let sampler = SamplerFactoryImpl::new(char, color); let char_converter = CharConverterImpl::new(args.chars); @@ -104,60 +195,3 @@ fn main() -> Result<(), Error> { timer.run(renderer) } - -fn choose(options: Vec, rand: &mut TRand) -> TValue { - if options.is_empty() { - TValue::value_variants() - .iter() - .choose(rand) - .unwrap() - .clone() - } else { - options.iter().choose(rand).unwrap().clone() - } -} - -fn create_pattern(pattern: PatternEnum) -> Box { - match pattern { - PatternEnum::Circle => Box::new(CircleFactory::default()), - PatternEnum::Line => Box::new(LineFactory::default()), - PatternEnum::Rhombus => Box::new(RhombusFactory::default()), - PatternEnum::Wheel => Box::new(WheelFactory::default()), - } -} - -fn create_pallet(colors: PalletEnum) -> Vec { - match colors { - PalletEnum::Red => vec![DarkRed, Red, White], - PalletEnum::Yellow => vec![DarkYellow, Yellow, White], - PalletEnum::Green => vec![DarkGreen, Green, White], - PalletEnum::Blue => vec![DarkBlue, Blue, White], - PalletEnum::Magenta => vec![DarkMagenta, Magenta, White], - PalletEnum::Cyan => vec![DarkCyan, Cyan, White], - PalletEnum::Rainbow => vec![Red, Yellow, Green, Blue, Cyan, Magenta], - - PalletEnum::DarkRed => vec![Black, DarkRed, Red], - PalletEnum::DarkYellow => vec![Black, DarkYellow, Yellow], - PalletEnum::DarkGreen => vec![Black, DarkGreen, Green], - PalletEnum::DarkBlue => vec![Black, DarkBlue, Blue], - PalletEnum::DarkMagenta => vec![Black, DarkMagenta, Magenta], - PalletEnum::DarkCyan => vec![Black, DarkCyan, Cyan], - PalletEnum::DarkRainbow => vec![ - DarkRed, - DarkYellow, - DarkGreen, - DarkBlue, - DarkCyan, - DarkMagenta, - ], - - PalletEnum::RedYellow => vec![Red, DarkRed, DarkYellow, Yellow], - PalletEnum::YellowGreen => vec![Yellow, DarkYellow, DarkGreen, Green], - PalletEnum::GreenBlue => vec![Green, DarkGreen, DarkBlue, Blue], - PalletEnum::BlueCyan => vec![Blue, DarkBlue, DarkCyan, Cyan], - PalletEnum::CyanMagenta => vec![Cyan, DarkCyan, DarkMagenta, Magenta], - PalletEnum::MagentaRed => vec![Magenta, DarkMagenta, DarkRed, Red], - - PalletEnum::Gray => vec![Black, DarkGrey, Grey, White], - } -} diff --git a/src/transform/mod.rs b/src/transform/mod.rs new file mode 100644 index 0000000..daebe43 --- /dev/null +++ b/src/transform/mod.rs @@ -0,0 +1,3 @@ +mod shift; + +pub use shift::*; \ No newline at end of file diff --git a/src/transform/shift.rs b/src/transform/shift.rs new file mode 100644 index 0000000..8027ab8 --- /dev/null +++ b/src/transform/shift.rs @@ -0,0 +1,25 @@ +use crate::pattern::*; +use crate::Vector; + +#[derive(derive_more::Constructor)] +pub struct ShiftFactory { + child: Box, +} + +#[derive(derive_more::Constructor)] +pub struct Shift { + child: Box, + shift: f32, +} + +impl PatternFactory for ShiftFactory { + fn create(&self, config: &Config) -> Box { + Box::new(Shift::new(self.child.create(config), config.step)) + } +} + +impl Pattern for Shift { + fn sample(&self, pos: Vector) -> f32 { + self.child.sample(pos) + 1.0 - 2.0 * self.shift + } +}