From ea5db5846bc700f0da912225ddcb4be372359044 Mon Sep 17 00:00:00 2001 From: Mica White Date: Mon, 7 Oct 2024 20:45:14 -0400 Subject: Finish basic windowing stuff --- Cargo.toml | 3 +- console/Cargo.toml | 4 +-- console/src/lib.rs | 58 ++++++++++++++++--------------------- game.json | 2 +- profiler/src/lib.rs | 13 +++------ scripts/Cargo.toml | 2 +- scripts/src/wasm.rs | 2 +- src/main.rs | 82 +++++++++++++++++++++++++++++++++++++++-------------- sys/src/lib.rs | 2 +- sys/src/renderer.rs | 12 ++++---- 10 files changed, 101 insertions(+), 79 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 49cf229..0616f91 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,10 +16,11 @@ alligator_scripts = { path = "scripts" } alligator_sprites = { path = "sprites" } alligator_sys = { path = "sys" } -clap = "4" +clap = { version = "4", features=["derive"] } serde = "1" serde_json = "1" pollster = "0.3" +log = "0.4" sha3 = "0.10" [profile.release] diff --git a/console/Cargo.toml b/console/Cargo.toml index 0d23054..18ea28d 100644 --- a/console/Cargo.toml +++ b/console/Cargo.toml @@ -6,6 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -smol = "2" -log = "0.4" -pollster = "0.3" \ No newline at end of file +log = "0.4" \ No newline at end of file diff --git a/console/src/lib.rs b/console/src/lib.rs index d98183c..578d255 100644 --- a/console/src/lib.rs +++ b/console/src/lib.rs @@ -1,13 +1,9 @@ -use std::net::Ipv6Addr; +use std::io::{stdout, Write}; +use std::sync::mpsc::{Receiver, Sender}; use log::Level; -use pollster::FutureExt; -use smol::channel::{Receiver, Sender}; -use smol::io::AsyncWriteExt; -use smol::net::{TcpListener, TcpStream}; pub struct Console { - tcp_socket: TcpStream, messages: Receiver, sender: Sender, } @@ -41,11 +37,8 @@ pub enum ConsoleMessage { impl Console { pub async fn new(port: u16) -> Result { - let tcp_listener = TcpListener::bind((Ipv6Addr::LOCALHOST, port)).await?; - let tcp_socket = tcp_listener.accept().await?.0; - let (sender, reciever) = smol::channel::unbounded(); + let (sender, reciever) = std::sync::mpsc::channel(); Ok(Self { - tcp_socket, messages: reciever, sender, }) @@ -59,9 +52,11 @@ impl Console { ConsoleLogger(self.sender()) } - pub async fn flush(&mut self) -> std::io::Result<()> { + pub fn flush(&self) -> std::io::Result<()> { + let mut stdout = stdout().lock(); + while let Ok(message) = self.messages.try_recv() { - match message { + let message = match message { ConsoleMessage::RuntimeLog { message, level, @@ -69,8 +64,7 @@ impl Console { line, } => { let message = message.replace('\n', "\\n"); - let msg = format!("runtimelog {level} {file}:{line} {message}\n"); - self.tcp_socket.write(msg.as_bytes()).await?; + format!("runtimelog {level} {file}:{line} {message}\n") } ConsoleMessage::ScriptLog { message, @@ -79,32 +73,31 @@ impl Console { line, } => { let message = message.replace('\n', "\\n"); - let msg = format!("scriptlog {level} {file}:{line} {message}\n"); - self.tcp_socket.write(msg.as_bytes()).await?; + format!("scriptlog {level} {file}:{line} {message}\n") } ConsoleMessage::FrameTime { timestamp: unix_timestamp, } => { - let msg = format!("frametime {unix_timestamp}"); - self.tcp_socket.write(msg.as_bytes()).await?; + format!("frametime {unix_timestamp}") } ConsoleMessage::ScopeStart { scope_name, timestamp: unix_timestamp, } => { - let msg = format!("scopestart {scope_name} {unix_timestamp}"); - self.tcp_socket.write(msg.as_bytes()).await?; + format!("scopestart {scope_name} {unix_timestamp}") } ConsoleMessage::ScopeEnd { timestamp: unix_timestamp, } => { - let msg = format!("scopeend {unix_timestamp}"); - self.tcp_socket.write(msg.as_bytes()).await?; + format!("scopeend {unix_timestamp}") } - } + }; + + stdout.write_all(message.as_bytes())?; + stdout.write_all(b"\n")?; } - self.tcp_socket.flush().await?; + stdout.flush()?; Ok(()) } @@ -112,7 +105,7 @@ impl Console { impl ConsoleLogger { pub fn send(&self, message: ConsoleMessage) { - _ = self.0.send(message).block_on(); + _ = self.0.send(message); } } @@ -122,15 +115,12 @@ impl log::Log for ConsoleLogger { } fn log(&self, record: &log::Record) { - let _ = self - .0 - .send(ConsoleMessage::RuntimeLog { - message: record.args().to_string(), - level: record.level(), - file: record.file().map(str::to_string).unwrap_or_default(), - line: record.line().unwrap_or_default(), - }) - .block_on(); + let _ = self.0.send(ConsoleMessage::RuntimeLog { + message: record.args().to_string(), + level: record.level(), + file: record.file().map(str::to_string).unwrap_or_default(), + line: record.line().unwrap_or_default(), + }); } fn flush(&self) {} diff --git a/game.json b/game.json index 479c8f1..cef0474 100644 --- a/game.json +++ b/game.json @@ -1,5 +1,5 @@ { - "alligator_version": 0, + "alligator_version": "0.1", "scenes": { "black": { "initial_sprites": {}, diff --git a/profiler/src/lib.rs b/profiler/src/lib.rs index d23ad24..1a9558d 100644 --- a/profiler/src/lib.rs +++ b/profiler/src/lib.rs @@ -8,15 +8,11 @@ static GLOBAL_PROFILER: OnceLock = OnceLock::new(); struct Profiler { logger: ConsoleLogger, - start_time: DateTime, } impl Profiler { fn new(logger: ConsoleLogger) -> Self { - Self { - logger, - start_time: Utc::now(), - } + Self { logger } } fn current_timestamp(&self) -> i64 { @@ -51,18 +47,17 @@ pub fn set_profiler(logger: ConsoleLogger) { } pub fn finish_frame() { - GLOBAL_PROFILER.get().unwrap().finish_frame(); + GLOBAL_PROFILER.get().inspect(|p| p.finish_frame()); } pub fn start_scope(scope_name: impl AsRef) { GLOBAL_PROFILER .get() - .unwrap() - .start_scope(scope_name.as_ref().to_string()); + .inspect(|p| p.start_scope(scope_name.as_ref().to_string())); } pub fn end_scope() { - GLOBAL_PROFILER.get().unwrap().end_scope(); + GLOBAL_PROFILER.get().inspect(|p| p.end_scope()); } pub fn profile_scope(scope_name: impl AsRef) -> ScopeGuard<(), impl FnOnce(())> { diff --git a/scripts/Cargo.toml b/scripts/Cargo.toml index a9fe5e4..8854678 100644 --- a/scripts/Cargo.toml +++ b/scripts/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -wasmtime = "15" +wasmtime = "24" rayon = "1" thiserror = "1" rand = "0.8" diff --git a/scripts/src/wasm.rs b/scripts/src/wasm.rs index 06d840f..7f8f0b5 100644 --- a/scripts/src/wasm.rs +++ b/scripts/src/wasm.rs @@ -72,7 +72,7 @@ fn validate_module(module: &Module) -> Result<(), InvalidWasmScript> { let Some(heap_base) = export.global() else { return Err(InvalidWasmScript::HeapBaseIsNotGlobal); }; - if *heap_base.content() != ValType::I32 { + if heap_base.content().matches(&ValType::I32) { return Err(InvalidWasmScript::HeapBaseMustBeI32); } if heap_base.mutability() != Mutability::Const { diff --git a/src/main.rs b/src/main.rs index c8d4618..100cfea 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,6 +10,7 @@ use alligator_scripts::ScriptManager; use alligator_sprites::SpriteManager; use alligator_sys::{Renderer, RendererConfig, Window, WindowConfig, WindowEvent}; +use clap::Parser; use pollster::FutureExt; use serde::Deserialize; use sha3::{Digest, Sha3_256}; @@ -67,6 +68,19 @@ pub struct Config { vsync: bool, } +#[derive(Debug, Clone, Parser)] +#[command(version, about, long_about = None)] +pub struct CommandLineArguments { + /// The configuration, represented as a JSON object. If not specified, + /// this is retrieved from the game.json in the executable's directory. + #[arg(short, long)] + config: Option>, + + /// Send and receive console commands through the stdio + #[arg(short, long)] + debug: bool, +} + fn sprite_manager(config: &Config) -> SpriteManager { SpriteManager::with_capacity(config.sprite_manager_capacity as usize) } @@ -98,10 +112,11 @@ fn script_manager(config: &Config) -> ScriptManager { fn window(config: &Config) -> Window { let config = WindowConfig { title: config.window_title.clone(), - default_width: config.default_window_width.get(), - default_height: config.default_window_height.get(), - default_x: 100, - default_y: 100, + // TODO set window size properly + default_width: config.default_window_width.unwrap().get(), + default_height: config.default_window_height.unwrap().get(), + default_x: 200, + default_y: 200, borderless_fullscreen: config.default_window_mode == ConfigWindowMode::BorderlessFullscreen, visible: false, }; @@ -111,8 +126,9 @@ fn window(config: &Config) -> Window { fn renderer(config: &Config, window: &Window) -> Renderer { let config = RendererConfig { - width: config.default_window_width.get(), - height: config.default_window_height.get(), + // TODO set window size properly + width: config.default_window_width.unwrap().get(), + height: config.default_window_height.unwrap().get(), instance_capacity: config.sprite_manager_capacity, fullscreen: false, vsync: config.vsync, @@ -122,14 +138,30 @@ fn renderer(config: &Config, window: &Window) -> Renderer { } fn main() { - let console = Console::new(26009) - .block_on() - .expect("The console should not fail to start"); - profile::set_profiler(console.logger()); + let args = CommandLineArguments::parse(); + + let console = if args.debug { + let console = Console::new(26009) + .block_on() + .expect("The console should not fail to start"); + log::set_logger(Box::leak(Box::new(console.logger()))) + .expect("this should be the only logger"); + profile::set_profiler(console.logger()); + + Some(console) + } else { + None + }; - std::env::set_current_dir(std::env::current_exe().unwrap().parent().unwrap()).unwrap(); - let config = File::open("game.json").unwrap(); - let config: Config = serde_json::from_reader(config).unwrap(); + //std::env::set_current_dir(std::env::current_exe().unwrap().parent().unwrap()).unwrap(); + + let config = match args.config { + Some(config) => serde_json::from_str(&config).unwrap(), + None => { + let config = File::open("game.json").unwrap(); + serde_json::from_reader(config).unwrap() + } + }; let sprites = sprite_manager(&config); let scripts = script_manager(&config); @@ -140,15 +172,21 @@ fn main() { let mut renderer = renderer(&config, &window); window.set_visible(true); - window.run(move |window, event| match event { - Some(WindowEvent::RedrawRequest) => { - renderer.render_frame(); - profile::finish_frame(); - } - Some(WindowEvent::CloseRequest) => { - std::process::exit(0); + window.run(move |window, event| { + match event { + Some(WindowEvent::RedrawRequest) => { + renderer.render_frame(); + profile::finish_frame(); + } + Some(WindowEvent::CloseRequest) => { + std::process::exit(0); + } + Some(_) => (), + None => window.request_redraw(), + }; + + if let Some(c) = &console { + c.flush().expect("why would this error?"); } - Some(_) => (), - None => window.request_redraw(), }) } diff --git a/sys/src/lib.rs b/sys/src/lib.rs index f3fae9c..ddce186 100644 --- a/sys/src/lib.rs +++ b/sys/src/lib.rs @@ -64,7 +64,7 @@ extern "C" { fn new_renderer(config: RendererConfig, window: CWindow) -> CRenderer; fn resize_renderer(renderer: CRenderer, width: c_uint, height: c_uint); fn set_vsync(renderer: CRenderer, vsync: bool); - fn create_vertex_buffer(renderer: CRenderer, count: c_uint, instances: *const Vertex); + //fn create_vertex_buffer(renderer: CRenderer, count: c_uint, instances: *const Vertex); fn set_camera( renderer: CRenderer, x: f32, diff --git a/sys/src/renderer.rs b/sys/src/renderer.rs index a4dab20..31431ea 100644 --- a/sys/src/renderer.rs +++ b/sys/src/renderer.rs @@ -24,12 +24,12 @@ impl Renderer { unsafe { crate::set_vsync(self.ptr, vsync) } } - pub fn create_vertex_buffer(&mut self, vertices: &[Vertex]) { - assert!(vertices.len() < (u32::MAX as usize), "Too many triangles!"); - let ptr = vertices.as_ptr(); - let len = vertices.len(); - unsafe { crate::create_vertex_buffer(self.ptr, len as u32, ptr) } - } + //pub fn create_vertex_buffer(&mut self, vertices: &[Vertex]) { + // assert!(vertices.len() < (u32::MAX as usize), "Too many triangles!"); + // let ptr = vertices.as_ptr(); + // let len = vertices.len(); + // unsafe { crate::create_vertex_buffer(self.ptr, len as u32, ptr) } + //} pub fn set_camera( &mut self, -- cgit v1.2.3