diff --git a/Cargo.lock b/Cargo.lock index 831493a..37e871e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2184,6 +2184,7 @@ dependencies = [ "wasm-bindgen-futures", "web-sys", "wgpu", + "winit", ] [[package]] @@ -3715,7 +3716,7 @@ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "visula" version = "0.1.0" -source = "git+https://github.com/dragly/visula?rev=6bb9207a722d3631edb38882a124ff1135278f25#6bb9207a722d3631edb38882a124ff1135278f25" +source = "git+https://github.com/dragly/visula?rev=a103a8bcac6231dda61826af29e52d7a996af075#a103a8bcac6231dda61826af29e52d7a996af075" dependencies = [ "bytemuck", "cgmath", @@ -3762,7 +3763,7 @@ dependencies = [ [[package]] name = "visula_core" version = "0.1.0" -source = "git+https://github.com/dragly/visula?rev=6bb9207a722d3631edb38882a124ff1135278f25#6bb9207a722d3631edb38882a124ff1135278f25" +source = "git+https://github.com/dragly/visula?rev=a103a8bcac6231dda61826af29e52d7a996af075#a103a8bcac6231dda61826af29e52d7a996af075" dependencies = [ "bytemuck", "glam", @@ -3776,7 +3777,7 @@ dependencies = [ [[package]] name = "visula_derive" version = "0.1.0" -source = "git+https://github.com/dragly/visula?rev=6bb9207a722d3631edb38882a124ff1135278f25#6bb9207a722d3631edb38882a124ff1135278f25" +source = "git+https://github.com/dragly/visula?rev=a103a8bcac6231dda61826af29e52d7a996af075#a103a8bcac6231dda61826af29e52d7a996af075" dependencies = [ "proc-macro-crate 1.3.1", "proc-macro2", diff --git a/neuronify-core/Cargo.toml b/neuronify-core/Cargo.toml index 1aee181..4946de1 100644 --- a/neuronify-core/Cargo.toml +++ b/neuronify-core/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" crate-type = ["cdylib", "rlib"] [dependencies] -visula = { git = "https://github.com/dragly/visula", rev = "6bb9207a722d3631edb38882a124ff1135278f25" } -visula_derive = { git = "https://github.com/dragly/visula", rev = "6bb9207a722d3631edb38882a124ff1135278f25" } -visula_core = { git = "https://github.com/dragly/visula", rev = "6bb9207a722d3631edb38882a124ff1135278f25" } +visula = { git = "https://github.com/dragly/visula", rev = "a103a8bcac6231dda61826af29e52d7a996af075" } +visula_derive = { git = "https://github.com/dragly/visula", rev = "a103a8bcac6231dda61826af29e52d7a996af075" } +visula_core = { git = "https://github.com/dragly/visula", rev = "a103a8bcac6231dda61826af29e52d7a996af075" } wgpu = { version = "0.19", features = ["webgl"] } glam = { version = "0.24", features = ["bytemuck", "serde"] } bytemuck = { version = "1.4", features = ["derive"] } @@ -45,3 +45,4 @@ postcard = { version = "1.0.8", features = ["use-std"] } web-sys = { version = "0.3.69", features = ["Request", "Response", "RequestInit", "Headers"] } chrono = { version = "0.4.38", features = ["serde"] } rfd = "0.14.1" +winit = "0.29" diff --git a/neuronify-core/src/lib.rs b/neuronify-core/src/lib.rs index 75ca013..5f4786d 100644 --- a/neuronify-core/src/lib.rs +++ b/neuronify-core/src/lib.rs @@ -1,62 +1,56 @@ +use crate::measurement::voltmeter::RollingWindow; +use crate::measurement::voltmeter::VoltageMeasurement; +use crate::measurement::voltmeter::VoltageSeries; +use crate::measurement::voltmeter::Voltmeter; +use crate::serialization::{LoadContext, SaveContext}; +use bytemuck::{Pod, Zeroable}; +use cgmath::prelude::*; +use cgmath::Vector4; use chrono::{DateTime, Duration, Utc}; +use egui::Color32; +use egui::LayerId; +use egui::Pos2; +use egui_plot::PlotBounds; +use egui_plot::{Line, PlotPoints}; +use glam::Quat; +use glam::Vec3; use hecs::serialize::column::*; +use hecs::Entity; use js_sys::Uint8Array; use postcard::ser_flavors::Flavor; use serde::{Deserialize, Serialize}; use std::borrow::BorrowMut; use std::cmp::Ordering; +use std::collections::HashMap; use std::io::BufReader; use std::io::Read; use std::io::Write; use std::path::PathBuf; use std::sync::Arc; use std::thread; -use visula::initialize_event_loop_and_window_with_config; -use visula::initialize_logger; -use visula::winit::keyboard::ModifiersKeyState; -use visula::Application; -use visula::RunConfig; -use visula::Simulation; -use visula::Vector3; -use wasm_bindgen::prelude::*; - -use wasm_bindgen_futures::JsFuture; -use web_sys::{Request, RequestInit, Response}; - -use std::collections::HashMap; - -use crate::measurement::voltmeter::VoltageSeries; - -use bytemuck::{Pod, Zeroable}; -use cgmath::prelude::*; -use cgmath::Vector4; -use egui::Color32; -use egui::LayerId; -use egui::Pos2; -use egui_plot::PlotBounds; -use egui_plot::{Line, PlotPoints}; -use glam::Quat; -use glam::Vec3; -use hecs::Entity; - -use crate::measurement::voltmeter::RollingWindow; -use crate::measurement::voltmeter::VoltageMeasurement; -use crate::measurement::voltmeter::Voltmeter; use strum::EnumIter; use strum::IntoEnumIterator; +use visula::create_window; +#[cfg(target_arch = "wasm32")] +use visula::winit::platform::web::EventLoopExtWebSys; use visula::winit::{ dpi::PhysicalPosition, event::{ElementState, Event, MouseButton, WindowEvent}, }; -use visula::Renderable; use visula::{ - CustomEvent, InstanceBuffer, LineDelegate, Lines, RenderData, SphereDelegate, Spheres, + create_event_loop, initialize_logger, winit::keyboard::ModifiersKeyState, Application, + CustomEvent, InstanceBuffer, LineDelegate, Lines, RenderData, Renderable, RunConfig, + Simulation, SphereDelegate, Spheres, Vector3, }; use visula_derive::Instance; +use wasm_bindgen::prelude::*; +use wasm_bindgen_futures::JsFuture; +use web_sys::{Request, RequestInit, Response}; +use winit::event_loop::EventLoop; +use winit::event_loop::EventLoopWindowTarget; pub mod measurement; pub mod serialization; -use crate::serialization::{LoadContext, SaveContext}; #[derive(Clone, Debug, EnumIter, PartialEq)] pub enum Tool { @@ -1622,6 +1616,11 @@ impl visula::Simulation for Neuronify { } fn handle_event(&mut self, application: &mut visula::Application, event: &Event) { + if let Event::WindowEvent { window_id, .. } = event { + if &application.window.id() != window_id { + return; + } + } match event { Event::WindowEvent { event: @@ -1658,15 +1657,37 @@ impl visula::Simulation for Neuronify { } } +struct Bundle { + application: Application, + simulation: Neuronify, +} + #[wasm_bindgen] -pub async fn load(url: &str) -> Result<(), JsValue> { +pub struct WasmWrapper { + event_loop: EventLoop, + bundles: Vec, +} + +#[wasm_bindgen] +pub async fn initialize() -> WasmWrapper { initialize_logger(); - let (event_loop, window) = initialize_event_loop_and_window_with_config(RunConfig { - canvas_name: "canvas".to_owned(), - }); - let main_window_id = window.id(); - let mut application = - pollster::block_on(async { Application::new(Arc::new(window), &event_loop).await }); + let event_loop = create_event_loop(); + let bundles: Vec = Vec::new(); + WasmWrapper { + event_loop, + bundles, + } +} + +#[wasm_bindgen] +pub async fn load(wrapper: &mut WasmWrapper, canvas: &str, url: &str) -> Result<(), JsValue> { + let window = create_window( + RunConfig { + canvas_name: canvas.to_owned(), + }, + &wrapper.event_loop, + ); + let mut application = pollster::block_on(async { Application::new(Arc::new(window)).await }); let mut opts = RequestInit::new(); opts.method("GET"); @@ -1677,21 +1698,29 @@ pub async fn load(url: &str) -> Result<(), JsValue> { let buffer = JsFuture::from(response.array_buffer()?).await?; let uint8_array = Uint8Array::new(&buffer); let vec = uint8_array.to_vec(); - let mut simulation = Neuronify::from_slice(&mut application, &vec); - event_loop - .run(move |event, target| { + let simulation = Neuronify::from_slice(&mut application, &vec); + wrapper.bundles.push(Bundle { + application, + simulation, + }); + Ok(()) +} + +#[wasm_bindgen] +pub async fn start(mut wrapper: WasmWrapper) -> Result<(), JsValue> { + let _event_handler = move |event, target: &EventLoopWindowTarget| { + for bundle in wrapper.bundles.iter_mut() { + let application = &mut bundle.application; + let simulation = &mut bundle.simulation; if !application.handle_event(&event) { - simulation.handle_event(&mut application, &event); + simulation.handle_event(application, &event); } - if let Event::WindowEvent { window_id, event } = event { - if main_window_id != window_id { - return; - } + if let Event::WindowEvent { ref event, .. } = event { match event { WindowEvent::RedrawRequested => { application.update(); - simulation.update(&mut application); - application.render(&mut simulation); + simulation.update(application); + application.render(simulation); application.window.borrow_mut().request_redraw(); } @@ -1699,8 +1728,10 @@ pub async fn load(url: &str) -> Result<(), JsValue> { _ => {} } } - }) - .expect("Event loop failed to run"); + } + }; + #[cfg(target_arch = "wasm32")] + wrapper.event_loop.spawn(_event_handler); Ok(()) }