refactor: simplify web bootstrap

Amp-Thread-ID: https://ampcode.com/threads/T-019f9d91-77c1-7206-a60f-ed6554ce92ab

Co-authored-by: Heaust Azure <heaust.azure@gmail.com>
This commit is contained in:
Amp
2026-07-29 02:02:22 +00:00
co-authored by heaust
parent 2ff8a4a17b
commit c1a95e4b27
5 changed files with 15 additions and 91 deletions
+4 -17
View File
@@ -1,11 +1,9 @@
use std::sync::mpsc::Receiver;
use std::{cell::RefCell, rc::Rc};
use ultraviolet::Mat4; use ultraviolet::Mat4;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
use renderer::app_setup::WebApp; #[cfg(target_arch = "wasm32")]
use renderer::app_setup::WebAppRuntime;
use renderer::camera::Camera; use renderer::camera::Camera;
use renderer::message::WindowEvent;
use renderer::render_data::{InstanceType, MeshCreateInfo, RenderData}; use renderer::render_data::{InstanceType, MeshCreateInfo, RenderData};
use renderer::renderer as gpu_renderer; use renderer::renderer as gpu_renderer;
use renderer::renderer::gpu_scene::vertex_layouts; use renderer::renderer::gpu_scene::vertex_layouts;
@@ -18,7 +16,7 @@ struct Vertex {
pos: [f32; 3], pos: [f32; 3],
} }
pub struct EditorScene { struct EditorScene {
uniform_buffers: [wgpu::Buffer; 2], uniform_buffers: [wgpu::Buffer; 2],
bind_groups: [wgpu::BindGroup; 2], bind_groups: [wgpu::BindGroup; 2],
bind_group_layouts: [wgpu::BindGroupLayout; 2], bind_group_layouts: [wgpu::BindGroupLayout; 2],
@@ -111,17 +109,6 @@ impl renderer::renderer::scene::Scene for EditorScene {
} }
} }
#[cfg(target_arch = "wasm32")]
pub struct LevelEditor {
#[allow(dead_code)]
scene: EditorScene,
}
#[cfg(target_arch = "wasm32")]
impl WebApp for LevelEditor {
type Scene = EditorScene;
}
impl EditorScene { impl EditorScene {
/// Ground plane vertex data. /// Ground plane vertex data.
const VERTICES: &[Vertex] = &[ const VERTICES: &[Vertex] = &[
@@ -208,7 +195,7 @@ pub fn main(profile: bool) -> Result<RendererBridge, JsValue> {
std::panic::set_hook(Box::new(console_error_panic_hook::hook)); std::panic::set_hook(Box::new(console_error_panic_hook::hook));
wasm_logger::init(wasm_logger::Config::default()); wasm_logger::init(wasm_logger::Config::default());
let runtime = LevelEditor::setup_runtime(profile)?; let runtime = WebAppRuntime::new::<EditorScene>("main-worker", "#canvas0", profile)?;
Ok(RendererBridge { runtime }) Ok(RendererBridge { runtime })
} }
+10 -61
View File
@@ -14,27 +14,13 @@ use wasm_bindgen_futures::spawn_local;
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
use web_sys::AddEventListenerOptions; use web_sys::AddEventListenerOptions;
/// Helper struct to store event listener closures
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
pub struct EventListeners { pub struct EventListeners {
pub resize_listener: Option<Closure<dyn FnMut()>>, _resize_listener: Closure<dyn FnMut()>,
pub pointer_listener: Option<Closure<dyn FnMut(web_sys::PointerEvent)>>, _pointer_listener: Closure<dyn FnMut(web_sys::PointerEvent)>,
pub click_listener: Option<Closure<dyn FnMut(web_sys::MouseEvent)>>, _click_listener: Closure<dyn FnMut(web_sys::MouseEvent)>,
pub wheel_listener: Option<Closure<dyn FnMut(web_sys::WheelEvent)>>, _wheel_listener: Closure<dyn FnMut(web_sys::WheelEvent)>,
pub contextmenu_listener: Option<Closure<dyn FnMut(web_sys::MouseEvent)>>, _contextmenu_listener: Closure<dyn FnMut(web_sys::MouseEvent)>,
}
#[cfg(target_arch = "wasm32")]
impl EventListeners {
pub fn new() -> Self {
Self {
resize_listener: None,
pointer_listener: None,
click_listener: None,
wheel_listener: None,
contextmenu_listener: None,
}
}
} }
/// Setup default window event listeners that forward events to the worker thread /// Setup default window event listeners that forward events to the worker thread
@@ -152,11 +138,11 @@ pub fn setup_event_listeners(
)?; )?;
Ok(EventListeners { Ok(EventListeners {
resize_listener: Some(resize_listener), _resize_listener: resize_listener,
pointer_listener: Some(pointer_listener), _pointer_listener: pointer_listener,
click_listener: Some(click_listener), _click_listener: click_listener,
wheel_listener: Some(wheel_listener), _wheel_listener: wheel_listener,
contextmenu_listener: Some(contextmenu_listener), _contextmenu_listener: contextmenu_listener,
}) })
} }
@@ -164,7 +150,6 @@ pub fn setup_event_listeners(
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
pub struct WebAppRuntime { pub struct WebAppRuntime {
worker: MainWorker, worker: MainWorker,
worker_chan: Sender<WindowEvent>,
_event_listeners: EventListeners, _event_listeners: EventListeners,
ring: Box<CommandRing>, ring: Box<CommandRing>,
} }
@@ -199,17 +184,11 @@ impl WebAppRuntime {
Ok(Self { Ok(Self {
worker, worker,
worker_chan: sender,
_event_listeners: event_listeners, _event_listeners: event_listeners,
ring, ring,
}) })
} }
/// Access the worker channel sender for dispatching custom window events.
pub fn sender(&self) -> &Sender<WindowEvent> {
&self.worker_chan
}
/// Access the spawned worker reference. /// Access the spawned worker reference.
pub fn worker(&self) -> &MainWorker { pub fn worker(&self) -> &MainWorker {
&self.worker &self.worker
@@ -218,33 +197,3 @@ impl WebAppRuntime {
self.ring.ptr() self.ring.ptr()
} }
} }
/// Trait for applications that rely on the renderer's default WASM setup.
#[cfg(target_arch = "wasm32")]
pub trait WebApp {
type Scene: crate::renderer::scene::Scene + 'static;
/// Name used for the spawned `MainWorker`.
fn worker_name() -> &'static str {
"main-worker"
}
/// CSS selector for the canvas element that will be transferred to the worker.
fn canvas_selector() -> &'static str {
"#canvas0"
}
/// Hook invoked after the runtime has been created.
fn on_runtime_initialized(_runtime: &mut WebAppRuntime) {}
/// Perform the default WASM initialization routine.
fn setup_runtime(profile: bool) -> Result<WebAppRuntime, JsValue> {
let mut runtime = WebAppRuntime::new::<Self::Scene>(
Self::worker_name(),
Self::canvas_selector(),
profile,
)?;
Self::on_runtime_initialized(&mut runtime);
Ok(runtime)
}
}
+1 -7
View File
@@ -6,11 +6,5 @@ pub fn get_canvas_element(selectors: &str) -> web_sys::HtmlCanvasElement {
let window = web_sys::window().unwrap(); let window = web_sys::window().unwrap();
let document = window.document().unwrap(); let document = window.document().unwrap();
let element = document.query_selector(selectors).unwrap().unwrap(); let element = document.query_selector(selectors).unwrap().unwrap();
let canvas = element.dyn_into::<web_sys::HtmlCanvasElement>().unwrap(); element.dyn_into::<web_sys::HtmlCanvasElement>().unwrap()
let scale_factor = window.device_pixel_ratio();
let width = (canvas.client_width() as f64 * scale_factor) as u32;
let height = (canvas.client_height() as f64 * scale_factor) as u32;
canvas.set_width(width);
canvas.set_height(height);
canvas
} }
@@ -2,8 +2,6 @@
// Works for any application because the relative depth from this file to pkg is stable. // Works for any application because the relative depth from this file to pkg is stable.
import initWasm, { clear_payloads, discard_payload, stage_payload, worker_entrypoint } from "/level-editor/pkg/level_editor.js"; import initWasm, { clear_payloads, discard_payload, stage_payload, worker_entrypoint } from "/level-editor/pkg/level_editor.js";
export function attachMain() {}
export function listenerReady() { export function listenerReady() {
if (state !== "waiting-listener") return; if (state !== "waiting-listener") return;
state = "replaying"; state = "replaying";
-4
View File
@@ -20,10 +20,6 @@ extern "C" {
/// So that bundler can bundle it together. /// So that bundler can bundle it together.
#[wasm_bindgen(module = "/src/platform/web/worker/mainWorker.js")] #[wasm_bindgen(module = "/src/platform/web/worker/mainWorker.js")]
extern "C" { extern "C" {
/// Nothing to do.
#[wasm_bindgen]
fn attachMain();
#[wasm_bindgen(js_name = "listenerReady")] #[wasm_bindgen(js_name = "listenerReady")]
fn listener_ready(); fn listener_ready();
} }