Skip to content

Commit

Permalink
Create winit canvas under WebAssembly (#506)
Browse files Browse the repository at this point in the history
  • Loading branch information
smokku authored Sep 19, 2020
1 parent 19d4694 commit 5e3731d
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 2 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -280,4 +280,4 @@ required-features = []
[[example]]
name = "winit_wasm"
path = "examples/wasm/winit_wasm.rs"
required-features = []
required-features = ["bevy_winit"]
1 change: 1 addition & 0 deletions crates/bevy_winit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
14 changes: 14 additions & 0 deletions crates/bevy_winit/src/winit_windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
4 changes: 4 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
18 changes: 18 additions & 0 deletions examples/wasm/index.html
Original file line number Diff line number Diff line change
@@ -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'
Expand Down
73 changes: 72 additions & 1 deletion examples/wasm/winit_wasm.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,31 @@
extern crate console_error_panic_hook;
use bevy::prelude::*;
use bevy::{
input::{
keyboard::KeyboardInput,
mouse::{MouseButtonInput, MouseMotion, MouseWheel},
},
prelude::*,
};
use std::panic;

fn main() {
panic::set_hook(Box::new(console_error_panic_hook::hook));
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();
}

Expand All @@ -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
);
}
}

0 comments on commit 5e3731d

Please sign in to comment.