1//! What is drawn round the cat and not part of it: sound waves, a thought bubble, stars, z's, 2//! hearts, balls, a cloud with a cross, a drop of sweat. Shared by every theme: a theme is the 3//! cat itself, and the weather round it is the app's. 4 5use whiskers_pet::Mood; 6use crate::motion::Motion; 7use crate::node::{Color, Node, moving, r, ra}; 8 9pub const WHITE: Color = Color::hex(0xFFFFFF); 10pub const INK: Color = Color::hex(0x000000); 11const STAR: Color = Color::hex(0xFFD84A); 12const SLEEP_BLUE: Color = Color::hex(0xD6E6FF); 13pub const BLUSH: Color = Color::hex(0xFF8FA3); 14const SWEAT: Color = Color::hex(0x6EC1FF); 15const CROSS: Color = Color::hex(0xFF5A5A); 16 17/// The things round the cat for a standing mood. 18pub fn around(mood: Mood) -> Vec<Node> { 19 match mood { 20 Mood::Listening => { 21 let mut waves = Vec::new(); 22 for (side, x0) in [(-1.0_f32, -1.8_f32), (1.0, 16.8)] { 23 waves.push(moving(Motion::Pulse(0), (0.0, 0.0), vec![r(x0, 8.0, 0.5, 2.0, WHITE)])); 24 waves.push(moving(Motion::Pulse(1), (0.0, 0.0), vec![r(x0 + side * 1.1, 7.0, 0.5, 4.0, WHITE)])); 25 } 26 waves 27 } 28 Mood::Thinking => { 29 let mut out = vec![ 30 ra(10.5, 1.8, 0.8, 0.8, WHITE, 0.9), 31 ra(11.5, 0.0, 1.1, 1.1, WHITE, 0.9), 32 ra(12.0, -3.0, 6.0, 2.2, WHITE, 0.93), 33 ra(13.0, -3.8, 4.0, 3.8, WHITE, 0.93), 34 ]; 35 for i in 0..3_u8 { 36 out.push(moving(Motion::Dot(i), (0.0, 0.0), vec![r(13.2 + f32::from(i) * 1.5, -2.2, 0.8, 0.8, INK)])); 37 } 38 out 39 } 40 Mood::Dizzy => (0..3_u8).map(|k| moving(Motion::Orbit(k), (0.0, 0.0), star(7.5, 2.5))).collect(), 41 Mood::Tickled => (0..2_u8).map(|k| moving(Motion::Heart(k), (0.0, 0.0), heart())).collect(), 42 Mood::Busy => { 43 // Three balls chasing each other over the head along one arc. 44 [STAR, BLUSH, SWEAT] 45 .into_iter() 46 .enumerate() 47 .map(|(k, color)| moving(Motion::Ball(k as u8), (0.0, 0.0), vec![r(-0.7, -0.7, 1.4, 1.4, color)])) 48 .collect() 49 } 50 Mood::Offline => { 51 // A cloud with a cross through it: it cannot reach its thinking cloud. 52 let mut out = vec![ra(11.0, -2.2, 6.0, 2.4, WHITE, 0.93), ra(12.0, -3.2, 4.0, 3.4, WHITE, 0.93)]; 53 for i in 0..4 { 54 let i = i as f32; 55 out.push(r(12.4 + i * 0.9, -2.6 + i * 0.9, 0.9, 0.9, CROSS)); 56 out.push(r(15.1 - i * 0.9, -2.6 + i * 0.9, 0.9, 0.9, CROSS)); 57 } 58 out 59 } 60 Mood::Tangled => vec![moving(Motion::Drip, (0.0, 0.0), vec![r(12.2, 5.5, 0.8, 1.2, SWEAT)])], 61 Mood::Idle | Mood::Speaking | Mood::Working | Mood::Sleeping => Vec::new(), 62 } 63} 64 65/// The z's over a sleeping cat. 66pub fn zs() -> Vec<Node> { 67 (0..3_u8) 68 .map(|k| { 69 // The app draws each at (10, 7) and moves and scales it: about its own corner. 70 moving(Motion::Rise(k), (10.0, 7.0), z(10.0, 7.0)) 71 }) 72 .collect() 73} 74 75fn z(x: f32, y: f32) -> Vec<Node> { 76 vec![ 77 r(x, y, 3.0, 0.6, SLEEP_BLUE), 78 r(x + 1.6, y + 0.6, 0.8, 0.8, SLEEP_BLUE), 79 r(x + 0.6, y + 1.4, 0.8, 0.6, SLEEP_BLUE), 80 r(x, y + 2.0, 3.0, 0.6, SLEEP_BLUE), 81 ] 82} 83 84fn heart() -> Vec<Node> { 85 vec![r(0.0, 0.0, 0.8, 0.8, BLUSH), r(1.6, 0.0, 0.8, 0.8, BLUSH), r(0.0, 0.8, 2.4, 0.8, BLUSH), r(0.8, 1.6, 0.8, 0.8, BLUSH)] 86} 87 88fn star(x: f32, y: f32) -> Vec<Node> { 89 vec![r(x - 0.5, y - 1.5, 1.0, 3.0, STAR), r(x - 1.5, y - 0.5, 3.0, 1.0, STAR)] 90} 91 92/// A 3 by 3 ring of cells with a gap walking round it, centred on (`cx`, `cy`): the dizzy eye. 93pub fn spiral(cx: f32, cy: f32, color: Color) -> Vec<Node> { 94 let ring = [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2), (1, 2), (0, 2), (0, 1)]; 95 let mut out: Vec<Node> = ring 96 .iter() 97 .enumerate() 98 .map(|(i, (dx, dy))| moving(Motion::Gap(i as u8), (0.0, 0.0), vec![r(cx - 1.5 + *dx as f32, cy - 1.5 + *dy as f32, 1.0, 1.0, color)])) 99 .collect(); 100 out.push(r(cx - 0.5, cy - 0.5, 1.0, 1.0, color)); 101 out 102}