diff --git a/src/main.rs b/src/main.rs index 681a7cd..5691daa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,7 @@ #![windows_subsystem = "windows"] use crate::{app::App, constants::LOOP_TIME}; -use tracing::{debug, info, warn}; +use tracing::info; mod app; mod asset; @@ -22,19 +22,9 @@ mod texture; /// This function initializes SDL, the window, the game state, and then enters /// the main game loop. pub fn main() { - if platform::requires_console() { - // Setup buffered tracing subscriber that will buffer logs until console is ready - let switchable_writer = platform::tracing_buffer::setup_switchable_subscriber(); - - // Initialize platform-specific console - platform::init_console().expect("Could not initialize console"); - - // Now that console is initialized, flush buffered logs and switch to direct output - debug!("Switching to direct logging mode and flushing buffer..."); - if let Err(error) = switchable_writer.switch_to_direct_mode() { - warn!("Failed to flush buffered logs to console: {error:?}"); - } - } + // On Windows, this connects output streams to the console dynamically + // On Emscripten, this connects the subscriber to the browser console + platform::init_console().expect("Could not initialize console"); let mut app = App::new().expect("Could not create app"); diff --git a/src/platform/desktop.rs b/src/platform/desktop.rs index 35db096..f408bdf 100644 --- a/src/platform/desktop.rs +++ b/src/platform/desktop.rs @@ -20,9 +20,13 @@ pub fn sleep(duration: Duration, focused: bool) { pub fn init_console() -> Result<(), PlatformError> { #[cfg(windows)] { + use crate::platform::tracing_buffer::setup_switchable_subscriber; use tracing::{debug, info}; use windows::Win32::System::Console::GetConsoleWindow; + // Setup buffered tracing subscriber that will buffer logs until console is ready + let switchable_writer = setup_switchable_subscriber(); + // Check if we already have a console window if unsafe { !GetConsoleWindow().0.is_null() } { debug!("Already have a console window"); @@ -40,15 +44,19 @@ pub fn init_console() -> Result<(), PlatformError> { attach_to_parent_console()?; info!("Successfully attached to parent console"); } + + // Now that console is initialized, flush buffered logs and switch to direct output + debug!("Switching to direct logging mode and flushing buffer..."); + if let Err(error) = switchable_writer.switch_to_direct_mode() { + use tracing::warn; + + warn!("Failed to flush buffered logs to console: {error:?}"); + } } Ok(()) } -pub fn requires_console() -> bool { - cfg!(windows) -} - pub fn get_asset_bytes(asset: Asset) -> Result, AssetError> { match asset { Asset::Wav1 => Ok(Cow::Borrowed(include_bytes!("../../assets/game/sound/waka/1.ogg"))), diff --git a/src/platform/emscripten.rs b/src/platform/emscripten.rs index a0e55b1..faf93f1 100644 --- a/src/platform/emscripten.rs +++ b/src/platform/emscripten.rs @@ -1,18 +1,21 @@ //! Emscripten platform implementation. -use std::borrow::Cow; -use std::time::Duration; - use crate::asset::Asset; use crate::error::{AssetError, PlatformError}; use rand::{rngs::SmallRng, SeedableRng}; +use sdl2::rwops::RWops; +use std::borrow::Cow; +use std::ffi::CString; +use std::io::{self, Read, Write}; +use std::time::Duration; // Emscripten FFI functions #[allow(dead_code)] extern "C" { - fn emscripten_get_now() -> f64; fn emscripten_sleep(ms: u32); fn emscripten_get_element_css_size(target: *const u8, width: *mut f64, height: *mut f64) -> i32; + // Standard C functions that Emscripten redirects to console + fn printf(format: *const u8, ...) -> i32; } pub fn sleep(duration: Duration, _focused: bool) { @@ -22,11 +25,44 @@ pub fn sleep(duration: Duration, _focused: bool) { } pub fn init_console() -> Result<(), PlatformError> { - Ok(()) // No-op for Emscripten + use tracing_subscriber::{fmt, layer::SubscriberExt, EnvFilter}; + + // Set up a custom tracing subscriber that writes directly to emscripten console + let subscriber = tracing_subscriber::registry() + .with( + fmt::layer() + .with_writer(|| EmscriptenConsoleWriter) + .with_ansi(false) + .without_time() + .with_target(false), + ) + .with(EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("debug"))); + + tracing::subscriber::set_global_default(subscriber) + .map_err(|e| PlatformError::ConsoleInit(format!("Failed to set tracing subscriber: {}", e)))?; + + Ok(()) } -pub fn requires_console() -> bool { - false +/// A writer that outputs to the browser console via printf (redirected by emscripten) +struct EmscriptenConsoleWriter; + +impl Write for EmscriptenConsoleWriter { + fn write(&mut self, buf: &[u8]) -> io::Result { + if let Ok(s) = std::str::from_utf8(buf) { + if let Ok(cstr) = CString::new(s.trim_end_matches('\n')) { + let format_str = CString::new("%s\n").unwrap(); + unsafe { + printf(format_str.as_ptr().cast(), cstr.as_ptr()); + } + } + } + Ok(buf.len()) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } } #[allow(dead_code)] @@ -44,18 +80,13 @@ pub fn get_canvas_size() -> Option<(u32, u32)> { } pub fn get_asset_bytes(asset: Asset) -> Result, AssetError> { - use sdl2::rwops::RWops; - use std::io::Read; - let path = format!("assets/game/{}", asset.path()); let mut rwops = RWops::from_file(&path, "rb").map_err(|_| AssetError::NotFound(asset.path().to_string()))?; let len = rwops.len().ok_or_else(|| AssetError::NotFound(asset.path().to_string()))?; let mut buf = vec![0u8; len]; - rwops - .read_exact(&mut buf) - .map_err(|e| AssetError::Io(std::io::Error::other(e)))?; + rwops.read_exact(&mut buf).map_err(|e| AssetError::Io(io::Error::other(e)))?; Ok(Cow::Owned(buf)) } diff --git a/src/platform/mod.rs b/src/platform/mod.rs index ac4340f..d0fff45 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -1,10 +1,12 @@ //! Platform abstraction layer for cross-platform functionality. -pub mod buffered_writer; -pub mod tracing_buffer; +#[cfg(not(target_os = "emscripten"))] +pub mod buffered_writer; #[cfg(not(target_os = "emscripten"))] mod desktop; #[cfg(not(target_os = "emscripten"))] +pub mod tracing_buffer; +#[cfg(not(target_os = "emscripten"))] pub use desktop::*; #[cfg(target_os = "emscripten")] diff --git a/src/systems/input.rs b/src/systems/input.rs index 2377ef2..1e9efe1 100644 --- a/src/systems/input.rs +++ b/src/systems/input.rs @@ -293,6 +293,9 @@ pub fn input_system( simple_key_events.push(SimpleKeyEvent::KeyUp(key)); } } + Event::RenderTargetsReset { .. } | Event::Window { .. } => { + // No-op + } _ => { tracing::warn!("Unhandled event, consider disabling: {:?}", event); }