diff --git a/Cargo.lock b/Cargo.lock index 9aa842b..6dbe10f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,12 +1,12 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "bitflags" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" [[package]] name = "core" @@ -38,6 +38,12 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.169" @@ -101,6 +107,24 @@ version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" +[[package]] +name = "sdl3" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f43489df3f10ba4e6682ac57203f0f3e1f85e51936ccf5bf8b3276d585c42f" +dependencies = [ + "bitflags", + "lazy_static", + "libc", + "sdl3-sys", +] + +[[package]] +name = "sdl3-sys" +version = "0.4.3+SDL3-3.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb7ecf5e5f416b2e6408ebe1825ded6bdcac3b8c79e429aada3c79efc675e80d" + [[package]] name = "serde" version = "1.0.217" @@ -214,6 +238,14 @@ version = "0.1.0" dependencies = [ "core", "simplelog", + "uitlk", +] + +[[package]] +name = "uitlk" +version = "0.1.0" +dependencies = [ + "sdl3", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index a48ffd7..eb66f67 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,4 +6,4 @@ # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [workspace] -members = ["core", "ui"] \ No newline at end of file +members = ["core", "ui", "uitlk"] \ No newline at end of file diff --git a/ui/Cargo.toml b/ui/Cargo.toml index 5450c55..41f6e02 100644 --- a/ui/Cargo.toml +++ b/ui/Cargo.toml @@ -7,4 +7,5 @@ edition = "2021" [dependencies] core = { path = "../core" } +uitlk = { path = "../uitlk" } simplelog = { version = "^0.12.0", features = ["paris"] } \ No newline at end of file diff --git a/ui/src/main.rs b/ui/src/main.rs index 6590dd5..6a32f14 100644 --- a/ui/src/main.rs +++ b/ui/src/main.rs @@ -4,6 +4,7 @@ use simplelog::*; use std::fs::File; use std::thread::sleep; use std::time::Duration; +use uitlk::UIWindow; const ROM_PATH: &'static str = "./roms/dk.nes"; @@ -23,13 +24,19 @@ fn main() { ]) .unwrap(); - let mut system = System::new(); - system.insert_rom(ROM_PATH).expect("Failed to insert ROM"); + let mut window = UIWindow::new("NesRust", 800, 600, 60); + // let mut system = System::new(); + // system.insert_rom(ROM_PATH).expect("Failed to insert ROM"); loop { - system.cycle(); + // system.cycle(); + if window.poll_events() { + break; + } - // TODO: Inaccurate, ~60hz - sleep(Duration::from_millis(16)); + // TODO: System loop + + window.render(); + window.wait(); } } diff --git a/uitlk/Cargo.toml b/uitlk/Cargo.toml new file mode 100644 index 0000000..7e132ef --- /dev/null +++ b/uitlk/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "uitlk" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +sdl3 = "0.14.3" \ No newline at end of file diff --git a/uitlk/src/lib.rs b/uitlk/src/lib.rs new file mode 100644 index 0000000..700083b --- /dev/null +++ b/uitlk/src/lib.rs @@ -0,0 +1,96 @@ +mod menu; + +use sdl3::event::Event; +use sdl3::keyboard::Keycode; +use sdl3::pixels::{Color, PixelFormat, PixelMasks}; +use sdl3::rect::Rect; +use sdl3::render::{FRect, WindowCanvas}; +use sdl3::surface::Surface; +use sdl3::sys::pixels::{SDL_PixelFormat, SDL_PIXELFORMAT_ARGB8888}; +use sdl3::EventPump; +use std::time::Duration; + +pub struct UIWindow { + title: &'static str, + width: u32, + height: u32, + refresh_rate: u32, + canvas: WindowCanvas, + event_pump: EventPump, +} + +impl UIWindow { + pub fn new(title: &'static str, width: u32, height: u32, refresh_rate: u32) -> Self { + let sdl_context = sdl3::init().unwrap(); + let video_subsystem = sdl_context.video().unwrap(); + + let window = video_subsystem + .window(title, width, height) + .position_centered() + .build() + .unwrap(); + + let canvas = window.into_canvas(); + let event_pump = sdl_context.event_pump().unwrap(); + + Self { + title, + width, + height, + refresh_rate, + canvas, + event_pump, + } + } + + pub fn render(&mut self) { + self.canvas.set_draw_color(Color::RGB(0, 0, 0)); + self.canvas.clear(); + + let texture_creator = self.canvas.texture_creator(); + let mut texture = texture_creator + .create_texture_static( + PixelFormat::from_masks(PixelMasks { + bpp: 32, + amask: 0x16, + bmask: 0x36, + gmask: 0x20, + rmask: 0x04, + }), + 1, + 1, + ) + .unwrap(); + let color_buffer = vec![0xff, 0x35, 0x35, 0x35]; + texture.update(None, &color_buffer, 4).unwrap(); + + self.canvas.copy(&texture, None, Rect::new(10, 10, 50, 50)).unwrap(); + + self.canvas.present(); + } + + /// Poll and processes events. + /// + /// # Returns + /// `true` if there was a "Quit" event (meaning the user want to close the window) + pub fn poll_events(&mut self) -> bool { + for event in self.event_pump.poll_iter() { + match event { + Event::Quit { .. } + | Event::KeyDown { + keycode: Some(Keycode::Escape), + .. + } => return true, + _ => {} + } + } + + false + } + + pub fn wait(&self) { + ::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / self.refresh_rate)); + } +} + +pub trait UIComponent {} diff --git a/uitlk/src/menu.rs b/uitlk/src/menu.rs new file mode 100644 index 0000000..b22cb20 --- /dev/null +++ b/uitlk/src/menu.rs @@ -0,0 +1,11 @@ +use sdl3::rect::Rect; + +struct UIMenu { + +} + +impl UIMenu { + fn test() { + let rect = Rect::new(50, 50, 100, 100); + } +} \ No newline at end of file diff --git a/uitlk/structure.plantuml b/uitlk/structure.plantuml new file mode 100644 index 0000000..f77ec85 --- /dev/null +++ b/uitlk/structure.plantuml @@ -0,0 +1,16 @@ +@startuml UIToolkit + +abstract class UIComponent +class UIPanelComponent +class UITextComponent +class UIButtonComponent + +UITextComponent --|> UIComponent + +UIButtonComponent --|> UIComponent +UIButtonComponent --> UITextComponent : "text" + +UIPanelComponent --|> UIComponent +UIPanelComponent --> UIComponent : "children" + +@enduml \ No newline at end of file