diff --git a/crates/core/src/play/mod.rs b/crates/core/src/play/mod.rs index 321cc1b..8bd1698 100644 --- a/crates/core/src/play/mod.rs +++ b/crates/core/src/play/mod.rs @@ -17,7 +17,9 @@ use crate::{ use btreemultimap::{BTreeMultiMap, MultiRange}; use std::collections::HashSet; -#[derive(Debug, Default, Clone)] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen::prelude::wasm_bindgen)] +#[derive(Debug, Default, Clone, Copy)] +#[repr(C)] pub struct JudgementReport { pub amazings: u32, pub perfects: u32, @@ -28,9 +30,9 @@ pub struct JudgementReport { } pub struct Play { - field: Field, - state: S, - settings: Settings, + pub field: Field, + pub state: S, + pub settings: Settings, } impl Play { @@ -51,6 +53,13 @@ pub struct Active { judgement_report: JudgementReport, } +impl Active { + #[must_use] + pub fn judgement_report(&self) -> &JudgementReport { + &self.judgement_report + } +} + pub struct Concluded { turntable: Turntable, actions: BTreeMultiMap, diff --git a/crates/head-wasm/Cargo.toml b/crates/head-wasm/Cargo.toml index 26cef9d..5e3881a 100644 --- a/crates/head-wasm/Cargo.toml +++ b/crates/head-wasm/Cargo.toml @@ -22,12 +22,14 @@ release = ["rrr-head/release", "rrr-head/web"] [dependencies] anyhow = "1.0.65" +js-sys = "0.3.60" log = { version = "0.4.17" } rrr-head = { path = "../head", default-features = false } console_error_panic_hook = "0.1.7" console_log = { version = "0.2.0", features = ["color"] } wasm-bindgen = "0.2.83" wasm-bindgen-futures = "0.4.33" +winit = { version = "0.27.3", default-features = false } [dependencies.web-sys] version = "0.3.60" diff --git a/crates/head-wasm/rust-toolchain.toml b/crates/head-wasm/rust-toolchain.toml new file mode 100644 index 0000000..5d56faf --- /dev/null +++ b/crates/head-wasm/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/crates/head-wasm/src/lib.rs b/crates/head-wasm/src/lib.rs index a0f8cda..456afe3 100644 --- a/crates/head-wasm/src/lib.rs +++ b/crates/head-wasm/src/lib.rs @@ -1,34 +1,131 @@ -use anyhow::Error; -use rrr_head::prelude::winit::{ +#![feature(cfg_eval)] +#![feature(type_alias_impl_trait)] + +use anyhow::{Error, Result}; +use js_sys::Function; +use rrr_head::prelude::play; +use rrr_head::{platform::platform::time::Time, query}; +use std::rc::Rc; +use wasm_bindgen::{prelude::*, JsCast}; +use winit::error::OsError; + +#[cfg_attr(feature = "wasm-bindgen", wasm_bindgen)] +use winit::{ self, dpi::PhysicalSize, event_loop::EventLoop, platform::web::WindowBuilderExtWebSys, window::{Window, WindowBuilder}, }; -use rrr_head::{platform::platform::time::Time, query}; -use std::rc::Rc; -use wasm_bindgen::{closure::Closure, prelude::wasm_bindgen, JsCast}; + use web_sys::HtmlCanvasElement; -pub fn build_window( - event_loop: &EventLoop<()>, - canvas: Option, - size: PhysicalSize, -) -> Result { - { - log::debug!("Inner Size {:?}", size); - WindowBuilder::new() +#[cfg_eval] +#[cfg_attr(feature = "wasm-bindgen", wasm_bindgen)] +pub struct Engine { + #[cfg_attr(feature = "wasm-bindgen", wasm_bindgen(skip))] + event_loop: EventLoop<()>, + window: Window, +} + +#[wasm_bindgen] +impl Engine { + #[inline] + pub(crate) fn new(engine: EngineComponents) -> Result { + Self::init(engine) + } + + fn init(engine: EngineComponents) -> Result { + let event_loop = EventLoop::new(); + + let size = PhysicalSize { + width: engine.width, + height: engine.height, + }; + let window = WindowBuilder::new() .with_title("Rust Rust Revolution") - .with_canvas(canvas) + .with_canvas(engine.canvas) .with_inner_size(size) .with_resizable(false) .with_max_inner_size(size) .with_min_inner_size(size) - .build(event_loop) + .build(&event_loop)?; + + Ok(Engine { event_loop, window }) } } +#[derive(Debug, Default, Clone)] +#[wasm_bindgen] +pub struct EngineBuilder { + pub(crate) engine: EngineComponents, +} + +/// Components to use when building an Engine instance. +#[derive(Debug, Clone)] +pub(crate) struct EngineComponents { + pub canvas: Option, + pub width: u32, + pub height: u32, + pub ui_callback: Option, +} + +impl Default for EngineComponents { + #[inline] + fn default() -> EngineComponents { + EngineComponents { + canvas: None, + width: 512, + height: 768, + ui_callback: None, + } + } +} + +impl EngineBuilder { + /// Initializes builder with default values. + #[inline] + pub fn new() -> Self { + Default::default() + } + + #[inline] + pub fn with_canvas(mut self, canvas: HtmlCanvasElement) -> Self { + self.engine.canvas.replace(canvas); + self + } + + #[inline] + pub fn with_judgement_callback(mut self, callback: Function) -> Self { + self.engine.ui_callback.replace(callback); + self + } + + #[inline] + pub fn build(self) -> Engine { + if let Ok(engine) = Engine::new(self.engine) { + engine + } else { + panic!("no good") + } + } +} + +pub fn build_window( + event_loop: &EventLoop<()>, + canvas: Option, + size: PhysicalSize, +) -> Result { + WindowBuilder::new() + .with_title("Rust Rust Revolution") + .with_canvas(canvas) + .with_inner_size(size) + .with_resizable(false) + .with_max_inner_size(size) + .with_min_inner_size(size) + .build(event_loop) +} + #[wasm_bindgen(start)] pub fn initialize() { console_log::init().unwrap(); @@ -48,7 +145,7 @@ pub fn play(canvas: Option, width: u32, height: u32) { let mut game = rrr_head::Game::