From 1b1e5e4a72f8e8453f8d124668090adcd6535079 Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Sun, 19 Nov 2023 04:33:47 +0100 Subject: [PATCH] Use low-level-wasm from bevy --- Cargo.toml | 9 ++++++++ examples/web_image.rs | 5 +---- src/web_asset_source.rs | 50 +++++++++++++++++++++++++++++++++++++++-- 3 files changed, 58 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index cd44b2e..6b92ff3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,13 +11,22 @@ version = "0.7.0" [dependencies] bevy = {version = "0.12", default-features = false, features = ["bevy_asset"]} + +[target.'cfg(not(target_arch = "wasm32"))'.dependencies] ehttp = "0.3" +[target.'cfg(target_arch = "wasm32")'.dependencies] +js-sys = {version = "0.3", default-features = false} +wasm-bindgen = {version = "0.2", default-features = false} +wasm-bindgen-futures = "0.4" +web-sys = {version = "0.3.22", default-features = false} + [dev-dependencies] bevy = {version = "0.12", default-features = false, features = [ "bevy_asset", "bevy_core_pipeline", "bevy_sprite", "png", + "webgl2", "x11", # GitHub Actions runners don't have libxkbcommon installed, so can't use Wayland ]} diff --git a/examples/web_image.rs b/examples/web_image.rs index 51ea8fd..e69303f 100644 --- a/examples/web_image.rs +++ b/examples/web_image.rs @@ -16,10 +16,7 @@ fn setup(mut commands: Commands, asset_server: Res) { commands.spawn(SpriteBundle { // Simply use a url where you would normally use an asset folder relative path - texture: asset_server.load( - // TODO: `https://s3.johanhelsing.studio/dump/favicon.png` doesn't seem to work - "https://raw.githubusercontent.com/johanhelsing/bevy_web_asset/main/assets/favicon.png", - ), + texture: asset_server.load("https://s3.johanhelsing.studio/dump/favicon.png"), ..default() }); } diff --git a/src/web_asset_source.rs b/src/web_asset_source.rs index 7bbff63..b7dccf6 100644 --- a/src/web_asset_source.rs +++ b/src/web_asset_source.rs @@ -1,5 +1,4 @@ -use bevy::asset::io::PathStream; -use bevy::utils::BoxedFuture; +use bevy::{asset::io::PathStream, utils::BoxedFuture}; use std::path::{Path, PathBuf}; use bevy::asset::io::{AssetReader, AssetReaderError, Reader, VecReader}; @@ -33,6 +32,53 @@ impl WebAssetReader { } } +#[cfg(target_arch = "wasm32")] +async fn get<'a>(path: PathBuf) -> Result>, AssetReaderError> { + use js_sys::Uint8Array; + use wasm_bindgen::JsCast; + use wasm_bindgen_futures::JsFuture; + use web_sys::Response; + + fn js_value_to_err<'a>( + context: &'a str, + ) -> impl FnOnce(wasm_bindgen::JsValue) -> std::io::Error + 'a { + move |value| { + let message = match js_sys::JSON::stringify(&value) { + Ok(js_str) => format!("Failed to {context}: {js_str}"), + Err(_) => { + format!( + "Failed to {context} and also failed to stringify the JSValue of the error" + ) + } + }; + + std::io::Error::new(std::io::ErrorKind::Other, message) + } + } + + let window = web_sys::window().unwrap(); + let resp_value = JsFuture::from(window.fetch_with_str(path.to_str().unwrap())) + .await + .map_err(js_value_to_err("fetch path"))?; + let resp = resp_value + .dyn_into::() + .map_err(js_value_to_err("convert fetch to Response"))?; + match resp.status() { + 200 => { + let data = JsFuture::from(resp.array_buffer().unwrap()).await.unwrap(); + let bytes = Uint8Array::new(&data).to_vec(); + let reader: Box = Box::new(VecReader::new(bytes)); + Ok(reader) + } + 404 => Err(AssetReaderError::NotFound(path)), + status => Err(AssetReaderError::Io(std::io::Error::new( + std::io::ErrorKind::Other, + format!("Encountered unexpected HTTP status {status}"), + ))), + } +} + +#[cfg(not(target_arch = "wasm32"))] async fn get<'a>(uri: PathBuf) -> Result>, AssetReaderError> { use ehttp::{fetch, Request}; use std::future::Future;