From fbfded47050aa5bb86e6792f66f1cf6d9c894f2f Mon Sep 17 00:00:00 2001 From: Kevin King <4kevinking@gmail.com> Date: Sat, 19 Feb 2022 19:10:12 -0800 Subject: [PATCH 1/7] start prototyping embedding bevy --- components/bevy.tsx | 9 ++++ crates/bevy-example/.cargo-ok | 0 crates/bevy-example/.cargo/config.toml | 2 + crates/bevy-example/.gitignore | 6 +++ crates/bevy-example/.travis.yml | 69 ++++++++++++++++++++++++++ crates/bevy-example/Cargo.toml | 24 +++++++++ crates/bevy-example/src/lib.rs | 38 ++++++++++++++ crates/bevy-example/src/utils.rs | 10 ++++ crates/bevy-example/tests/web.rs | 13 +++++ pages/blog/benefits-of-bevy.mdx | 18 +++++++ 10 files changed, 189 insertions(+) create mode 100644 components/bevy.tsx create mode 100644 crates/bevy-example/.cargo-ok create mode 100644 crates/bevy-example/.cargo/config.toml create mode 100644 crates/bevy-example/.gitignore create mode 100644 crates/bevy-example/.travis.yml create mode 100644 crates/bevy-example/Cargo.toml create mode 100644 crates/bevy-example/src/lib.rs create mode 100644 crates/bevy-example/src/utils.rs create mode 100644 crates/bevy-example/tests/web.rs create mode 100644 pages/blog/benefits-of-bevy.mdx diff --git a/components/bevy.tsx b/components/bevy.tsx new file mode 100644 index 0000000..ea6936f --- /dev/null +++ b/components/bevy.tsx @@ -0,0 +1,9 @@ +import { useEffect } from "react"; +import { run } from "../crates/bevy-example/pkg"; + +export const BevyExample = () => { + useEffect(() => { + run(); + }, []); + return <>; +}; diff --git a/crates/bevy-example/.cargo-ok b/crates/bevy-example/.cargo-ok new file mode 100644 index 0000000..e69de29 diff --git a/crates/bevy-example/.cargo/config.toml b/crates/bevy-example/.cargo/config.toml new file mode 100644 index 0000000..f4e8c00 --- /dev/null +++ b/crates/bevy-example/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +target = "wasm32-unknown-unknown" diff --git a/crates/bevy-example/.gitignore b/crates/bevy-example/.gitignore new file mode 100644 index 0000000..4e30131 --- /dev/null +++ b/crates/bevy-example/.gitignore @@ -0,0 +1,6 @@ +/target +**/*.rs.bk +Cargo.lock +bin/ +pkg/ +wasm-pack.log diff --git a/crates/bevy-example/.travis.yml b/crates/bevy-example/.travis.yml new file mode 100644 index 0000000..7a91325 --- /dev/null +++ b/crates/bevy-example/.travis.yml @@ -0,0 +1,69 @@ +language: rust +sudo: false + +cache: cargo + +matrix: + include: + + # Builds with wasm-pack. + - rust: beta + env: RUST_BACKTRACE=1 + addons: + firefox: latest + chrome: stable + before_script: + - (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update) + - (test -x $HOME/.cargo/bin/cargo-generate || cargo install --vers "^0.2" cargo-generate) + - cargo install-update -a + - curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh -s -- -f + script: + - cargo generate --git . --name testing + # Having a broken Cargo.toml (in that it has curlies in fields) anywhere + # in any of our parent dirs is problematic. + - mv Cargo.toml Cargo.toml.tmpl + - cd testing + - wasm-pack build + - wasm-pack test --chrome --firefox --headless + + # Builds on nightly. + - rust: nightly + env: RUST_BACKTRACE=1 + before_script: + - (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update) + - (test -x $HOME/.cargo/bin/cargo-generate || cargo install --vers "^0.2" cargo-generate) + - cargo install-update -a + - rustup target add wasm32-unknown-unknown + script: + - cargo generate --git . --name testing + - mv Cargo.toml Cargo.toml.tmpl + - cd testing + - cargo check + - cargo check --target wasm32-unknown-unknown + - cargo check --no-default-features + - cargo check --target wasm32-unknown-unknown --no-default-features + - cargo check --no-default-features --features console_error_panic_hook + - cargo check --target wasm32-unknown-unknown --no-default-features --features console_error_panic_hook + - cargo check --no-default-features --features "console_error_panic_hook wee_alloc" + - cargo check --target wasm32-unknown-unknown --no-default-features --features "console_error_panic_hook wee_alloc" + + # Builds on beta. + - rust: beta + env: RUST_BACKTRACE=1 + before_script: + - (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update) + - (test -x $HOME/.cargo/bin/cargo-generate || cargo install --vers "^0.2" cargo-generate) + - cargo install-update -a + - rustup target add wasm32-unknown-unknown + script: + - cargo generate --git . --name testing + - mv Cargo.toml Cargo.toml.tmpl + - cd testing + - cargo check + - cargo check --target wasm32-unknown-unknown + - cargo check --no-default-features + - cargo check --target wasm32-unknown-unknown --no-default-features + - cargo check --no-default-features --features console_error_panic_hook + - cargo check --target wasm32-unknown-unknown --no-default-features --features console_error_panic_hook + # Note: no enabling the `wee_alloc` feature here because it requires + # nightly for now. diff --git a/crates/bevy-example/Cargo.toml b/crates/bevy-example/Cargo.toml new file mode 100644 index 0000000..a335e1e --- /dev/null +++ b/crates/bevy-example/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "bevy-example" +version = "0.1.0" +authors = ["Kevin King <4kevinking@gmail.com>"] +edition = "2021" + +[lib] +crate-type = ["cdylib", "rlib"] + +[features] +default = ["console_error_panic_hook"] + +[dependencies] +wasm-bindgen = "0.2.63" +console_error_panic_hook = { version = "0.1.6", optional = true } +wee_alloc = { version = "0.4.5" } +bevy = "0.6.1" + +[dev-dependencies] +wasm-bindgen-test = "0.3.13" + +[profile.release] +# Tell `rustc` to optimize for small code size. +opt-level = "s" diff --git a/crates/bevy-example/src/lib.rs b/crates/bevy-example/src/lib.rs new file mode 100644 index 0000000..ca56af2 --- /dev/null +++ b/crates/bevy-example/src/lib.rs @@ -0,0 +1,38 @@ +mod utils; + +use wasm_bindgen::prelude::*; + +#[global_allocator] +static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; + +#[wasm_bindgen] +pub fn greet() {} + +// IDEA: +// 1. expose method to run single frame of app +// 2. scope bevy to existing canvas so it doesn't take over the whole page +use bevy::prelude::*; +#[wasm_bindgen] +pub fn run() { + App::new() + .add_plugins(DefaultPlugins) + .add_startup_system(setup) + .add_system(log_tick) + .run(); +} + +fn setup(mut commands: Commands) { + commands.spawn_bundle(OrthographicCameraBundle::new_2d()); + commands.spawn_bundle(SpriteBundle { + sprite: Sprite { + color: Color::rgb(0.25, 0.25, 0.75), + custom_size: Some(Vec2::new(50.0, 50.0)), + ..Default::default() + }, + ..Default::default() + }); +} + +fn log_tick() { + warn!("tick"); +} diff --git a/crates/bevy-example/src/utils.rs b/crates/bevy-example/src/utils.rs new file mode 100644 index 0000000..b1d7929 --- /dev/null +++ b/crates/bevy-example/src/utils.rs @@ -0,0 +1,10 @@ +pub fn set_panic_hook() { + // When the `console_error_panic_hook` feature is enabled, we can call the + // `set_panic_hook` function at least once during initialization, and then + // we will get better error messages if our code ever panics. + // + // For more details see + // https://github.com/rustwasm/console_error_panic_hook#readme + #[cfg(feature = "console_error_panic_hook")] + console_error_panic_hook::set_once(); +} diff --git a/crates/bevy-example/tests/web.rs b/crates/bevy-example/tests/web.rs new file mode 100644 index 0000000..de5c1da --- /dev/null +++ b/crates/bevy-example/tests/web.rs @@ -0,0 +1,13 @@ +//! Test suite for the Web and headless browsers. + +#![cfg(target_arch = "wasm32")] + +extern crate wasm_bindgen_test; +use wasm_bindgen_test::*; + +wasm_bindgen_test_configure!(run_in_browser); + +#[wasm_bindgen_test] +fn pass() { + assert_eq!(1 + 1, 2); +} diff --git a/pages/blog/benefits-of-bevy.mdx b/pages/blog/benefits-of-bevy.mdx new file mode 100644 index 0000000..2a72f0b --- /dev/null +++ b/pages/blog/benefits-of-bevy.mdx @@ -0,0 +1,18 @@ +import { MDXProvider } from "@mdx-js/react"; +import { Layout } from "../../components/bloglayout"; +export default ({ children }) => {children}; + +import { BevyExample } from "../../components/bevy"; + +export const meta = { + title: "Intro to Bevy", + date: "Feb 19 2022", + draft: true, + subtitle: "yea", +}; + +# {meta.title} + +> {meta.subtitle} + +{} From 31f647e2c8dda0bb7758440fa002e1aebbc89b88 Mon Sep 17 00:00:00 2001 From: Kevin King <4kevinking@gmail.com> Date: Mon, 21 Feb 2022 00:35:45 -0800 Subject: [PATCH 2/7] scope bevy to exsting canvas --- components/bevy.tsx | 8 +++++- components/bevy_dynamic.tsx | 3 ++ crates/bevy-example/.vscode/settings.json | 3 ++ crates/bevy-example/src/lib.rs | 35 ++++++++++++++++------- package.json | 2 +- pages/blog/benefits-of-bevy.mdx | 4 ++- 6 files changed, 42 insertions(+), 13 deletions(-) create mode 100644 components/bevy_dynamic.tsx create mode 100644 crates/bevy-example/.vscode/settings.json diff --git a/components/bevy.tsx b/components/bevy.tsx index ea6936f..3afede6 100644 --- a/components/bevy.tsx +++ b/components/bevy.tsx @@ -3,7 +3,13 @@ import { run } from "../crates/bevy-example/pkg"; export const BevyExample = () => { useEffect(() => { - run(); + try { + run(); + } catch (e) { + console.error(e); + } }, []); return <>; }; + +export default BevyExample; diff --git a/components/bevy_dynamic.tsx b/components/bevy_dynamic.tsx new file mode 100644 index 0000000..fa888d1 --- /dev/null +++ b/components/bevy_dynamic.tsx @@ -0,0 +1,3 @@ +import dynamic from "next/dynamic"; + +export const BevyExample = dynamic(() => import("./bevy"), { ssr: false }); diff --git a/crates/bevy-example/.vscode/settings.json b/crates/bevy-example/.vscode/settings.json new file mode 100644 index 0000000..865ec57 --- /dev/null +++ b/crates/bevy-example/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + // "rust-analyzer.cargo.target": "wasm32-unknown-unknown", +} diff --git a/crates/bevy-example/src/lib.rs b/crates/bevy-example/src/lib.rs index ca56af2..6bfc6d1 100644 --- a/crates/bevy-example/src/lib.rs +++ b/crates/bevy-example/src/lib.rs @@ -15,24 +15,39 @@ use bevy::prelude::*; #[wasm_bindgen] pub fn run() { App::new() + .insert_resource(WindowDescriptor { + canvas: Some("#bevy-canvas".into()), + ..Default::default() + }) .add_plugins(DefaultPlugins) .add_startup_system(setup) - .add_system(log_tick) + .add_system(tick) .run(); } +#[derive(Component)] +struct CubeTag; + fn setup(mut commands: Commands) { commands.spawn_bundle(OrthographicCameraBundle::new_2d()); - commands.spawn_bundle(SpriteBundle { - sprite: Sprite { - color: Color::rgb(0.25, 0.25, 0.75), - custom_size: Some(Vec2::new(50.0, 50.0)), + commands + .spawn_bundle(SpriteBundle { + sprite: Sprite { + color: Color::rgb(0.25, 0.25, 0.75), + custom_size: Some(Vec2::new(50.0, 50.0)), + ..Default::default() + }, ..Default::default() - }, - ..Default::default() - }); + }) + .insert(CubeTag); } -fn log_tick() { - warn!("tick"); +fn tick(mut q: Query<(&mut Transform, &CubeTag)>, windows: Res) { + for mut cube in q.iter_mut() { + let pos = &mut cube.0.translation; + let window = windows.get_primary().unwrap(); + let cursor = window.cursor_position().unwrap_or_default(); + pos.x = cursor.x - window.width() / 2.; + pos.y = cursor.y - window.height() / 2.; + } } diff --git a/package.json b/package.json index ac70a5d..d58dea0 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "private": true, "scripts": { "dev": "next dev", - "build": "cd rust && wasm-pack build && cd .. && next build", + "build": "cd rust && wasm-pack build && cd ../crates/bevy-example && wasm-pack build && cd ../.. && next build", "start": "next start", "lint": "next lint", "vercel-build-deps": "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | bash -s -- -y && export PATH=\"/vercel/.cargo/bin:$PATH\" && wget -O wasm-pack.tar.gz \"https://github.com/rustwasm/wasm-pack/releases/download/v0.10.2/wasm-pack-v0.10.2-x86_64-unknown-linux-musl.tar.gz\" && tar xvf wasm-pack.tar.gz && ls && yarn install" diff --git a/pages/blog/benefits-of-bevy.mdx b/pages/blog/benefits-of-bevy.mdx index 2a72f0b..e4fe436 100644 --- a/pages/blog/benefits-of-bevy.mdx +++ b/pages/blog/benefits-of-bevy.mdx @@ -2,7 +2,7 @@ import { MDXProvider } from "@mdx-js/react"; import { Layout } from "../../components/bloglayout"; export default ({ children }) => {children}; -import { BevyExample } from "../../components/bevy"; +import { BevyExample } from "../../components/bevy_dynamic"; export const meta = { title: "Intro to Bevy", @@ -15,4 +15,6 @@ export const meta = { > {meta.subtitle} + + {} From 8098383c3abb7e30240fd040bf3bf5366b3cb4bb Mon Sep 17 00:00:00 2001 From: Kevin King <4kevinking@gmail.com> Date: Mon, 21 Feb 2022 00:38:31 -0800 Subject: [PATCH 3/7] todos --- crates/bevy-example/src/lib.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/bevy-example/src/lib.rs b/crates/bevy-example/src/lib.rs index 6bfc6d1..354523c 100644 --- a/crates/bevy-example/src/lib.rs +++ b/crates/bevy-example/src/lib.rs @@ -8,9 +8,8 @@ static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; #[wasm_bindgen] pub fn greet() {} -// IDEA: -// 1. expose method to run single frame of app -// 2. scope bevy to existing canvas so it doesn't take over the whole page +// TODO: send canvas size to rust +// TODO: sometimes hit `unreachable error` after window is open for a while use bevy::prelude::*; #[wasm_bindgen] pub fn run() { From 083fe23e211b021c1ed6a0cc6687b1a4ba0833d6 Mon Sep 17 00:00:00 2001 From: Kevin King <4kevinking@gmail.com> Date: Mon, 21 Feb 2022 00:47:44 -0800 Subject: [PATCH 4/7] todo --- crates/bevy-example/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/bevy-example/src/lib.rs b/crates/bevy-example/src/lib.rs index 354523c..2b0c9e5 100644 --- a/crates/bevy-example/src/lib.rs +++ b/crates/bevy-example/src/lib.rs @@ -9,7 +9,8 @@ static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; pub fn greet() {} // TODO: send canvas size to rust -// TODO: sometimes hit `unreachable error` after window is open for a while +// TODO: sometimes hit `unreachable error` after window is open for a while, i +// think we need to have actual singleton on react side use bevy::prelude::*; #[wasm_bindgen] pub fn run() { From e3a07a545eeefba24d233674f787fa0a199eb3e6 Mon Sep 17 00:00:00 2001 From: Kevin King <4kevinking@gmail.com> Date: Mon, 21 Feb 2022 02:22:18 -0800 Subject: [PATCH 5/7] pass dimensions to bevy --- .vscode/settings.json | 6 ++++++ components/bevy.tsx | 6 ++++-- crates/bevy-example/src/lib.rs | 4 +++- pages/blog/benefits-of-bevy.mdx | 2 +- 4 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..dc337cc --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "rust-analyzer.linkedProjects": [ + "crates/bevy-example/Cargo.toml", + "rust/Cargo.toml", + ] +} \ No newline at end of file diff --git a/components/bevy.tsx b/components/bevy.tsx index 3afede6..9647954 100644 --- a/components/bevy.tsx +++ b/components/bevy.tsx @@ -1,10 +1,12 @@ import { useEffect } from "react"; import { run } from "../crates/bevy-example/pkg"; -export const BevyExample = () => { +const bevyGlobal = {bevy: null}; + +export const BevyExample = (props: {width: number; height: number}) => { useEffect(() => { try { - run(); + run(props.width, props.height); } catch (e) { console.error(e); } diff --git a/crates/bevy-example/src/lib.rs b/crates/bevy-example/src/lib.rs index 2b0c9e5..0c61ab3 100644 --- a/crates/bevy-example/src/lib.rs +++ b/crates/bevy-example/src/lib.rs @@ -13,10 +13,12 @@ pub fn greet() {} // think we need to have actual singleton on react side use bevy::prelude::*; #[wasm_bindgen] -pub fn run() { +pub fn run(width: f32, height: f32) { App::new() .insert_resource(WindowDescriptor { canvas: Some("#bevy-canvas".into()), + width, + height, ..Default::default() }) .add_plugins(DefaultPlugins) diff --git a/pages/blog/benefits-of-bevy.mdx b/pages/blog/benefits-of-bevy.mdx index e4fe436..2f8d882 100644 --- a/pages/blog/benefits-of-bevy.mdx +++ b/pages/blog/benefits-of-bevy.mdx @@ -17,4 +17,4 @@ export const meta = { -{} +{} From 16d281c3d69453ce8c172abb3f122e3ff097d804 Mon Sep 17 00:00:00 2001 From: Kevin King <4kevinking@gmail.com> Date: Mon, 21 Feb 2022 02:43:11 -0800 Subject: [PATCH 6/7] TODO --- crates/bevy-example/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/bevy-example/src/lib.rs b/crates/bevy-example/src/lib.rs index 0c61ab3..88c453c 100644 --- a/crates/bevy-example/src/lib.rs +++ b/crates/bevy-example/src/lib.rs @@ -8,7 +8,8 @@ static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; #[wasm_bindgen] pub fn greet() {} -// TODO: send canvas size to rust +// TODO: send reasonable canvas size to rust +// TODO: debug memory leak (happens at least on windows/FF) // TODO: sometimes hit `unreachable error` after window is open for a while, i // think we need to have actual singleton on react side use bevy::prelude::*; From d77e9ffa8cb951e5210673fc4199f2b2865f9410 Mon Sep 17 00:00:00 2001 From: Kevin King <4kevinking@gmail.com> Date: Mon, 21 Feb 2022 02:50:10 -0800 Subject: [PATCH 7/7] try default allocator --- crates/bevy-example/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bevy-example/src/lib.rs b/crates/bevy-example/src/lib.rs index 88c453c..e6f2aeb 100644 --- a/crates/bevy-example/src/lib.rs +++ b/crates/bevy-example/src/lib.rs @@ -2,14 +2,14 @@ mod utils; use wasm_bindgen::prelude::*; -#[global_allocator] -static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; +// #[global_allocator] +// static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; #[wasm_bindgen] pub fn greet() {} // TODO: send reasonable canvas size to rust -// TODO: debug memory leak (happens at least on windows/FF) +// TODO: debug memory leak (happens at least on windows/FF) -- switching off of wee_alloc may have fixed this? // TODO: sometimes hit `unreachable error` after window is open for a while, i // think we need to have actual singleton on react side use bevy::prelude::*;