mod account_monitor; mod account_sync; mod app; mod arm; mod config; mod fifa17_capability; mod game_launch; mod health; mod launch; mod local_services; mod logs; mod netcheck; mod preflight; mod setup; mod theme; fn main() -> eframe::Result<()> { let options = eframe::NativeOptions { viewport: egui::ViewportBuilder::default() .with_title("OpenFUT Launcher") .with_app_id("openfut-launcher") .with_icon(app_icon()) .with_inner_size([1040.0, 720.0]) .with_min_inner_size([880.0, 600.0]), ..Default::default() }; eframe::run_native( "OpenFUT Launcher", options, Box::new(|cc| Ok(Box::new(app::LauncherApp::new(cc)))), ) } /// The application / taskbar icon: the same "OF" monogram the header wordmark /// shows, drawn white on the signature accent tile. Generated in code (no PNG /// dependency) at 4x supersampling and box-downsampled to a crisp 64x64 RGBA — /// scales cleanly to the 32x32 the WM typically renders. Colours come from the /// theme palette so the icon never drifts from the in-app brand. fn app_icon() -> egui::IconData { const SIZE: usize = 64; // output edge const SS: usize = 4; // supersampling factor let accent = theme::ACCENT; let fg = theme::ON_ACCENT; // Rounded-square background: point inside the [0,SIZE]² square with corners // rounded to `round_r` (transparent outside, so the icon reads as a tile). let round_r = 13.0_f32; let inside_bg = |x: f32, y: f32| -> bool { let s = SIZE as f32; let cx = x.clamp(round_r, s - round_r); let cy = y.clamp(round_r, s - round_r); let (dx, dy) = (x - cx, y - cy); dx * dx + dy * dy <= round_r * round_r }; // "O" — an elliptical ring on the left. let inside_o = |x: f32, y: f32| -> bool { let (cx, cy) = (21.0_f32, 32.0_f32); let (dx, dy) = (x - cx, y - cy); let outer = (dx / 9.0).powi(2) + (dy / 14.0).powi(2) <= 1.0; let inner = (dx / 4.8).powi(2) + (dy / 9.5).powi(2) < 1.0; outer && !inner }; // "F" — a stem plus a top and middle bar on the right. let inside_f = |x: f32, y: f32| -> bool { let stem = (34.0..=39.0).contains(&x) && (18.0..=46.0).contains(&y); let top = (34.0..=52.0).contains(&x) && (18.0..=23.0).contains(&y); let mid = (34.0..=48.0).contains(&x) && (29.5..=34.0).contains(&y); stem || top || mid }; // Premultiplied-alpha accumulation per output pixel so antialiased edges // (both the rounded tile and the letters) never fringe dark. let mut rgba = vec![0u8; SIZE * SIZE * 4]; for oy in 0..SIZE { for ox in 0..SIZE { let (mut ar, mut ag, mut ab, mut aa) = (0.0_f32, 0.0_f32, 0.0_f32, 0.0_f32); for sy in 0..SS { for sx in 0..SS { let x = ox as f32 + (sx as f32 + 0.5) / SS as f32; let y = oy as f32 + (sy as f32 + 0.5) / SS as f32; let (r, g, b, a) = if inside_o(x, y) || inside_f(x, y) { (fg.r(), fg.g(), fg.b(), 255u16) } else if inside_bg(x, y) { (accent.r(), accent.g(), accent.b(), 255u16) } else { (0, 0, 0, 0) }; let af = a as f32 / 255.0; ar += r as f32 * af; ag += g as f32 * af; ab += b as f32 * af; aa += af; } } let samples = (SS * SS) as f32; let idx = (oy * SIZE + ox) * 4; let (r, g, b) = if aa > 0.0 { (ar / aa, ag / aa, ab / aa) } else { (0.0, 0.0, 0.0) }; rgba[idx] = r.round() as u8; rgba[idx + 1] = g.round() as u8; rgba[idx + 2] = b.round() as u8; rgba[idx + 3] = (aa / samples * 255.0).round() as u8; } } egui::IconData { rgba, width: SIZE as u32, height: SIZE as u32, } }