Skip to content

Commit 8657959

Browse files
authored
Merge branch 'bevyengine:main' into main
2 parents 2206617 + 1df8238 commit 8657959

File tree

141 files changed

+1744
-1158
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

141 files changed

+1744
-1158
lines changed

Cargo.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3430,6 +3430,17 @@ description = "Demonstrates screen space reflections with water ripples"
34303430
category = "3D Rendering"
34313431
wasm = false
34323432

3433+
[[example]]
3434+
name = "camera_sub_view"
3435+
path = "examples/3d/camera_sub_view.rs"
3436+
doc-scrape-examples = true
3437+
3438+
[package.metadata.example.camera_sub_view]
3439+
name = "Camera sub view"
3440+
description = "Demonstrates using different sub view effects on a camera"
3441+
category = "3D Rendering"
3442+
wasm = true
3443+
34333444
[[example]]
34343445
name = "color_grading"
34353446
path = "examples/3d/color_grading.rs"

crates/bevy_animation/src/graph.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -508,11 +508,11 @@ impl AssetLoader for AnimationGraphAssetLoader {
508508

509509
type Error = AnimationGraphLoadError;
510510

511-
async fn load<'a>(
512-
&'a self,
513-
reader: &'a mut dyn Reader,
514-
_: &'a Self::Settings,
515-
load_context: &'a mut LoadContext<'_>,
511+
async fn load(
512+
&self,
513+
reader: &mut dyn Reader,
514+
_: &Self::Settings,
515+
load_context: &mut LoadContext<'_>,
516516
) -> Result<Self::Asset, Self::Error> {
517517
let mut bytes = Vec::new();
518518
reader.read_to_end(&mut bytes).await?;

crates/bevy_asset/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ async-lock = "3.0"
3636
crossbeam-channel = "0.5"
3737
downcast-rs = "1.2"
3838
disqualified = "1.0"
39+
either = "1.13"
3940
futures-io = "0.3"
4041
futures-lite = "2.0.1"
4142
blake3 = "1.5"

crates/bevy_asset/src/io/android.rs

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
use crate::io::{
2-
get_meta_path, AssetReader, AssetReaderError, EmptyPathStream, PathStream, Reader, VecReader,
3-
};
4-
use alloc::ffi::CString;
1+
use crate::io::{get_meta_path, AssetReader, AssetReaderError, PathStream, Reader, VecReader};
52
use bevy_utils::tracing::error;
6-
use std::path::Path;
3+
use futures_lite::stream;
4+
use std::{ffi::CString, path::Path};
75

86
/// [`AssetReader`] implementation for Android devices, built on top of Android's [`AssetManager`].
97
///
108
/// Implementation details:
119
///
12-
/// - [`load_path`](AssetIo::load_path) uses the [`AssetManager`] to load files.
13-
/// - [`read_directory`](AssetIo::read_directory) always returns an empty iterator.
10+
/// - All functions use the [`AssetManager`] to load files.
11+
/// - [`is_directory`](AssetReader::is_directory) tries to open the path
12+
/// as a normal file and treats an error as if the path is a directory.
1413
/// - Watching for changes is not supported. The watcher method will do nothing.
1514
///
1615
/// [AssetManager]: https://developer.android.com/reference/android/content/res/AssetManager
@@ -46,15 +45,53 @@ impl AssetReader for AndroidAssetReader {
4645

4746
async fn read_directory<'a>(
4847
&'a self,
49-
_path: &'a Path,
48+
path: &'a Path,
5049
) -> Result<Box<PathStream>, AssetReaderError> {
51-
let stream: Box<PathStream> = Box::new(EmptyPathStream);
52-
error!("Reading directories is not supported with the AndroidAssetReader");
53-
Ok(stream)
50+
let asset_manager = bevy_winit::ANDROID_APP
51+
.get()
52+
.expect("Bevy must be setup with the #[bevy_main] macro on Android")
53+
.asset_manager();
54+
let opened_assets_dir = asset_manager
55+
.open_dir(&CString::new(path.to_str().unwrap()).unwrap())
56+
.ok_or(AssetReaderError::NotFound(path.to_path_buf()))?;
57+
58+
let mapped_stream = opened_assets_dir
59+
.filter_map(move |f| {
60+
let file_path = path.join(Path::new(f.to_str().unwrap()));
61+
// filter out meta files as they are not considered assets
62+
if let Some(ext) = file_path.extension().and_then(|e| e.to_str()) {
63+
if ext.eq_ignore_ascii_case("meta") {
64+
return None;
65+
}
66+
}
67+
Some(file_path.to_owned())
68+
})
69+
.collect::<Vec<_>>();
70+
71+
let read_dir: Box<PathStream> = Box::new(stream::iter(mapped_stream));
72+
Ok(read_dir)
5473
}
5574

56-
async fn is_directory<'a>(&'a self, _path: &'a Path) -> Result<bool, AssetReaderError> {
57-
error!("Reading directories is not supported with the AndroidAssetReader");
58-
Ok(false)
75+
async fn is_directory<'a>(
76+
&'a self,
77+
path: &'a Path,
78+
) -> std::result::Result<bool, AssetReaderError> {
79+
let asset_manager = bevy_winit::ANDROID_APP
80+
.get()
81+
.expect("Bevy must be setup with the #[bevy_main] macro on Android")
82+
.asset_manager();
83+
// HACK: `AssetManager` does not provide a way to check if path
84+
// points to a directory or a file
85+
// `open_dir` succeeds for both files and directories and will only
86+
// fail if the path does not exist at all
87+
// `open` will fail for directories, but it will work for files
88+
// The solution here was to first use `open_dir` to eliminate the case
89+
// when the path does not exist at all, and then to use `open` to
90+
// see if that path is a file or a directory
91+
let cpath = CString::new(path.to_str().unwrap()).unwrap();
92+
let _ = asset_manager
93+
.open_dir(&cpath)
94+
.ok_or(AssetReaderError::NotFound(path.to_path_buf()))?;
95+
Ok(asset_manager.open(&cpath).is_none())
5996
}
6097
}

