launcher/pages/snowboards/
mod.rs1use std::collections::HashMap;
2
3use crate::utils::texture_loader::load_texture_robust;
4use crate::widgets::gallery::{GalleryConfig, GalleryState, gallery_grid};
5use crate::widgets::tile::gallery_tile;
6use supreme_boards::BoardConfig;
7
8mod popup;
9use popup::show_board_config_popup;
10
11#[derive(Default)]
12pub struct SnowboardsPageState {
13 pub gallery: GalleryState,
14 pub board_configs: HashMap<String, BoardConfig>,
15
16 is_initialized: bool,
18 init_error: Option<String>,
19}
20
21pub fn snowboards_page(
22 ui: &mut egui::Ui,
23 storage: &supreme_fs::GameStorage,
24 state: &mut SnowboardsPageState,
25) {
26 if !state.is_initialized {
30 state.is_initialized = true;
31 let game_path = storage.game_path();
32 let boards_dir = game_path.join("Data/Boards");
33
34 if let Err(e) = supreme_boards::generate_all_boards_files(&boards_dir, game_path) {
37 state.init_error = Some(format!("Failed to generate board files: {e}"));
38 }
39 }
40
41 if let Some(err) = state.init_error.clone() {
45 ui.centered_and_justified(|ui| {
46 ui.vertical_centered(|ui| {
47 ui.colored_label(egui::Color32::RED, &err);
48 ui.add_space(8.0);
49 if ui.button("Retry").clicked() {
50 state.is_initialized = false;
51 state.init_error = None;
52 }
53 });
54 });
55 return;
56 }
57
58 let game_path = storage.game_path();
62 let boards_dir = game_path.join("Data/Boards");
63
64 if !boards_dir.exists() {
65 ui.colored_label(egui::Color32::RED, "Boards directory not found!");
66 return;
67 }
68
69 let board_dirs = supreme_boards::get_valid_board_directories(&boards_dir);
70 let available_boards = supreme_boards::get_available_boards(game_path);
71
72 gallery_grid(
73 ui,
74 GalleryConfig {
75 id: "snowboards_grid",
76 title: "Snowboards",
77 info_text: Some(
78 "To create a new snowboard: duplicate an original board folder, then edit the texture files. Ensure the .txt files inside are edited to match the new directory you created.",
79 ),
80 open_folder_path: Some(&boards_dir),
81 },
82 &mut state.gallery,
83 &board_dirs,
84 |_| {},
85 |ui, board_dir, tile_size, gallery_state| {
86 if let Some(board_name) = board_dir.file_name().and_then(|n| n.to_str()) {
87 let mut is_available = available_boards.contains(board_name);
88
89 let texture_key = board_name.to_string();
91 if !gallery_state.textures.contains_key(&texture_key)
92 && let Some(texture_path) = supreme_boards::get_board_texture_path(board_dir)
93 {
94 let full_texture_path = game_path.join(&texture_path);
95 if let Ok(texture) =
96 load_texture_robust(ui.ctx(), &full_texture_path, &texture_key)
97 {
98 gallery_state.textures.insert(texture_key.clone(), texture);
99 }
100 }
101
102 let response = gallery_tile(
103 ui,
104 tile_size,
105 2.0,
106 board_name,
107 |ui| {
108 ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
109 let response = ui.checkbox(&mut is_available, "");
110 if response.changed()
111 && let Err(e) = supreme_boards::set_board_available(
112 game_path,
113 board_name,
114 is_available,
115 )
116 {
117 eprintln!("Error updating availability: {e}");
118 }
119 });
120 },
121 gallery_state.textures.get(&texture_key),
122 );
123
124 if response.clicked() {
125 gallery_state.selected_item = Some(board_dir.clone());
126
127 if !state.board_configs.contains_key(board_name) {
129 let config_path = board_dir.join("menu_board_cnf.txt");
130 if let Ok(config) = supreme_boards::parse_board_config(&config_path) {
131 state.board_configs.insert(board_name.to_string(), config);
132 }
133 }
134 }
135 }
136 },
137 );
138
139 if let Some(selected_board_path) = state.gallery.selected_item.clone() {
141 show_board_config_popup(ui.ctx(), &selected_board_path, game_path, state);
142 }
143}