Create winit canvas under WebAssembly (#506)

This commit is contained in:
Tomasz Sterna 2020-09-19 05:11:26 +02:00 committed by GitHub
parent 19d4694d24
commit 5e3731ddce
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 110 additions and 2 deletions

View file

@ -280,4 +280,4 @@ required-features = []
[[example]]
name = "winit_wasm"
path = "examples/wasm/winit_wasm.rs"
required-features = []
required-features = ["bevy_winit"]

View file

@ -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"

View file

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

View file

@ -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

View file

@ -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'

View file

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