Create winit canvas under WebAssembly (#506)
This commit is contained in:
		
							parent
							
								
									19d4694d24
								
							
						
					
					
						commit
						5e3731ddce
					
				@ -280,4 +280,4 @@ required-features = []
 | 
			
		||||
[[example]]
 | 
			
		||||
name = "winit_wasm"
 | 
			
		||||
path = "examples/wasm/winit_wasm.rs"
 | 
			
		||||
required-features = []
 | 
			
		||||
required-features = ["bevy_winit"]
 | 
			
		||||
 | 
			
		||||
@ -31,3 +31,4 @@ log = { version = "0.4", features = ["release_max_level_info"] }
 | 
			
		||||
 | 
			
		||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
 | 
			
		||||
winit = { version = "0.22.2", package = "cart-tmp-winit", features = ["web-sys"] }
 | 
			
		||||
web-sys = "0.3"
 | 
			
		||||
 | 
			
		||||
@ -46,6 +46,20 @@ impl WinitWindows {
 | 
			
		||||
        self.window_id_to_winit.insert(window.id, winit_window.id());
 | 
			
		||||
        self.winit_to_window_id.insert(winit_window.id(), window.id);
 | 
			
		||||
 | 
			
		||||
        #[cfg(target_arch = "wasm32")]
 | 
			
		||||
        {
 | 
			
		||||
            use winit::platform::web::WindowExtWebSys;
 | 
			
		||||
 | 
			
		||||
            let canvas = winit_window.canvas();
 | 
			
		||||
 | 
			
		||||
            let window = web_sys::window().unwrap();
 | 
			
		||||
            let document = window.document().unwrap();
 | 
			
		||||
            let body = document.body().unwrap();
 | 
			
		||||
 | 
			
		||||
            body.append_child(&canvas)
 | 
			
		||||
                .expect("Append canvas to HTML body");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        self.windows.insert(winit_window.id(), winit_window);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -126,6 +126,10 @@ Example | File | Description
 | 
			
		||||
 | 
			
		||||
#### build & run
 | 
			
		||||
 | 
			
		||||
Following is an example for `headless_wasm`. For other examples in wasm/ directory,
 | 
			
		||||
change the `headless_wasm` in the following commands **and edit** `examples/wasm/index.html`
 | 
			
		||||
to point to the correct `.js` file.
 | 
			
		||||
 | 
			
		||||
    $ cargo build --example headless_wasm --target wasm32-unknown-unknown --no-default-features
 | 
			
		||||
    $ wasm-bindgen --out-dir examples/wasm/target --target web target/wasm32-unknown-unknown/debug/examples/headless_wasm.wasm
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,24 @@
 | 
			
		||||
<html>
 | 
			
		||||
  <head>
 | 
			
		||||
    <meta charset="UTF-8" />
 | 
			
		||||
    <style>
 | 
			
		||||
      body {
 | 
			
		||||
        background: linear-gradient(
 | 
			
		||||
          135deg,
 | 
			
		||||
          white 0%,
 | 
			
		||||
          white 49%,
 | 
			
		||||
          black 49%,
 | 
			
		||||
          black 51%,
 | 
			
		||||
          white 51%,
 | 
			
		||||
          white 100%
 | 
			
		||||
        );
 | 
			
		||||
        background-repeat: repeat;
 | 
			
		||||
        background-size: 20px 20px;
 | 
			
		||||
      }
 | 
			
		||||
      canvas {
 | 
			
		||||
        background-color: white;
 | 
			
		||||
      }
 | 
			
		||||
    </style>
 | 
			
		||||
  </head>
 | 
			
		||||
  <script type="module">
 | 
			
		||||
    import init from './target/headless_wasm.js'
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,11 @@
 | 
			
		||||
extern crate console_error_panic_hook;
 | 
			
		||||
use bevy::prelude::*;
 | 
			
		||||
use bevy::{
 | 
			
		||||
    input::{
 | 
			
		||||
        keyboard::KeyboardInput,
 | 
			
		||||
        mouse::{MouseButtonInput, MouseMotion, MouseWheel},
 | 
			
		||||
    },
 | 
			
		||||
    prelude::*,
 | 
			
		||||
};
 | 
			
		||||
use std::panic;
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
@ -7,9 +13,19 @@ fn main() {
 | 
			
		||||
    console_log::init_with_level(log::Level::Debug).expect("cannot initialize console_log");
 | 
			
		||||
 | 
			
		||||
    App::build()
 | 
			
		||||
        .add_resource(WindowDescriptor {
 | 
			
		||||
            width: 300,
 | 
			
		||||
            height: 300,
 | 
			
		||||
            ..Default::default()
 | 
			
		||||
        })
 | 
			
		||||
        .add_default_plugins()
 | 
			
		||||
        // One time greet
 | 
			
		||||
        .add_startup_system(hello_wasm_system.system())
 | 
			
		||||
        // Track ticks (sanity check, whether game loop is running)
 | 
			
		||||
        .add_system(counter.system())
 | 
			
		||||
        // Track input events
 | 
			
		||||
        .init_resource::<TrackInputState>()
 | 
			
		||||
        .add_system(track_input_events.system())
 | 
			
		||||
        .run();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -33,3 +49,58 @@ fn counter(mut state: Local<CounterState>, time: Res<Time>) {
 | 
			
		||||
struct CounterState {
 | 
			
		||||
    count: u32,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Default)]
 | 
			
		||||
struct TrackInputState {
 | 
			
		||||
    keys: EventReader<KeyboardInput>,
 | 
			
		||||
    cursor: EventReader<CursorMoved>,
 | 
			
		||||
    motion: EventReader<MouseMotion>,
 | 
			
		||||
    mousebtn: EventReader<MouseButtonInput>,
 | 
			
		||||
    scroll: EventReader<MouseWheel>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn track_input_events(
 | 
			
		||||
    mut state: ResMut<TrackInputState>,
 | 
			
		||||
    ev_keys: Res<Events<KeyboardInput>>,
 | 
			
		||||
    ev_cursor: Res<Events<CursorMoved>>,
 | 
			
		||||
    ev_motion: Res<Events<MouseMotion>>,
 | 
			
		||||
    ev_mousebtn: Res<Events<MouseButtonInput>>,
 | 
			
		||||
    ev_scroll: Res<Events<MouseWheel>>,
 | 
			
		||||
) {
 | 
			
		||||
    // Keyboard input
 | 
			
		||||
    for ev in state.keys.iter(&ev_keys) {
 | 
			
		||||
        if ev.state.is_pressed() {
 | 
			
		||||
            log::info!("Just pressed key: {:?}", ev.key_code);
 | 
			
		||||
        } else {
 | 
			
		||||
            log::info!("Just released key: {:?}", ev.key_code);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Absolute cursor position (in window coordinates)
 | 
			
		||||
    for ev in state.cursor.iter(&ev_cursor) {
 | 
			
		||||
        log::info!("Cursor at: {}", ev.position);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Relative mouse motion
 | 
			
		||||
    for ev in state.motion.iter(&ev_motion) {
 | 
			
		||||
        log::info!("Mouse moved {} pixels", ev.delta);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Mouse buttons
 | 
			
		||||
    for ev in state.mousebtn.iter(&ev_mousebtn) {
 | 
			
		||||
        if ev.state.is_pressed() {
 | 
			
		||||
            log::info!("Just pressed mouse button: {:?}", ev.button);
 | 
			
		||||
        } else {
 | 
			
		||||
            log::info!("Just released mouse button: {:?}", ev.button);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // scrolling (mouse wheel, touchpad, etc.)
 | 
			
		||||
    for ev in state.scroll.iter(&ev_scroll) {
 | 
			
		||||
        log::info!(
 | 
			
		||||
            "Scrolled vertically by {} and horizontally by {}.",
 | 
			
		||||
            ev.y,
 | 
			
		||||
            ev.x
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user