use std::sync::OnceLock;
#[derive(Debug, Clone)]
pub struct GameConfig {
pub game_name: String,
pub project_path: String,
pub fullscreen: bool,
pub fullscreen_fit: bool,
}
pub static GAME_CONFIG: OnceLock<GameConfig> = OnceLock::new();
pub fn init_game_config(game_name: &str, project_path: &str, fullscreen: bool, fullscreen_fit: bool) {
let _ = GAME_CONFIG.set(GameConfig {
game_name: game_name.to_string(),
project_path: project_path.to_string(),
fullscreen,
fullscreen_fit,
});
}
pub fn get_game_config() -> &'static GameConfig {
GAME_CONFIG.get_or_init(|| {
GameConfig {
game_name: String::new(),
project_path: ".".to_string(),
fullscreen: false,
fullscreen_fit: false,
}
})
}
pub static WASM_APP_DATA: OnceLock<String> = OnceLock::new();
pub fn set_wasm_app_data(data: &str) {
let _ = WASM_APP_DATA.set(data.to_string());
}
pub fn get_wasm_app_data() -> Option<&'static str> {
WASM_APP_DATA.get().map(|s| s.as_str())
}
#[derive(Debug, Clone)]
pub struct PixelLayerData {
pub layer_size: u32,
pub layers: Vec<Vec<u8>>,
}
pub static PIXEL_LAYER_DATA: OnceLock<PixelLayerData> = OnceLock::new();
pub fn get_pixel_layer_data() -> Option<&'static PixelLayerData> {
PIXEL_LAYER_DATA.get()
}
#[cfg(all(graphics_mode, not(target_arch = "wasm32")))]
pub fn init_layered_pixel_assets(
game_name: &str,
project_path: &str,
fullscreen: bool,
fullscreen_fit: bool,
) -> Result<(), String> {
use crate::render::adapter::{PIXEL_SYM_HEIGHT, PIXEL_SYM_WIDTH};
use crate::render::symbol_map::init_layered_symbol_map_from_file;
init_game_config(game_name, project_path, fullscreen, fullscreen_fit);
let pix_base = {
let app_pix = format!("{}{}assets/pix", project_path, std::path::MAIN_SEPARATOR);
let app_json = format!("{}/layered_symbol_map.json", app_pix);
if std::path::Path::new(&app_json).exists() {
app_pix
} else {
let root_pix = "assets/pix".to_string();
let root_json = format!("{}/layered_symbol_map.json", root_pix);
if std::path::Path::new(&root_json).exists() {
root_pix
} else {
return Err(format!(
"Cannot find layered_symbol_map.json in '{}' or '{}'",
app_pix, root_pix
));
}
}
};
let json_path = format!("{}/layered_symbol_map.json", pix_base);
init_layered_symbol_map_from_file(&json_path)?;
let lmap = crate::render::symbol_map::get_layered_symbol_map()
.ok_or("Layered symbol map not initialized")?;
let cell_px = lmap.cell_pixel_size as f32;
let _ = PIXEL_SYM_WIDTH.set(cell_px);
let _ = PIXEL_SYM_HEIGHT.set(cell_px);
let layer_size = lmap.layer_size;
let mut layers = Vec::with_capacity(lmap.layer_files.len());
for layer_file in &lmap.layer_files {
let layer_path = format!("{}/{}", pix_base, layer_file);
let img = image::open(&layer_path)
.map_err(|e| format!("Failed to load layer '{}': {}", layer_path, e))?
.to_rgba8();
if img.width() != layer_size || img.height() != layer_size {
return Err(format!(
"Layer {} size {}x{} != expected {}x{}",
layer_file,
img.width(),
img.height(),
layer_size,
layer_size
));
}
layers.push(img.into_raw());
}
let layer_count = layers.len();
PIXEL_LAYER_DATA
.set(PixelLayerData { layer_size, layers })
.map_err(|_| "PIXEL_LAYER_DATA already initialized".to_string())?;
println!(
"Layered pixel assets initialized: {} layers ({}x{}), {} symbols from {}",
layer_count, layer_size, layer_size, lmap.symbol_count(), pix_base
);
Ok(())
}
#[cfg(target_arch = "wasm32")]
pub fn wasm_init_pixel_assets(
game_name: &str,
layer_size: u32,
layer_count: u32,
layer_data: &[u8],
symbol_map_json: &str,
) -> bool {
use crate::render::adapter::{PIXEL_SYM_HEIGHT, PIXEL_SYM_WIDTH};
init_game_config(game_name, ".", true, false);
if let Err(e) = crate::render::symbol_map::init_layered_symbol_map_from_json(symbol_map_json) {
web_sys::console::error_1(&format!("RUST: Failed to init symbol map: {}", e).into());
return false;
}
let lmap = match crate::render::symbol_map::get_layered_symbol_map() {
Some(m) => m,
None => {
web_sys::console::error_1(&"RUST: Layered symbol map not initialized".into());
return false;
}
};
let cell_px = lmap.cell_pixel_size as f32;
web_sys::console::log_1(
&format!(
"RUST: layer_size={}, layer_count={}, cell_pixel_size={}",
layer_size, layer_count, lmap.cell_pixel_size
)
.into(),
);
if PIXEL_SYM_WIDTH.set(cell_px).is_err() {
web_sys::console::warn_1(&"PIXEL_SYM_WIDTH already initialized".into());
}
if PIXEL_SYM_HEIGHT.set(cell_px).is_err() {
web_sys::console::warn_1(&"PIXEL_SYM_HEIGHT already initialized".into());
}
let bytes_per_layer = (layer_size * layer_size * 4) as usize;
let mut layers = Vec::with_capacity(layer_count as usize);
for i in 0..layer_count as usize {
let start = i * bytes_per_layer;
let end = start + bytes_per_layer;
if end > layer_data.len() {
web_sys::console::error_1(&format!("RUST: Layer data too short for layer {}", i).into());
return false;
}
layers.push(layer_data[start..end].to_vec());
}
if PIXEL_LAYER_DATA
.set(PixelLayerData { layer_size, layers })
.is_err()
{
web_sys::console::warn_1(&"PIXEL_LAYER_DATA already initialized".into());
}
web_sys::console::log_1(
&format!(
"RUST: Layered pixel assets initialized: {} layers ({}x{}), {} symbols",
layer_count, layer_size, layer_size, lmap.symbol_count()
)
.into(),
);
true
}