crates/bevy_asset/src/io/file/file_asset.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,35 @@
11
use crate::io::{
2-
get_meta_path, AssetReader, AssetReaderError, AssetWriter, AssetWriterError, PathStream,
3-
Reader, Writer,
2+
get_meta_path, AssetReader, AssetReaderError, AssetWriter, AssetWriterError, AsyncSeekForward,
3+
PathStream, Reader, Writer,
44
};
55
use async_fs::{read_dir, File};
6+
use futures_io::AsyncSeek;
67
use futures_lite::StreamExt;
78

9+
use core::{pin::Pin, task, task::Poll};
810
use std::path::Path;
911

1012
use super::{FileAssetReader, FileAssetWriter};
1113

14+
impl AsyncSeekForward for File {
15+
fn poll_seek_forward(
16+
mut self: Pin<&mut Self>,
17+
cx: &mut task::Context<'_>,
18+
offset: u64,
19+
) -> Poll<futures_io::Result<u64>> {
20+
let offset: Result<i64, _> = offset.try_into();
21+
22+
if let Ok(offset) = offset {
23+
Pin::new(&mut self).poll_seek(cx, futures_io::SeekFrom::Current(offset))
24+
} else {
25+
Poll::Ready(Err(std::io::Error::new(
26+
std::io::ErrorKind::InvalidInput,
27+
"seek position is out of range",
28+
)))
29+
}
30+
}
31+
}
32+
1233
impl Reader for File {}
1334

1435
impl AssetReader for FileAssetReader {

crates/bevy_asset/src/io/file/sync_file_asset.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
use futures_io::{AsyncRead, AsyncSeek, AsyncWrite};
1+
use futures_io::{AsyncRead, AsyncWrite};
22
use futures_lite::Stream;
33

44
use crate::io::{
5-
get_meta_path, AssetReader, AssetReaderError, AssetWriter, AssetWriterError, PathStream,
6-
Reader, Writer,
5+
get_meta_path, AssetReader, AssetReaderError, AssetWriter, AssetWriterError, AsyncSeekForward,
6+
PathStream, Reader, Writer,
77
};
88

99
use core::{pin::Pin, task::Poll};
@@ -29,14 +29,16 @@ impl AsyncRead for FileReader {
2929
}
3030
}
3131

32-
impl AsyncSeek for FileReader {
33-
fn poll_seek(
32+
impl AsyncSeekForward for FileReader {
33+
fn poll_seek_forward(
3434
self: Pin<&mut Self>,
3535
_cx: &mut core::task::Context<'_>,
36-
pos: std::io::SeekFrom,
36+
offset: u64,
3737
) -> Poll<std::io::Result<u64>> {
3838
let this = self.get_mut();
39-
let seek = this.0.seek(pos);
39+
let current = this.0.stream_position()?;
40+
let seek = this.0.seek(std::io::SeekFrom::Start(current + offset));
41+
4042
Poll::Ready(seek)
4143
}
4244
}

crates/bevy_asset/src/io/memory.rs

Lines changed: 13 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@ use crate::io::{AssetReader, AssetReaderError, PathStream, Reader};
22
use alloc::sync::Arc;
33
use bevy_utils::HashMap;
44
use core::{pin::Pin, task::Poll};
5-
use futures_io::{AsyncRead, AsyncSeek};
5+
use futures_io::AsyncRead;
66
use futures_lite::{ready, Stream};
77
use parking_lot::RwLock;
8-
use std::{
9-
io::SeekFrom,
10-
path::{Path, PathBuf},
11-
};
8+
use std::path::{Path, PathBuf};
9+
10+
use super::AsyncSeekForward;
1211

1312
#[derive(Default, Debug)]
1413
struct DirInternal {
@@ -247,37 +246,20 @@ impl AsyncRead for DataReader {
247246
}
248247
}
249248

250-
impl AsyncSeek for DataReader {
251-
fn poll_seek(
249+
impl AsyncSeekForward for DataReader {
250+
fn poll_seek_forward(
252251
mut self: Pin<&mut Self>,
253252
_cx: &mut core::task::Context<'_>,
254-
pos: SeekFrom,
253+
offset: u64,
255254
) -> Poll<std::io::Result<u64>> {
256-
let result = match pos {
257-
SeekFrom::Start(offset) => offset.try_into(),
258-
SeekFrom::End(offset) => self
259-
.data
260-
.value()
261-
.len()
262-
.try_into()
263-
.map(|len: i64| len - offset),
264-
SeekFrom::Current(offset) => self
265-
.bytes_read
266-
.try_into()
267-
.map(|bytes_read: i64| bytes_read + offset),
268-
};
255+
let result = self
256+
.bytes_read
257+
.try_into()
258+
.map(|bytes_read: u64| bytes_read + offset);
269259

270260
if let Ok(new_pos) = result {
271-
if new_pos < 0 {
272-
Poll::Ready(Err(std::io::Error::new(
273-
std::io::ErrorKind::InvalidInput,
274-
"seek position is out of range",
275-
)))
276-
} else {
277-
self.bytes_read = new_pos as _;
278-
279-
Poll::Ready(Ok(new_pos as _))
280-
}
261+
self.bytes_read = new_pos as _;
262+
Poll::Ready(Ok(new_pos as _))
281263
} else {
282264
Poll::Ready(Err(std::io::Error::new(
283265
std::io::ErrorKind::InvalidInput,

0 commit comments

Comments
 (0)