Compare commits
42 Commits
custom
...
release-0.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
55215706f2 | ||
![]() |
a66bdd074f | ||
![]() |
d2e794f112 | ||
![]() |
2278c1edbb | ||
![]() |
76f09e5be2 | ||
![]() |
17005b3c8b | ||
![]() |
9f24bd8705 | ||
![]() |
3b97fd625a | ||
![]() |
5c6628fe3c | ||
![]() |
cc153ec930 | ||
![]() |
3c3241a803 | ||
![]() |
0767e62112 | ||
![]() |
2683dfeee8 | ||
![]() |
6e6e99efdd | ||
![]() |
7f9ebfd603 | ||
![]() |
cb76dbbe97 | ||
![]() |
54f0c556f6 | ||
![]() |
db9d84fb2f | ||
![]() |
f4df8b8545 | ||
![]() |
7caa026806 | ||
![]() |
b8c58dedd9 | ||
![]() |
8234978ab0 | ||
![]() |
faa1387720 | ||
![]() |
d6e6814ac3 | ||
![]() |
b1f061586d | ||
![]() |
784b9bd945 | ||
![]() |
5bf5d48759 | ||
![]() |
d62319be38 | ||
![]() |
a8fa1f77b9 | ||
![]() |
0e75d0066e | ||
![]() |
4022385f51 | ||
![]() |
48d93b8e68 | ||
![]() |
f268c69402 | ||
![]() |
6b26a41a9d | ||
![]() |
bbd38e735f | ||
![]() |
4e24b68fa6 | ||
![]() |
152ee42a72 | ||
![]() |
5d9c9b85d5 | ||
![]() |
2a3e367b82 | ||
![]() |
1e57ca6f5e | ||
![]() |
b46c11c134 | ||
![]() |
63a3da8703 |
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -142,8 +142,6 @@ jobs:
|
||||
target: wasm32-unknown-unknown
|
||||
- name: Check wasm
|
||||
run: cargo check --target wasm32-unknown-unknown
|
||||
env:
|
||||
RUSTFLAGS: --cfg=web_sys_unstable_apis
|
||||
|
||||
markdownlint:
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
categories = ["game-engines", "graphics", "gui", "rendering"]
|
||||
description = "A refreshingly simple data-driven game engine and app framework"
|
||||
@ -289,7 +289,7 @@ pbr_transmission_textures = ["bevy_internal/pbr_transmission_textures"]
|
||||
# Enable some limitations to be able to use WebGL2. Please refer to the [WebGL2 and WebGPU](https://github.com/bevyengine/bevy/tree/latest/examples#webgl2-and-webgpu) section of the examples README for more information on how to run Wasm builds with WebGPU.
|
||||
webgl2 = ["bevy_internal/webgl"]
|
||||
|
||||
# Enable support for WebGPU in Wasm. When enabled, this feature will override the `webgl2` feature and you won't be able to run Wasm builds with WebGL2, only with WebGPU. Requires the `RUSTFLAGS` environment variable to be set to `--cfg=web_sys_unstable_apis` when building.
|
||||
# Enable support for WebGPU in Wasm. When enabled, this feature will override the `webgl2` feature and you won't be able to run Wasm builds with WebGL2, only with WebGPU.
|
||||
webgpu = ["bevy_internal/webgpu"]
|
||||
|
||||
# Enables the built-in asset processor for processed assets.
|
||||
@ -305,8 +305,8 @@ embedded_watcher = ["bevy_internal/embedded_watcher"]
|
||||
bevy_debug_stepping = ["bevy_internal/bevy_debug_stepping"]
|
||||
|
||||
[dependencies]
|
||||
bevy_dylib = { path = "crates/bevy_dylib", version = "0.13.0", default-features = false, optional = true }
|
||||
bevy_internal = { path = "crates/bevy_internal", version = "0.13.0", default-features = false }
|
||||
bevy_dylib = { path = "crates/bevy_dylib", version = "0.13.1", default-features = false, optional = true }
|
||||
bevy_internal = { path = "crates/bevy_internal", version = "0.13.1", default-features = false }
|
||||
|
||||
[dev-dependencies]
|
||||
rand = "0.8.0"
|
||||
|
@ -19,4 +19,5 @@ criterion_group!(
|
||||
contrived,
|
||||
schedule,
|
||||
build_schedule,
|
||||
empty_schedule_run,
|
||||
);
|
||||
|
@ -118,3 +118,28 @@ pub fn build_schedule(criterion: &mut Criterion) {
|
||||
|
||||
group.finish();
|
||||
}
|
||||
|
||||
pub fn empty_schedule_run(criterion: &mut Criterion) {
|
||||
let mut app = bevy_app::App::default();
|
||||
|
||||
let mut group = criterion.benchmark_group("run_empty_schedule");
|
||||
|
||||
let mut schedule = Schedule::default();
|
||||
schedule.set_executor_kind(bevy_ecs::schedule::ExecutorKind::SingleThreaded);
|
||||
group.bench_function("SingleThreaded", |bencher| {
|
||||
bencher.iter(|| schedule.run(&mut app.world));
|
||||
});
|
||||
|
||||
let mut schedule = Schedule::default();
|
||||
schedule.set_executor_kind(bevy_ecs::schedule::ExecutorKind::MultiThreaded);
|
||||
group.bench_function("MultiThreaded", |bencher| {
|
||||
bencher.iter(|| schedule.run(&mut app.world));
|
||||
});
|
||||
|
||||
let mut schedule = Schedule::default();
|
||||
schedule.set_executor_kind(bevy_ecs::schedule::ExecutorKind::Simple);
|
||||
group.bench_function("Simple", |bencher| {
|
||||
bencher.iter(|| schedule.run(&mut app.world));
|
||||
});
|
||||
group.finish();
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_a11y"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Provides accessibility support for Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -10,9 +10,9 @@ keywords = ["bevy", "accessibility", "a11y"]
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.0" }
|
||||
bevy_derive = { path = "../bevy_derive", version = "0.13.0" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.0" }
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.1" }
|
||||
bevy_derive = { path = "../bevy_derive", version = "0.13.1" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.1" }
|
||||
|
||||
accesskit = "0.12"
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_animation"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Provides animation functionality for Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -10,19 +10,19 @@ keywords = ["bevy"]
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.0" }
|
||||
bevy_asset = { path = "../bevy_asset", version = "0.13.0" }
|
||||
bevy_core = { path = "../bevy_core", version = "0.13.0" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.0" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.0", features = [
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.1" }
|
||||
bevy_asset = { path = "../bevy_asset", version = "0.13.1" }
|
||||
bevy_core = { path = "../bevy_core", version = "0.13.1" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.1" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.1", features = [
|
||||
"bevy",
|
||||
] }
|
||||
bevy_render = { path = "../bevy_render", version = "0.13.0" }
|
||||
bevy_time = { path = "../bevy_time", version = "0.13.0" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.0" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.0" }
|
||||
bevy_transform = { path = "../bevy_transform", version = "0.13.0" }
|
||||
bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.13.0" }
|
||||
bevy_render = { path = "../bevy_render", version = "0.13.1" }
|
||||
bevy_time = { path = "../bevy_time", version = "0.13.1" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.1" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.1" }
|
||||
bevy_transform = { path = "../bevy_transform", version = "0.13.1" }
|
||||
bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.13.1" }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_app"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Provides core App functionality for Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -17,11 +17,11 @@ bevy_reflect = ["dep:bevy_reflect", "bevy_ecs/bevy_reflect"]
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
bevy_derive = { path = "../bevy_derive", version = "0.13.0" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.0", default-features = false }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.0", optional = true }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.0" }
|
||||
bevy_tasks = { path = "../bevy_tasks", version = "0.13.0" }
|
||||
bevy_derive = { path = "../bevy_derive", version = "0.13.1" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.1", default-features = false }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.1", optional = true }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.1" }
|
||||
bevy_tasks = { path = "../bevy_tasks", version = "0.13.1" }
|
||||
|
||||
# other
|
||||
serde = { version = "1.0", features = ["derive"], optional = true }
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_asset"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Provides asset functionality for Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -18,13 +18,13 @@ asset_processor = []
|
||||
watch = []
|
||||
|
||||
[dependencies]
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.0" }
|
||||
bevy_asset_macros = { path = "macros", version = "0.13.0" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.0" }
|
||||
bevy_log = { path = "../bevy_log", version = "0.13.0" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.0" }
|
||||
bevy_tasks = { path = "../bevy_tasks", version = "0.13.0" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.0" }
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.1" }
|
||||
bevy_asset_macros = { path = "macros", version = "0.13.1" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.1" }
|
||||
bevy_log = { path = "../bevy_log", version = "0.13.1" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.1" }
|
||||
bevy_tasks = { path = "../bevy_tasks", version = "0.13.1" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.1" }
|
||||
|
||||
async-broadcast = "0.5"
|
||||
async-fs = "2.0"
|
||||
@ -40,7 +40,7 @@ serde = { version = "1", features = ["derive"] }
|
||||
thiserror = "1.0"
|
||||
|
||||
[target.'cfg(target_os = "android")'.dependencies]
|
||||
bevy_winit = { path = "../bevy_winit", version = "0.13.0" }
|
||||
bevy_winit = { path = "../bevy_winit", version = "0.13.1" }
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
wasm-bindgen = { version = "0.2" }
|
||||
@ -52,7 +52,7 @@ js-sys = "0.3"
|
||||
notify-debouncer-full = { version = "0.3.1", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
bevy_core = { path = "../bevy_core", version = "0.13.0" }
|
||||
bevy_core = { path = "../bevy_core", version = "0.13.1" }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_asset_macros"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Derive implementations for bevy_asset"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -12,7 +12,7 @@ keywords = ["bevy"]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
bevy_macro_utils = { path = "../../bevy_macro_utils", version = "0.13.0" }
|
||||
bevy_macro_utils = { path = "../../bevy_macro_utils", version = "0.13.1" }
|
||||
|
||||
syn = "2.0"
|
||||
proc-macro2 = "1.0"
|
||||
|
@ -503,10 +503,8 @@ impl<A: Asset> Assets<A> {
|
||||
while let Ok(drop_event) = assets.handle_provider.drop_receiver.try_recv() {
|
||||
let id = drop_event.id.typed();
|
||||
|
||||
assets.queued_events.push(AssetEvent::Unused { id });
|
||||
|
||||
if drop_event.asset_server_managed {
|
||||
let untyped_id = drop_event.id.untyped(TypeId::of::<A>());
|
||||
let untyped_id = id.untyped();
|
||||
if let Some(info) = infos.get(untyped_id) {
|
||||
if info.load_state == LoadState::Loading
|
||||
|| info.load_state == LoadState::NotLoaded
|
||||
@ -515,12 +513,16 @@ impl<A: Asset> Assets<A> {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if infos.process_handle_drop(untyped_id) {
|
||||
assets.remove_dropped(id);
|
||||
|
||||
// the process_handle_drop call checks whether new handles have been created since the drop event was fired, before removing the asset
|
||||
if !infos.process_handle_drop(untyped_id) {
|
||||
// a new handle has been created, or the asset doesn't exist
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
assets.remove_dropped(id);
|
||||
}
|
||||
|
||||
assets.queued_events.push(AssetEvent::Unused { id });
|
||||
assets.remove_dropped(id);
|
||||
}
|
||||
|
||||
// TODO: this is _extremely_ inefficient find a better fix
|
||||
|
@ -75,16 +75,15 @@ impl FileAssetWriter {
|
||||
///
|
||||
/// See `get_base_path` below.
|
||||
pub fn new<P: AsRef<Path> + std::fmt::Debug>(path: P, create_root: bool) -> Self {
|
||||
let root_path = get_base_path().join(path.as_ref());
|
||||
if create_root {
|
||||
if let Err(e) = std::fs::create_dir_all(&path) {
|
||||
if let Err(e) = std::fs::create_dir_all(&root_path) {
|
||||
error!(
|
||||
"Failed to create root directory {:?} for file asset writer: {:?}",
|
||||
path, e
|
||||
root_path, e
|
||||
);
|
||||
}
|
||||
}
|
||||
Self {
|
||||
root_path: get_base_path().join(path.as_ref()),
|
||||
}
|
||||
Self { root_path }
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_audio"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Provides audio functionality for Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -10,22 +10,22 @@ keywords = ["bevy"]
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.0" }
|
||||
bevy_asset = { path = "../bevy_asset", version = "0.13.0" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.0" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.0" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.0", features = [
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.1" }
|
||||
bevy_asset = { path = "../bevy_asset", version = "0.13.1" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.1" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.1" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.1", features = [
|
||||
"bevy",
|
||||
] }
|
||||
bevy_transform = { path = "../bevy_transform", version = "0.13.0" }
|
||||
bevy_derive = { path = "../bevy_derive", version = "0.13.0" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.0" }
|
||||
bevy_transform = { path = "../bevy_transform", version = "0.13.1" }
|
||||
bevy_derive = { path = "../bevy_derive", version = "0.13.1" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.1" }
|
||||
|
||||
# other
|
||||
rodio = { version = "0.17", default-features = false }
|
||||
|
||||
[target.'cfg(target_os = "android")'.dependencies]
|
||||
oboe = { version = "0.5", optional = true }
|
||||
cpal = { version = "0.15", optional = true }
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
rodio = { version = "0.17", default-features = false, features = [
|
||||
@ -45,7 +45,7 @@ symphonia-isomp4 = ["rodio/symphonia-isomp4"]
|
||||
symphonia-vorbis = ["rodio/symphonia-vorbis"]
|
||||
symphonia-wav = ["rodio/symphonia-wav"]
|
||||
# Enable using a shared stdlib for cxx on Android.
|
||||
android_shared_stdcxx = ["oboe/shared-stdcxx"]
|
||||
android_shared_stdcxx = ["cpal/oboe-shared-stdcxx"]
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_core"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Provides core functionality for Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -11,18 +11,18 @@ keywords = ["bevy"]
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.0", features = [
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.1", features = [
|
||||
"bevy_reflect",
|
||||
] }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.0", features = [
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.1", features = [
|
||||
"bevy_reflect",
|
||||
] }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.0" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.0", features = [
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.1" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.1", features = [
|
||||
"bevy",
|
||||
] }
|
||||
bevy_tasks = { path = "../bevy_tasks", version = "0.13.0" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.0" }
|
||||
bevy_tasks = { path = "../bevy_tasks", version = "0.13.1" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.1" }
|
||||
|
||||
# other
|
||||
bytemuck = "1.5"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_core_pipeline"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
authors = [
|
||||
"Bevy Contributors <bevyengine@gmail.com>",
|
||||
@ -13,7 +13,7 @@ license = "MIT OR Apache-2.0"
|
||||
keywords = ["bevy"]
|
||||
|
||||
[features]
|
||||
dds = []
|
||||
dds = ["bevy_render/dds"]
|
||||
trace = []
|
||||
webgl = []
|
||||
webgpu = []
|
||||
@ -21,17 +21,17 @@ tonemapping_luts = ["bevy_render/ktx2", "bevy_render/zstd"]
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.0" }
|
||||
bevy_asset = { path = "../bevy_asset", version = "0.13.0" }
|
||||
bevy_core = { path = "../bevy_core", version = "0.13.0" }
|
||||
bevy_derive = { path = "../bevy_derive", version = "0.13.0" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.0" }
|
||||
bevy_log = { path = "../bevy_log", version = "0.13.0" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.0" }
|
||||
bevy_render = { path = "../bevy_render", version = "0.13.0" }
|
||||
bevy_transform = { path = "../bevy_transform", version = "0.13.0" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.0" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.0" }
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.1" }
|
||||
bevy_asset = { path = "../bevy_asset", version = "0.13.1" }
|
||||
bevy_core = { path = "../bevy_core", version = "0.13.1" }
|
||||
bevy_derive = { path = "../bevy_derive", version = "0.13.1" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.1" }
|
||||
bevy_log = { path = "../bevy_log", version = "0.13.1" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.1" }
|
||||
bevy_render = { path = "../bevy_render", version = "0.13.1" }
|
||||
bevy_transform = { path = "../bevy_transform", version = "0.13.1" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.1" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.1" }
|
||||
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
bitflags = "2.3"
|
||||
|
@ -106,6 +106,8 @@ pub struct BloomSettings {
|
||||
|
||||
impl BloomSettings {
|
||||
/// The default bloom preset.
|
||||
///
|
||||
/// This uses the [`EnergyConserving`](BloomCompositeMode::EnergyConserving) composite mode.
|
||||
pub const NATURAL: Self = Self {
|
||||
intensity: 0.15,
|
||||
low_frequency_boost: 0.7,
|
||||
|
@ -93,6 +93,12 @@ impl ExtractComponent for Skybox {
|
||||
skybox.clone(),
|
||||
SkyboxUniforms {
|
||||
brightness: skybox.brightness * exposure,
|
||||
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
|
||||
_wasm_padding_8b: 0,
|
||||
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
|
||||
_wasm_padding_12b: 0,
|
||||
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
|
||||
_wasm_padding_16b: 0,
|
||||
},
|
||||
))
|
||||
}
|
||||
@ -102,6 +108,12 @@ impl ExtractComponent for Skybox {
|
||||
#[derive(Component, ShaderType, Clone)]
|
||||
pub struct SkyboxUniforms {
|
||||
brightness: f32,
|
||||
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
|
||||
_wasm_padding_8b: u32,
|
||||
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
|
||||
_wasm_padding_12b: u32,
|
||||
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
|
||||
_wasm_padding_16b: u32,
|
||||
}
|
||||
|
||||
#[derive(Resource)]
|
||||
|
@ -1,10 +1,19 @@
|
||||
#import bevy_render::view::View
|
||||
#import bevy_pbr::utils::coords_to_viewport_uv
|
||||
|
||||
struct SkyboxUniforms {
|
||||
brightness: f32,
|
||||
#ifdef SIXTEEN_BYTE_ALIGNMENT
|
||||
_wasm_padding_8b: u32,
|
||||
_wasm_padding_12b: u32,
|
||||
_wasm_padding_16b: u32,
|
||||
#endif
|
||||
}
|
||||
|
||||
@group(0) @binding(0) var skybox: texture_cube<f32>;
|
||||
@group(0) @binding(1) var skybox_sampler: sampler;
|
||||
@group(0) @binding(2) var<uniform> view: View;
|
||||
@group(0) @binding(3) var<uniform> brightness: f32;
|
||||
@group(0) @binding(3) var<uniform> uniforms: SkyboxUniforms;
|
||||
|
||||
fn coords_to_ray_direction(position: vec2<f32>, viewport: vec4<f32>) -> vec3<f32> {
|
||||
// Using world positions of the fragment and camera to calculate a ray direction
|
||||
@ -63,5 +72,5 @@ fn skybox_fragment(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||
let ray_direction = coords_to_ray_direction(in.position.xy, view.viewport);
|
||||
|
||||
// Cube maps are left-handed so we negate the z coordinate.
|
||||
return textureSample(skybox, skybox_sampler, ray_direction * vec3(1.0, 1.0, -1.0)) * brightness;
|
||||
return textureSample(skybox, skybox_sampler, ray_direction * vec3(1.0, 1.0, -1.0)) * uniforms.brightness;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_derive"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Provides derive implementations for Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -12,7 +12,7 @@ keywords = ["bevy"]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
bevy_macro_utils = { path = "../bevy_macro_utils", version = "0.13.0" }
|
||||
bevy_macro_utils = { path = "../bevy_macro_utils", version = "0.13.1" }
|
||||
|
||||
quote = "1.0"
|
||||
syn = { version = "2.0", features = ["full"] }
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_diagnostic"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Provides diagnostic functionality for Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -14,12 +14,12 @@ dynamic_linking = []
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.0" }
|
||||
bevy_core = { path = "../bevy_core", version = "0.13.0" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.0" }
|
||||
bevy_log = { path = "../bevy_log", version = "0.13.0" }
|
||||
bevy_time = { path = "../bevy_time", version = "0.13.0" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.0" }
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.1" }
|
||||
bevy_core = { path = "../bevy_core", version = "0.13.1" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.1" }
|
||||
bevy_log = { path = "../bevy_log", version = "0.13.1" }
|
||||
bevy_time = { path = "../bevy_time", version = "0.13.1" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.1" }
|
||||
|
||||
const-fnv1a-hash = "1.1.0"
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_dylib"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Force the Bevy Engine to be dynamically linked for faster linking"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -12,7 +12,7 @@ keywords = ["bevy"]
|
||||
crate-type = ["dylib"]
|
||||
|
||||
[dependencies]
|
||||
bevy_internal = { path = "../bevy_internal", version = "0.13.0", default-features = false }
|
||||
bevy_internal = { path = "../bevy_internal", version = "0.13.1", default-features = false }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_dynamic_plugin"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Provides dynamic plugin loading capabilities for non-wasm platforms"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -10,7 +10,7 @@ keywords = ["bevy"]
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.0" }
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.1" }
|
||||
|
||||
# other
|
||||
libloading = { version = "0.8" }
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_ecs"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Bevy Engine's entity component system"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -16,11 +16,11 @@ bevy_debug_stepping = []
|
||||
default = ["bevy_reflect", "bevy_debug_stepping"]
|
||||
|
||||
[dependencies]
|
||||
bevy_ptr = { path = "../bevy_ptr", version = "0.13.0" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.0", optional = true }
|
||||
bevy_tasks = { path = "../bevy_tasks", version = "0.13.0" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.0" }
|
||||
bevy_ecs_macros = { path = "macros", version = "0.13.0" }
|
||||
bevy_ptr = { path = "../bevy_ptr", version = "0.13.1" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.1", optional = true }
|
||||
bevy_tasks = { path = "../bevy_tasks", version = "0.13.1" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.1" }
|
||||
bevy_ecs_macros = { path = "macros", version = "0.13.1" }
|
||||
|
||||
async-channel = "2.1.0"
|
||||
thread_local = "1.1.4"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_ecs_macros"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
description = "Bevy ECS Macros"
|
||||
edition = "2021"
|
||||
license = "MIT OR Apache-2.0"
|
||||
@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0"
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
bevy_macro_utils = { path = "../../bevy_macro_utils", version = "0.13.0" }
|
||||
bevy_macro_utils = { path = "../../bevy_macro_utils", version = "0.13.1" }
|
||||
|
||||
syn = "2.0"
|
||||
quote = "1.0"
|
||||
|
@ -21,8 +21,8 @@ pub(super) trait SystemExecutor: Send + Sync {
|
||||
fn run(
|
||||
&mut self,
|
||||
schedule: &mut SystemSchedule,
|
||||
skip_systems: Option<FixedBitSet>,
|
||||
world: &mut World,
|
||||
skip_systems: Option<&FixedBitSet>,
|
||||
);
|
||||
fn set_apply_final_deferred(&mut self, value: bool);
|
||||
}
|
||||
|
@ -166,8 +166,8 @@ impl SystemExecutor for MultiThreadedExecutor {
|
||||
fn run(
|
||||
&mut self,
|
||||
schedule: &mut SystemSchedule,
|
||||
_skip_systems: Option<FixedBitSet>,
|
||||
world: &mut World,
|
||||
_skip_systems: Option<&FixedBitSet>,
|
||||
) {
|
||||
// reset counts
|
||||
self.num_systems = schedule.systems.len();
|
||||
@ -189,26 +189,18 @@ impl SystemExecutor for MultiThreadedExecutor {
|
||||
// If stepping is enabled, make sure we skip those systems that should
|
||||
// not be run.
|
||||
#[cfg(feature = "bevy_debug_stepping")]
|
||||
if let Some(mut skipped_systems) = _skip_systems {
|
||||
if let Some(skipped_systems) = _skip_systems {
|
||||
debug_assert_eq!(skipped_systems.len(), self.completed_systems.len());
|
||||
// mark skipped systems as completed
|
||||
self.completed_systems |= &skipped_systems;
|
||||
self.completed_systems |= skipped_systems;
|
||||
self.num_completed_systems = self.completed_systems.count_ones(..);
|
||||
|
||||
// signal the dependencies for each of the skipped systems, as
|
||||
// though they had run
|
||||
for system_index in skipped_systems.ones() {
|
||||
self.signal_dependents(system_index);
|
||||
self.ready_systems.set(system_index, false);
|
||||
}
|
||||
|
||||
// Finally, we need to clear all skipped systems from the ready
|
||||
// list.
|
||||
//
|
||||
// We invert the skipped system mask to get the list of systems
|
||||
// that should be run. Then we bitwise AND it with the ready list,
|
||||
// resulting in a list of ready systems that aren't skipped.
|
||||
skipped_systems.toggle_range(..);
|
||||
self.ready_systems &= skipped_systems;
|
||||
}
|
||||
|
||||
let thread_executor = world
|
||||
|
@ -4,7 +4,9 @@ use fixedbitset::FixedBitSet;
|
||||
use std::panic::AssertUnwindSafe;
|
||||
|
||||
use crate::{
|
||||
schedule::{BoxedCondition, ExecutorKind, SystemExecutor, SystemSchedule},
|
||||
schedule::{
|
||||
executor::is_apply_deferred, BoxedCondition, ExecutorKind, SystemExecutor, SystemSchedule,
|
||||
},
|
||||
world::World,
|
||||
};
|
||||
|
||||
@ -33,15 +35,15 @@ impl SystemExecutor for SimpleExecutor {
|
||||
fn run(
|
||||
&mut self,
|
||||
schedule: &mut SystemSchedule,
|
||||
_skip_systems: Option<FixedBitSet>,
|
||||
world: &mut World,
|
||||
_skip_systems: Option<&FixedBitSet>,
|
||||
) {
|
||||
// If stepping is enabled, make sure we skip those systems that should
|
||||
// not be run.
|
||||
#[cfg(feature = "bevy_debug_stepping")]
|
||||
if let Some(skipped_systems) = _skip_systems {
|
||||
// mark skipped systems as completed
|
||||
self.completed_systems |= &skipped_systems;
|
||||
self.completed_systems |= skipped_systems;
|
||||
}
|
||||
|
||||
for system_index in 0..schedule.systems.len() {
|
||||
@ -86,6 +88,10 @@ impl SystemExecutor for SimpleExecutor {
|
||||
}
|
||||
|
||||
let system = &mut schedule.systems[system_index];
|
||||
if is_apply_deferred(system) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let res = std::panic::catch_unwind(AssertUnwindSafe(|| {
|
||||
system.run((), world);
|
||||
}));
|
||||
@ -125,3 +131,16 @@ fn evaluate_and_fold_conditions(conditions: &mut [BoxedCondition], world: &mut W
|
||||
.map(|condition| condition.run((), world))
|
||||
.fold(true, |acc, res| acc && res)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[test]
|
||||
fn skip_automatic_sync_points() {
|
||||
// Schedules automatically insert appy_deferred systems, but these should
|
||||
// not be executed as they only serve as markers and are not initialized
|
||||
use crate::prelude::*;
|
||||
let mut sched = Schedule::default();
|
||||
sched.set_executor_kind(ExecutorKind::Simple);
|
||||
sched.add_systems((|_: Commands| (), || ()).chain());
|
||||
let mut world = World::new();
|
||||
sched.run(&mut world);
|
||||
}
|
||||
|
@ -41,15 +41,15 @@ impl SystemExecutor for SingleThreadedExecutor {
|
||||
fn run(
|
||||
&mut self,
|
||||
schedule: &mut SystemSchedule,
|
||||
_skip_systems: Option<FixedBitSet>,
|
||||
world: &mut World,
|
||||
_skip_systems: Option<&FixedBitSet>,
|
||||
) {
|
||||
// If stepping is enabled, make sure we skip those systems that should
|
||||
// not be run.
|
||||
#[cfg(feature = "bevy_debug_stepping")]
|
||||
if let Some(skipped_systems) = _skip_systems {
|
||||
// mark skipped systems as completed
|
||||
self.completed_systems |= &skipped_systems;
|
||||
self.completed_systems |= skipped_systems;
|
||||
}
|
||||
|
||||
for system_index in 0..schedule.systems.len() {
|
||||
|
@ -333,15 +333,18 @@ impl Schedule {
|
||||
.unwrap_or_else(|e| panic!("Error when initializing schedule {:?}: {e}", self.label));
|
||||
|
||||
#[cfg(not(feature = "bevy_debug_stepping"))]
|
||||
let skip_systems = None;
|
||||
self.executor.run(&mut self.executable, world, None);
|
||||
|
||||
#[cfg(feature = "bevy_debug_stepping")]
|
||||
let skip_systems = match world.get_resource_mut::<Stepping>() {
|
||||
None => None,
|
||||
Some(mut stepping) => stepping.skipped_systems(self),
|
||||
};
|
||||
{
|
||||
let skip_systems = match world.get_resource_mut::<Stepping>() {
|
||||
None => None,
|
||||
Some(mut stepping) => stepping.skipped_systems(self),
|
||||
};
|
||||
|
||||
self.executor.run(&mut self.executable, skip_systems, world);
|
||||
self.executor
|
||||
.run(&mut self.executable, world, skip_systems.as_ref());
|
||||
}
|
||||
}
|
||||
|
||||
/// Initializes any newly-added systems and conditions, rebuilds the executable schedule,
|
||||
|
@ -9,7 +9,8 @@ use bevy_utils::intern::Interned;
|
||||
pub use bevy_utils::label::DynEq;
|
||||
|
||||
use crate::system::{
|
||||
ExclusiveSystemParamFunction, IsExclusiveFunctionSystem, IsFunctionSystem, SystemParamFunction,
|
||||
ExclusiveFunctionSystem, ExclusiveSystemParamFunction, FunctionSystem,
|
||||
IsExclusiveFunctionSystem, IsFunctionSystem, SystemParamFunction,
|
||||
};
|
||||
|
||||
define_label!(
|
||||
@ -167,26 +168,28 @@ impl<S: SystemSet> IntoSystemSet<()> for S {
|
||||
// systems
|
||||
impl<Marker, F> IntoSystemSet<(IsFunctionSystem, Marker)> for F
|
||||
where
|
||||
Marker: 'static,
|
||||
F: SystemParamFunction<Marker>,
|
||||
{
|
||||
type Set = SystemTypeSet<Self>;
|
||||
type Set = SystemTypeSet<FunctionSystem<Marker, F>>;
|
||||
|
||||
#[inline]
|
||||
fn into_system_set(self) -> Self::Set {
|
||||
SystemTypeSet::new()
|
||||
SystemTypeSet::<FunctionSystem<Marker, F>>::new()
|
||||
}
|
||||
}
|
||||
|
||||
// exclusive systems
|
||||
impl<Marker, F> IntoSystemSet<(IsExclusiveFunctionSystem, Marker)> for F
|
||||
where
|
||||
Marker: 'static,
|
||||
F: ExclusiveSystemParamFunction<Marker>,
|
||||
{
|
||||
type Set = SystemTypeSet<Self>;
|
||||
type Set = SystemTypeSet<ExclusiveFunctionSystem<Marker, F>>;
|
||||
|
||||
#[inline]
|
||||
fn into_system_set(self) -> Self::Set {
|
||||
SystemTypeSet::new()
|
||||
SystemTypeSet::<ExclusiveFunctionSystem<Marker, F>>::new()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,7 +143,7 @@ where
|
||||
}
|
||||
|
||||
fn default_system_sets(&self) -> Vec<InternedSystemSet> {
|
||||
let set = crate::schedule::SystemTypeSet::<F>::new();
|
||||
let set = crate::schedule::SystemTypeSet::<Self>::new();
|
||||
vec![set.intern()]
|
||||
}
|
||||
|
||||
|
@ -536,7 +536,7 @@ where
|
||||
}
|
||||
|
||||
fn default_system_sets(&self) -> Vec<InternedSystemSet> {
|
||||
let set = crate::schedule::SystemTypeSet::<F>::new();
|
||||
let set = crate::schedule::SystemTypeSet::<Self>::new();
|
||||
vec![set.intern()]
|
||||
}
|
||||
|
||||
|
@ -38,9 +38,11 @@ impl<I, O> RemovedSystem<I, O> {
|
||||
///
|
||||
/// These are opaque identifiers, keyed to a specific [`World`],
|
||||
/// and are created via [`World::register_system`].
|
||||
#[derive(Eq)]
|
||||
pub struct SystemId<I = (), O = ()>(Entity, std::marker::PhantomData<fn(I) -> O>);
|
||||
|
||||
// A manual impl is used because the trait bounds should ignore the `I` and `O` phantom parameters.
|
||||
impl<I, O> Eq for SystemId<I, O> {}
|
||||
|
||||
// A manual impl is used because the trait bounds should ignore the `I` and `O` phantom parameters.
|
||||
impl<I, O> Copy for SystemId<I, O> {}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_encase_derive"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Bevy derive macro for encase"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -12,7 +12,7 @@ keywords = ["bevy"]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
bevy_macro_utils = { path = "../bevy_macro_utils", version = "0.13.0" }
|
||||
bevy_macro_utils = { path = "../bevy_macro_utils", version = "0.13.1" }
|
||||
encase_derive_impl = "0.7"
|
||||
|
||||
[lints]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_gilrs"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Gamepad system made using Gilrs for Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -10,12 +10,12 @@ keywords = ["bevy"]
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.0" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.0" }
|
||||
bevy_input = { path = "../bevy_input", version = "0.13.0" }
|
||||
bevy_log = { path = "../bevy_log", version = "0.13.0" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.0" }
|
||||
bevy_time = { path = "../bevy_time", version = "0.13.0" }
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.1" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.1" }
|
||||
bevy_input = { path = "../bevy_input", version = "0.13.1" }
|
||||
bevy_log = { path = "../bevy_log", version = "0.13.1" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.1" }
|
||||
bevy_time = { path = "../bevy_time", version = "0.13.1" }
|
||||
|
||||
# other
|
||||
gilrs = "0.10.1"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_gizmos"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Provides gizmos for Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -14,20 +14,20 @@ webgpu = []
|
||||
|
||||
[dependencies]
|
||||
# Bevy
|
||||
bevy_pbr = { path = "../bevy_pbr", version = "0.13.0", optional = true }
|
||||
bevy_sprite = { path = "../bevy_sprite", version = "0.13.0", optional = true }
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.0" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.0" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.0" }
|
||||
bevy_asset = { path = "../bevy_asset", version = "0.13.0" }
|
||||
bevy_render = { path = "../bevy_render", version = "0.13.0" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.0" }
|
||||
bevy_core = { path = "../bevy_core", version = "0.13.0" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.0" }
|
||||
bevy_core_pipeline = { path = "../bevy_core_pipeline", version = "0.13.0" }
|
||||
bevy_transform = { path = "../bevy_transform", version = "0.13.0" }
|
||||
bevy_log = { path = "../bevy_log", version = "0.13.0" }
|
||||
bevy_gizmos_macros = { path = "macros", version = "0.13.0" }
|
||||
bevy_pbr = { path = "../bevy_pbr", version = "0.13.1", optional = true }
|
||||
bevy_sprite = { path = "../bevy_sprite", version = "0.13.1", optional = true }
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.1" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.1" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.1" }
|
||||
bevy_asset = { path = "../bevy_asset", version = "0.13.1" }
|
||||
bevy_render = { path = "../bevy_render", version = "0.13.1" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.1" }
|
||||
bevy_core = { path = "../bevy_core", version = "0.13.1" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.1" }
|
||||
bevy_core_pipeline = { path = "../bevy_core_pipeline", version = "0.13.1" }
|
||||
bevy_transform = { path = "../bevy_transform", version = "0.13.1" }
|
||||
bevy_log = { path = "../bevy_log", version = "0.13.1" }
|
||||
bevy_gizmos_macros = { path = "macros", version = "0.13.1" }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_gizmos_macros"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Derive implementations for bevy_gizmos"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -12,7 +12,7 @@ keywords = ["bevy"]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
bevy_macro_utils = { path = "../../bevy_macro_utils", version = "0.13.0" }
|
||||
bevy_macro_utils = { path = "../../bevy_macro_utils", version = "0.13.1" }
|
||||
|
||||
syn = "2.0"
|
||||
proc-macro2 = "1.0"
|
||||
|
@ -3,8 +3,8 @@
|
||||
use crate as bevy_gizmos;
|
||||
pub use bevy_gizmos_macros::GizmoConfigGroup;
|
||||
|
||||
use bevy_ecs::{component::Component, system::Resource};
|
||||
use bevy_reflect::{Reflect, TypePath};
|
||||
use bevy_ecs::{component::Component, reflect::ReflectResource, system::Resource};
|
||||
use bevy_reflect::{std_traits::ReflectDefault, Reflect, TypePath};
|
||||
use bevy_render::view::RenderLayers;
|
||||
use bevy_utils::TypeIdMap;
|
||||
use core::panic;
|
||||
@ -27,9 +27,11 @@ pub struct DefaultGizmoConfigGroup;
|
||||
/// A [`Resource`] storing [`GizmoConfig`] and [`GizmoConfigGroup`] structs
|
||||
///
|
||||
/// Use `app.init_gizmo_group::<T>()` to register a custom config group.
|
||||
#[derive(Resource, Default)]
|
||||
#[derive(Reflect, Resource, Default)]
|
||||
#[reflect(Resource, Default)]
|
||||
pub struct GizmoConfigStore {
|
||||
// INVARIANT: must map TypeId::of::<T>() to correct type T
|
||||
#[reflect(ignore)]
|
||||
store: TypeIdMap<(GizmoConfig, Box<dyn Reflect>)>,
|
||||
}
|
||||
|
||||
|
@ -319,7 +319,7 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> {
|
||||
SphereBuilder {
|
||||
gizmos: self,
|
||||
position,
|
||||
rotation,
|
||||
rotation: rotation.normalize(),
|
||||
radius,
|
||||
color,
|
||||
circle_segments: DEFAULT_CIRCLE_SEGMENTS,
|
||||
|
@ -98,6 +98,7 @@ impl Plugin for GizmoPlugin {
|
||||
load_internal_asset!(app, LINE_SHADER_HANDLE, "lines.wgsl", Shader::from_wgsl);
|
||||
|
||||
app.register_type::<GizmoConfig>()
|
||||
.register_type::<GizmoConfigStore>()
|
||||
.add_plugins(UniformComponentPlugin::<LineGizmoUniform>::default())
|
||||
.init_asset::<LineGizmo>()
|
||||
.add_plugins(RenderAssetPlugin::<LineGizmo>::default())
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_gltf"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Bevy Engine GLTF loading"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -14,26 +14,26 @@ pbr_transmission_textures = []
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
bevy_animation = { path = "../bevy_animation", version = "0.13.0", optional = true }
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.0" }
|
||||
bevy_asset = { path = "../bevy_asset", version = "0.13.0" }
|
||||
bevy_core = { path = "../bevy_core", version = "0.13.0" }
|
||||
bevy_core_pipeline = { path = "../bevy_core_pipeline", version = "0.13.0" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.0" }
|
||||
bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.13.0" }
|
||||
bevy_log = { path = "../bevy_log", version = "0.13.0" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.0" }
|
||||
bevy_pbr = { path = "../bevy_pbr", version = "0.13.0" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.0", features = [
|
||||
bevy_animation = { path = "../bevy_animation", version = "0.13.1", optional = true }
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.1" }
|
||||
bevy_asset = { path = "../bevy_asset", version = "0.13.1" }
|
||||
bevy_core = { path = "../bevy_core", version = "0.13.1" }
|
||||
bevy_core_pipeline = { path = "../bevy_core_pipeline", version = "0.13.1" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.1" }
|
||||
bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.13.1" }
|
||||
bevy_log = { path = "../bevy_log", version = "0.13.1" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.1" }
|
||||
bevy_pbr = { path = "../bevy_pbr", version = "0.13.1" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.1", features = [
|
||||
"bevy",
|
||||
] }
|
||||
bevy_render = { path = "../bevy_render", version = "0.13.0" }
|
||||
bevy_scene = { path = "../bevy_scene", version = "0.13.0", features = [
|
||||
bevy_render = { path = "../bevy_render", version = "0.13.1" }
|
||||
bevy_scene = { path = "../bevy_scene", version = "0.13.1", features = [
|
||||
"bevy_render",
|
||||
] }
|
||||
bevy_transform = { path = "../bevy_transform", version = "0.13.0" }
|
||||
bevy_tasks = { path = "../bevy_tasks", version = "0.13.0" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.0" }
|
||||
bevy_transform = { path = "../bevy_transform", version = "0.13.1" }
|
||||
bevy_tasks = { path = "../bevy_tasks", version = "0.13.1" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.1" }
|
||||
|
||||
# other
|
||||
gltf = { version = "1.4.0", default-features = false, features = [
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_hierarchy"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Provides hierarchy functionality for Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -16,14 +16,14 @@ reflect = ["bevy_ecs/bevy_reflect", "bevy_reflect"]
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.0", optional = true }
|
||||
bevy_core = { path = "../bevy_core", version = "0.13.0", optional = true }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.0", default-features = false }
|
||||
bevy_log = { path = "../bevy_log", version = "0.13.0", optional = true }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.0", features = [
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.1", optional = true }
|
||||
bevy_core = { path = "../bevy_core", version = "0.13.1", optional = true }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.1", default-features = false }
|
||||
bevy_log = { path = "../bevy_log", version = "0.13.1", optional = true }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.1", features = [
|
||||
"bevy",
|
||||
], optional = true }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.0" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.1" }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_input"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Provides input functionality for Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -14,11 +14,11 @@ serialize = ["serde"]
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.0" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.0" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.0" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.0" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.0", features = [
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.1" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.1" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.1" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.1" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.1", features = [
|
||||
"glam",
|
||||
"smol_str",
|
||||
] }
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_internal"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "An internal Bevy crate used to facilitate optional dynamic linking via the 'dynamic_linking' feature"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -162,41 +162,41 @@ bevy_debug_stepping = [
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
bevy_a11y = { path = "../bevy_a11y", version = "0.13.0" }
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.0" }
|
||||
bevy_core = { path = "../bevy_core", version = "0.13.0" }
|
||||
bevy_derive = { path = "../bevy_derive", version = "0.13.0" }
|
||||
bevy_diagnostic = { path = "../bevy_diagnostic", version = "0.13.0" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.0" }
|
||||
bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.13.0" }
|
||||
bevy_input = { path = "../bevy_input", version = "0.13.0" }
|
||||
bevy_log = { path = "../bevy_log", version = "0.13.0" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.0" }
|
||||
bevy_ptr = { path = "../bevy_ptr", version = "0.13.0" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.0", features = [
|
||||
bevy_a11y = { path = "../bevy_a11y", version = "0.13.1" }
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.1" }
|
||||
bevy_core = { path = "../bevy_core", version = "0.13.1" }
|
||||
bevy_derive = { path = "../bevy_derive", version = "0.13.1" }
|
||||
bevy_diagnostic = { path = "../bevy_diagnostic", version = "0.13.1" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.1" }
|
||||
bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.13.1" }
|
||||
bevy_input = { path = "../bevy_input", version = "0.13.1" }
|
||||
bevy_log = { path = "../bevy_log", version = "0.13.1" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.1" }
|
||||
bevy_ptr = { path = "../bevy_ptr", version = "0.13.1" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.1", features = [
|
||||
"bevy",
|
||||
] }
|
||||
bevy_time = { path = "../bevy_time", version = "0.13.0" }
|
||||
bevy_transform = { path = "../bevy_transform", version = "0.13.0" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.0" }
|
||||
bevy_window = { path = "../bevy_window", version = "0.13.0" }
|
||||
bevy_tasks = { path = "../bevy_tasks", version = "0.13.0" }
|
||||
bevy_time = { path = "../bevy_time", version = "0.13.1" }
|
||||
bevy_transform = { path = "../bevy_transform", version = "0.13.1" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.1" }
|
||||
bevy_window = { path = "../bevy_window", version = "0.13.1" }
|
||||
bevy_tasks = { path = "../bevy_tasks", version = "0.13.1" }
|
||||
# bevy (optional)
|
||||
bevy_animation = { path = "../bevy_animation", optional = true, version = "0.13.0" }
|
||||
bevy_asset = { path = "../bevy_asset", optional = true, version = "0.13.0" }
|
||||
bevy_audio = { path = "../bevy_audio", optional = true, version = "0.13.0" }
|
||||
bevy_core_pipeline = { path = "../bevy_core_pipeline", optional = true, version = "0.13.0" }
|
||||
bevy_gltf = { path = "../bevy_gltf", optional = true, version = "0.13.0" }
|
||||
bevy_pbr = { path = "../bevy_pbr", optional = true, version = "0.13.0" }
|
||||
bevy_render = { path = "../bevy_render", optional = true, version = "0.13.0" }
|
||||
bevy_dynamic_plugin = { path = "../bevy_dynamic_plugin", optional = true, version = "0.13.0" }
|
||||
bevy_scene = { path = "../bevy_scene", optional = true, version = "0.13.0" }
|
||||
bevy_sprite = { path = "../bevy_sprite", optional = true, version = "0.13.0" }
|
||||
bevy_text = { path = "../bevy_text", optional = true, version = "0.13.0" }
|
||||
bevy_ui = { path = "../bevy_ui", optional = true, version = "0.13.0" }
|
||||
bevy_winit = { path = "../bevy_winit", optional = true, version = "0.13.0" }
|
||||
bevy_gilrs = { path = "../bevy_gilrs", optional = true, version = "0.13.0" }
|
||||
bevy_gizmos = { path = "../bevy_gizmos", optional = true, version = "0.13.0", default-features = false }
|
||||
bevy_animation = { path = "../bevy_animation", optional = true, version = "0.13.1" }
|
||||
bevy_asset = { path = "../bevy_asset", optional = true, version = "0.13.1" }
|
||||
bevy_audio = { path = "../bevy_audio", optional = true, version = "0.13.1" }
|
||||
bevy_core_pipeline = { path = "../bevy_core_pipeline", optional = true, version = "0.13.1" }
|
||||
bevy_gltf = { path = "../bevy_gltf", optional = true, version = "0.13.1" }
|
||||
bevy_pbr = { path = "../bevy_pbr", optional = true, version = "0.13.1" }
|
||||
bevy_render = { path = "../bevy_render", optional = true, version = "0.13.1" }
|
||||
bevy_dynamic_plugin = { path = "../bevy_dynamic_plugin", optional = true, version = "0.13.1" }
|
||||
bevy_scene = { path = "../bevy_scene", optional = true, version = "0.13.1" }
|
||||
bevy_sprite = { path = "../bevy_sprite", optional = true, version = "0.13.1" }
|
||||
bevy_text = { path = "../bevy_text", optional = true, version = "0.13.1" }
|
||||
bevy_ui = { path = "../bevy_ui", optional = true, version = "0.13.1" }
|
||||
bevy_winit = { path = "../bevy_winit", optional = true, version = "0.13.1" }
|
||||
bevy_gilrs = { path = "../bevy_gilrs", optional = true, version = "0.13.1" }
|
||||
bevy_gizmos = { path = "../bevy_gizmos", optional = true, version = "0.13.1", default-features = false }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_log"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Provides logging for Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -13,9 +13,9 @@ trace = ["tracing-error"]
|
||||
trace_tracy_memory = ["dep:tracy-client"]
|
||||
|
||||
[dependencies]
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.0" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.0" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.0" }
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.1" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.1" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.1" }
|
||||
|
||||
tracing-subscriber = { version = "0.3.1", features = [
|
||||
"registry",
|
||||
|
@ -217,12 +217,12 @@ impl Plugin for LogPlugin {
|
||||
bevy_utils::tracing::subscriber::set_global_default(finished_subscriber).is_err();
|
||||
|
||||
match (logger_already_set, subscriber_already_set) {
|
||||
(true, true) => warn!(
|
||||
(true, true) => error!(
|
||||
"Could not set global logger and tracing subscriber as they are already set. Consider disabling LogPlugin."
|
||||
),
|
||||
(true, _) => warn!("Could not set global logger as it is already set. Consider disabling LogPlugin."),
|
||||
(_, true) => warn!("Could not set global tracing subscriber as it is already set. Consider disabling LogPlugin."),
|
||||
_ => (),
|
||||
(true, false) => error!("Could not set global logger as it is already set. Consider disabling LogPlugin."),
|
||||
(false, true) => error!("Could not set global tracing subscriber as it is already set. Consider disabling LogPlugin."),
|
||||
(false, false) => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_macro_utils"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "A collection of utils for Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_math"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Provides math functionality for Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_mikktspace"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
authors = [
|
||||
"Benjamin Wasty <benny.wasty@gmail.com>",
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_pbr"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Adds PBR rendering to Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -15,19 +15,19 @@ pbr_transmission_textures = []
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.0" }
|
||||
bevy_asset = { path = "../bevy_asset", version = "0.13.0" }
|
||||
bevy_core_pipeline = { path = "../bevy_core_pipeline", version = "0.13.0" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.0" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.0" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.0", features = [
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.1" }
|
||||
bevy_asset = { path = "../bevy_asset", version = "0.13.1" }
|
||||
bevy_core_pipeline = { path = "../bevy_core_pipeline", version = "0.13.1" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.1" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.1" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.1", features = [
|
||||
"bevy",
|
||||
] }
|
||||
bevy_render = { path = "../bevy_render", version = "0.13.0" }
|
||||
bevy_transform = { path = "../bevy_transform", version = "0.13.0" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.0" }
|
||||
bevy_window = { path = "../bevy_window", version = "0.13.0" }
|
||||
bevy_derive = { path = "../bevy_derive", version = "0.13.0" }
|
||||
bevy_render = { path = "../bevy_render", version = "0.13.1" }
|
||||
bevy_transform = { path = "../bevy_transform", version = "0.13.1" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.1" }
|
||||
bevy_window = { path = "../bevy_window", version = "0.13.1" }
|
||||
bevy_derive = { path = "../bevy_derive", version = "0.13.1" }
|
||||
|
||||
# other
|
||||
bitflags = "2.3"
|
||||
|
@ -590,7 +590,7 @@ fn calculate_cascade(
|
||||
|
||||
// It is critical for `world_to_cascade` to be stable. So rather than forming `cascade_to_world`
|
||||
// and inverting it, which risks instability due to numerical precision, we directly form
|
||||
// `world_to_cascde` as the reference material suggests.
|
||||
// `world_to_cascade` as the reference material suggests.
|
||||
let light_to_world_transpose = light_to_world.transpose();
|
||||
let world_to_cascade = Mat4::from_cols(
|
||||
light_to_world_transpose.x_axis,
|
||||
|
@ -793,7 +793,19 @@ pub struct PreparedMaterial<T: Material> {
|
||||
}
|
||||
|
||||
#[derive(Component, Clone, Copy, Default, PartialEq, Eq, Deref, DerefMut)]
|
||||
pub struct MaterialBindGroupId(Option<BindGroupId>);
|
||||
pub struct MaterialBindGroupId(pub Option<BindGroupId>);
|
||||
|
||||
impl MaterialBindGroupId {
|
||||
pub fn new(id: BindGroupId) -> Self {
|
||||
Self(Some(id))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BindGroup> for MaterialBindGroupId {
|
||||
fn from(value: BindGroup) -> Self {
|
||||
Self::new(value.id())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Material> PreparedMaterial<T> {
|
||||
pub fn get_bind_group_id(&self) -> MaterialBindGroupId {
|
||||
|
@ -6,7 +6,7 @@ use bevy_render::{
|
||||
camera::Camera,
|
||||
color::Color,
|
||||
mesh::Mesh,
|
||||
primitives::{CascadesFrusta, CubemapFrusta, Frustum},
|
||||
primitives::{CascadesFrusta, CubemapFrusta, Frustum, HalfSpace},
|
||||
render_asset::RenderAssets,
|
||||
render_graph::{Node, NodeRunError, RenderGraphContext},
|
||||
render_phase::*,
|
||||
@ -29,30 +29,30 @@ use crate::*;
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct ExtractedPointLight {
|
||||
color: Color,
|
||||
pub color: Color,
|
||||
/// luminous intensity in lumens per steradian
|
||||
intensity: f32,
|
||||
range: f32,
|
||||
radius: f32,
|
||||
transform: GlobalTransform,
|
||||
shadows_enabled: bool,
|
||||
shadow_depth_bias: f32,
|
||||
shadow_normal_bias: f32,
|
||||
spot_light_angles: Option<(f32, f32)>,
|
||||
pub intensity: f32,
|
||||
pub range: f32,
|
||||
pub radius: f32,
|
||||
pub transform: GlobalTransform,
|
||||
pub shadows_enabled: bool,
|
||||
pub shadow_depth_bias: f32,
|
||||
pub shadow_normal_bias: f32,
|
||||
pub spot_light_angles: Option<(f32, f32)>,
|
||||
}
|
||||
|
||||
#[derive(Component, Debug)]
|
||||
pub struct ExtractedDirectionalLight {
|
||||
color: Color,
|
||||
illuminance: f32,
|
||||
transform: GlobalTransform,
|
||||
shadows_enabled: bool,
|
||||
shadow_depth_bias: f32,
|
||||
shadow_normal_bias: f32,
|
||||
cascade_shadow_config: CascadeShadowConfig,
|
||||
cascades: EntityHashMap<Vec<Cascade>>,
|
||||
frusta: EntityHashMap<Vec<Frustum>>,
|
||||
render_layers: RenderLayers,
|
||||
pub color: Color,
|
||||
pub illuminance: f32,
|
||||
pub transform: GlobalTransform,
|
||||
pub shadows_enabled: bool,
|
||||
pub shadow_depth_bias: f32,
|
||||
pub shadow_normal_bias: f32,
|
||||
pub cascade_shadow_config: CascadeShadowConfig,
|
||||
pub cascades: EntityHashMap<Vec<Cascade>>,
|
||||
pub frusta: EntityHashMap<Vec<Frustum>>,
|
||||
pub render_layers: RenderLayers,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, ShaderType, Default, Debug)]
|
||||
@ -1145,7 +1145,7 @@ pub fn prepare_lights(
|
||||
.unwrap()
|
||||
.iter()
|
||||
.take(MAX_CASCADES_PER_LIGHT);
|
||||
for (cascade_index, ((cascade, frusta), bound)) in cascades
|
||||
for (cascade_index, ((cascade, frustum), bound)) in cascades
|
||||
.zip(frusta)
|
||||
.zip(&light.cascade_shadow_config.bounds)
|
||||
.enumerate()
|
||||
@ -1172,6 +1172,11 @@ pub fn prepare_lights(
|
||||
});
|
||||
directional_depth_texture_array_index += 1;
|
||||
|
||||
let mut frustum = *frustum;
|
||||
// Push the near clip plane out to infinity for directional lights
|
||||
frustum.half_spaces[4] =
|
||||
HalfSpace::new(frustum.half_spaces[4].normal().extend(f32::INFINITY));
|
||||
|
||||
let view_light_entity = commands
|
||||
.spawn((
|
||||
ShadowView {
|
||||
@ -1192,7 +1197,7 @@ pub fn prepare_lights(
|
||||
hdr: false,
|
||||
color_grading: Default::default(),
|
||||
},
|
||||
*frusta,
|
||||
frustum,
|
||||
RenderPhase::<Shadow>::default(),
|
||||
LightEntity::Directional {
|
||||
light_entity,
|
||||
@ -1210,16 +1215,20 @@ pub fn prepare_lights(
|
||||
.create_view(&TextureViewDescriptor {
|
||||
label: Some("point_light_shadow_map_array_texture_view"),
|
||||
format: None,
|
||||
#[cfg(any(
|
||||
not(feature = "webgl"),
|
||||
not(target_arch = "wasm32"),
|
||||
feature = "webgpu"
|
||||
// NOTE: iOS Simulator is missing CubeArray support so we use Cube instead.
|
||||
// See https://github.com/bevyengine/bevy/pull/12052 - remove if support is added.
|
||||
#[cfg(all(
|
||||
not(ios_simulator),
|
||||
any(
|
||||
not(feature = "webgl"),
|
||||
not(target_arch = "wasm32"),
|
||||
feature = "webgpu"
|
||||
)
|
||||
))]
|
||||
dimension: Some(TextureViewDimension::CubeArray),
|
||||
#[cfg(all(
|
||||
feature = "webgl",
|
||||
target_arch = "wasm32",
|
||||
not(feature = "webgpu")
|
||||
#[cfg(any(
|
||||
ios_simulator,
|
||||
all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu"))
|
||||
))]
|
||||
dimension: Some(TextureViewDimension::Cube),
|
||||
aspect: TextureAspect::DepthOnly,
|
||||
|
@ -191,13 +191,19 @@ fn layout_entries(
|
||||
// Point Shadow Texture Cube Array
|
||||
(
|
||||
2,
|
||||
#[cfg(any(
|
||||
not(feature = "webgl"),
|
||||
not(target_arch = "wasm32"),
|
||||
feature = "webgpu"
|
||||
#[cfg(all(
|
||||
not(ios_simulator),
|
||||
any(
|
||||
not(feature = "webgl"),
|
||||
not(target_arch = "wasm32"),
|
||||
feature = "webgpu"
|
||||
)
|
||||
))]
|
||||
texture_cube_array(TextureSampleType::Depth),
|
||||
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
|
||||
#[cfg(any(
|
||||
ios_simulator,
|
||||
all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu"))
|
||||
))]
|
||||
texture_cube(TextureSampleType::Depth),
|
||||
),
|
||||
// Point Shadow Texture Array Sampler
|
||||
@ -250,7 +256,10 @@ fn layout_entries(
|
||||
),
|
||||
),
|
||||
// Globals
|
||||
(9, uniform_buffer::<GlobalsUniform>(false)),
|
||||
(
|
||||
9,
|
||||
uniform_buffer::<GlobalsUniform>(false).visibility(ShaderStages::VERTEX_FRAGMENT),
|
||||
),
|
||||
// Fog
|
||||
(10, uniform_buffer::<GpuFog>(true)),
|
||||
// Light probes
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
@group(0) @binding(0) var<uniform> view: View;
|
||||
@group(0) @binding(1) var<uniform> lights: types::Lights;
|
||||
#ifdef NO_ARRAY_TEXTURES_SUPPORT
|
||||
#ifdef NO_CUBE_ARRAY_TEXTURES_SUPPORT
|
||||
@group(0) @binding(2) var point_shadow_textures: texture_depth_cube;
|
||||
#else
|
||||
@group(0) @binding(2) var point_shadow_textures: texture_depth_cube_array;
|
||||
|
@ -109,6 +109,6 @@ pub fn no_automatic_morph_batching(
|
||||
query: Query<Entity, (With<MeshMorphWeights>, Without<NoAutomaticBatching>)>,
|
||||
) {
|
||||
for entity in &query {
|
||||
commands.entity(entity).insert(NoAutomaticBatching);
|
||||
commands.entity(entity).try_insert(NoAutomaticBatching);
|
||||
}
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ fn fetch_point_shadow(light_id: u32, frag_position: vec4<f32>, surface_normal: v
|
||||
// a quad (2x2 fragments) being processed not being sampled, and this messing with
|
||||
// mip-mapping functionality. The shadow maps have no mipmaps so Level just samples
|
||||
// from LOD 0.
|
||||
#ifdef NO_ARRAY_TEXTURES_SUPPORT
|
||||
#ifdef NO_CUBE_ARRAY_TEXTURES_SUPPORT
|
||||
return textureSampleCompare(view_bindings::point_shadow_textures, view_bindings::point_shadow_textures_sampler, frag_ls * flip_z, depth);
|
||||
#else
|
||||
return textureSampleCompareLevel(view_bindings::point_shadow_textures, view_bindings::point_shadow_textures_sampler, frag_ls * flip_z, i32(light_id), depth);
|
||||
|
@ -146,6 +146,6 @@ pub fn no_automatic_skin_batching(
|
||||
query: Query<Entity, (With<SkinnedMesh>, Without<NoAutomaticBatching>)>,
|
||||
) {
|
||||
for entity in &query {
|
||||
commands.entity(entity).insert(NoAutomaticBatching);
|
||||
commands.entity(entity).try_insert(NoAutomaticBatching);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_ptr"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Utilities for working with untyped pointers in a more safe way"
|
||||
homepage = "https://bevyengine.org"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_reflect"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Dynamically interact with rust types"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -21,12 +21,12 @@ documentation = ["bevy_reflect_derive/documentation"]
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.0", features = [
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.1", features = [
|
||||
"serialize",
|
||||
], optional = true }
|
||||
bevy_reflect_derive = { path = "bevy_reflect_derive", version = "0.13.0" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.0" }
|
||||
bevy_ptr = { path = "../bevy_ptr", version = "0.13.0" }
|
||||
bevy_reflect_derive = { path = "bevy_reflect_derive", version = "0.13.1" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.1" }
|
||||
bevy_ptr = { path = "../bevy_ptr", version = "0.13.1" }
|
||||
|
||||
# other
|
||||
erased-serde = "0.4"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_reflect_derive"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Derive implementations for bevy_reflect"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -17,7 +17,7 @@ default = []
|
||||
documentation = []
|
||||
|
||||
[dependencies]
|
||||
bevy_macro_utils = { path = "../../bevy_macro_utils", version = "0.13.0" }
|
||||
bevy_macro_utils = { path = "../../bevy_macro_utils", version = "0.13.1" }
|
||||
|
||||
syn = { version = "2.0", features = ["full"] }
|
||||
proc-macro2 = "1.0"
|
||||
|
@ -805,8 +805,12 @@ impl<'a, 'de> Visitor<'de> for EnumVisitor<'a> {
|
||||
)?
|
||||
.into(),
|
||||
};
|
||||
|
||||
dynamic_enum.set_variant(variant_info.name(), value);
|
||||
let variant_name = variant_info.name();
|
||||
let variant_index = self
|
||||
.enum_info
|
||||
.index_of(variant_name)
|
||||
.expect("variant should exist");
|
||||
dynamic_enum.set_variant_with_index(variant_index, variant_name, value);
|
||||
Ok(dynamic_enum)
|
||||
}
|
||||
}
|
||||
@ -1110,7 +1114,7 @@ mod tests {
|
||||
use bevy_utils::HashMap;
|
||||
|
||||
use crate as bevy_reflect;
|
||||
use crate::serde::{TypedReflectDeserializer, UntypedReflectDeserializer};
|
||||
use crate::serde::{ReflectSerializer, TypedReflectDeserializer, UntypedReflectDeserializer};
|
||||
use crate::{DynamicEnum, FromReflect, Reflect, ReflectDeserialize, TypeRegistry};
|
||||
|
||||
#[derive(Reflect, Debug, PartialEq)]
|
||||
@ -1168,7 +1172,7 @@ mod tests {
|
||||
#[reflect(Deserialize)]
|
||||
struct CustomDeserialize {
|
||||
value: usize,
|
||||
#[serde(rename = "renamed")]
|
||||
#[serde(alias = "renamed")]
|
||||
inner_struct: SomeDeserializableStruct,
|
||||
}
|
||||
|
||||
@ -1218,12 +1222,11 @@ mod tests {
|
||||
registry
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_deserialize() {
|
||||
fn get_my_struct() -> MyStruct {
|
||||
let mut map = HashMap::new();
|
||||
map.insert(64, 32);
|
||||
|
||||
let expected = MyStruct {
|
||||
MyStruct {
|
||||
primitive_value: 123,
|
||||
option_value: Some(String::from("Hello world!")),
|
||||
option_value_complex: Some(SomeStruct { foo: 123 }),
|
||||
@ -1250,7 +1253,13 @@ mod tests {
|
||||
value: 100,
|
||||
inner_struct: SomeDeserializableStruct { foo: 101 },
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_deserialize() {
|
||||
let expected = get_my_struct();
|
||||
let registry = get_registry();
|
||||
|
||||
let input = r#"{
|
||||
"bevy_reflect::serde::de::tests::MyStruct": (
|
||||
@ -1295,7 +1304,6 @@ mod tests {
|
||||
),
|
||||
}"#;
|
||||
|
||||
let registry = get_registry();
|
||||
let reflect_deserializer = UntypedReflectDeserializer::new(®istry);
|
||||
let mut ron_deserializer = ron::de::Deserializer::from_str(input).unwrap();
|
||||
let dynamic_output = reflect_deserializer
|
||||
@ -1477,40 +1485,28 @@ mod tests {
|
||||
assert!(expected.reflect_partial_eq(output.as_ref()).unwrap());
|
||||
}
|
||||
|
||||
// Regression test for https://github.com/bevyengine/bevy/issues/12462
|
||||
#[test]
|
||||
fn should_reserialize() {
|
||||
let registry = get_registry();
|
||||
let input1 = get_my_struct();
|
||||
|
||||
let serializer1 = ReflectSerializer::new(&input1, ®istry);
|
||||
let serialized1 = ron::ser::to_string(&serializer1).unwrap();
|
||||
|
||||
let mut deserializer = ron::de::Deserializer::from_str(&serialized1).unwrap();
|
||||
let reflect_deserializer = UntypedReflectDeserializer::new(®istry);
|
||||
let input2 = reflect_deserializer.deserialize(&mut deserializer).unwrap();
|
||||
|
||||
let serializer2 = ReflectSerializer::new(&*input2, ®istry);
|
||||
let serialized2 = ron::ser::to_string(&serializer2).unwrap();
|
||||
|
||||
assert_eq!(serialized1, serialized2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_deserialize_non_self_describing_binary() {
|
||||
let mut map = HashMap::new();
|
||||
map.insert(64, 32);
|
||||
|
||||
let expected = MyStruct {
|
||||
primitive_value: 123,
|
||||
option_value: Some(String::from("Hello world!")),
|
||||
option_value_complex: Some(SomeStruct { foo: 123 }),
|
||||
tuple_value: (PI, 1337),
|
||||
list_value: vec![-2, -1, 0, 1, 2],
|
||||
array_value: [-2, -1, 0, 1, 2],
|
||||
map_value: map,
|
||||
struct_value: SomeStruct { foo: 999999999 },
|
||||
tuple_struct_value: SomeTupleStruct(String::from("Tuple Struct")),
|
||||
unit_struct: SomeUnitStruct,
|
||||
unit_enum: SomeEnum::Unit,
|
||||
newtype_enum: SomeEnum::NewType(123),
|
||||
tuple_enum: SomeEnum::Tuple(1.23, 3.21),
|
||||
struct_enum: SomeEnum::Struct {
|
||||
foo: String::from("Struct variant value"),
|
||||
},
|
||||
ignored_struct: SomeIgnoredStruct { ignored: 0 },
|
||||
ignored_tuple_struct: SomeIgnoredTupleStruct(0),
|
||||
ignored_struct_variant: SomeIgnoredEnum::Struct {
|
||||
foo: String::default(),
|
||||
},
|
||||
ignored_tuple_variant: SomeIgnoredEnum::Tuple(0.0, 0.0),
|
||||
custom_deserialize: CustomDeserialize {
|
||||
value: 100,
|
||||
inner_struct: SomeDeserializableStruct { foo: 101 },
|
||||
},
|
||||
};
|
||||
|
||||
let expected = get_my_struct();
|
||||
let registry = get_registry();
|
||||
|
||||
let input = vec![
|
||||
@ -1542,38 +1538,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn should_deserialize_self_describing_binary() {
|
||||
let mut map = HashMap::new();
|
||||
map.insert(64, 32);
|
||||
|
||||
let expected = MyStruct {
|
||||
primitive_value: 123,
|
||||
option_value: Some(String::from("Hello world!")),
|
||||
option_value_complex: Some(SomeStruct { foo: 123 }),
|
||||
tuple_value: (PI, 1337),
|
||||
list_value: vec![-2, -1, 0, 1, 2],
|
||||
array_value: [-2, -1, 0, 1, 2],
|
||||
map_value: map,
|
||||
struct_value: SomeStruct { foo: 999999999 },
|
||||
tuple_struct_value: SomeTupleStruct(String::from("Tuple Struct")),
|
||||
unit_struct: SomeUnitStruct,
|
||||
unit_enum: SomeEnum::Unit,
|
||||
newtype_enum: SomeEnum::NewType(123),
|
||||
tuple_enum: SomeEnum::Tuple(1.23, 3.21),
|
||||
struct_enum: SomeEnum::Struct {
|
||||
foo: String::from("Struct variant value"),
|
||||
},
|
||||
ignored_struct: SomeIgnoredStruct { ignored: 0 },
|
||||
ignored_tuple_struct: SomeIgnoredTupleStruct(0),
|
||||
ignored_struct_variant: SomeIgnoredEnum::Struct {
|
||||
foo: String::default(),
|
||||
},
|
||||
ignored_tuple_variant: SomeIgnoredEnum::Tuple(0.0, 0.0),
|
||||
custom_deserialize: CustomDeserialize {
|
||||
value: 100,
|
||||
inner_struct: SomeDeserializableStruct { foo: 101 },
|
||||
},
|
||||
};
|
||||
|
||||
let expected = get_my_struct();
|
||||
let registry = get_registry();
|
||||
|
||||
let input = vec![
|
||||
|
@ -32,12 +32,19 @@ fn get_serializable<'a, E: Error>(
|
||||
reflect_value: &'a dyn Reflect,
|
||||
type_registry: &TypeRegistry,
|
||||
) -> Result<Serializable<'a>, E> {
|
||||
let info = reflect_value.get_represented_type_info().ok_or_else(|| {
|
||||
Error::custom(format_args!(
|
||||
"Type '{}' does not represent any type",
|
||||
reflect_value.reflect_type_path(),
|
||||
))
|
||||
})?;
|
||||
|
||||
let reflect_serialize = type_registry
|
||||
.get_type_data::<ReflectSerialize>(reflect_value.type_id())
|
||||
.get_type_data::<ReflectSerialize>(info.type_id())
|
||||
.ok_or_else(|| {
|
||||
Error::custom(format_args!(
|
||||
"Type '{}' did not register ReflectSerialize",
|
||||
reflect_value.reflect_type_path()
|
||||
info.type_path(),
|
||||
))
|
||||
})?;
|
||||
Ok(reflect_serialize.get_serializable(reflect_value))
|
||||
@ -567,12 +574,10 @@ mod tests {
|
||||
registry
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_serialize() {
|
||||
fn get_my_struct() -> MyStruct {
|
||||
let mut map = HashMap::new();
|
||||
map.insert(64, 32);
|
||||
|
||||
let input = MyStruct {
|
||||
MyStruct {
|
||||
primitive_value: 123,
|
||||
option_value: Some(String::from("Hello world!")),
|
||||
option_value_complex: Some(SomeStruct { foo: 123 }),
|
||||
@ -599,9 +604,14 @@ mod tests {
|
||||
value: 100,
|
||||
inner_struct: SomeSerializableStruct { foo: 101 },
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_serialize() {
|
||||
let input = get_my_struct();
|
||||
let registry = get_registry();
|
||||
|
||||
let serializer = ReflectSerializer::new(&input, ®istry);
|
||||
|
||||
let config = PrettyConfig::default()
|
||||
@ -769,38 +779,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn should_serialize_non_self_describing_binary() {
|
||||
let mut map = HashMap::new();
|
||||
map.insert(64, 32);
|
||||
|
||||
let input = MyStruct {
|
||||
primitive_value: 123,
|
||||
option_value: Some(String::from("Hello world!")),
|
||||
option_value_complex: Some(SomeStruct { foo: 123 }),
|
||||
tuple_value: (PI, 1337),
|
||||
list_value: vec![-2, -1, 0, 1, 2],
|
||||
array_value: [-2, -1, 0, 1, 2],
|
||||
map_value: map,
|
||||
struct_value: SomeStruct { foo: 999999999 },
|
||||
tuple_struct_value: SomeTupleStruct(String::from("Tuple Struct")),
|
||||
unit_struct: SomeUnitStruct,
|
||||
unit_enum: SomeEnum::Unit,
|
||||
newtype_enum: SomeEnum::NewType(123),
|
||||
tuple_enum: SomeEnum::Tuple(1.23, 3.21),
|
||||
struct_enum: SomeEnum::Struct {
|
||||
foo: String::from("Struct variant value"),
|
||||
},
|
||||
ignored_struct: SomeIgnoredStruct { ignored: 123 },
|
||||
ignored_tuple_struct: SomeIgnoredTupleStruct(123),
|
||||
ignored_struct_variant: SomeIgnoredEnum::Struct {
|
||||
foo: String::from("Struct Variant"),
|
||||
},
|
||||
ignored_tuple_variant: SomeIgnoredEnum::Tuple(1.23, 3.45),
|
||||
custom_serialize: CustomSerialize {
|
||||
value: 100,
|
||||
inner_struct: SomeSerializableStruct { foo: 101 },
|
||||
},
|
||||
};
|
||||
|
||||
let input = get_my_struct();
|
||||
let registry = get_registry();
|
||||
|
||||
let serializer = ReflectSerializer::new(&input, ®istry);
|
||||
@ -827,38 +806,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn should_serialize_self_describing_binary() {
|
||||
let mut map = HashMap::new();
|
||||
map.insert(64, 32);
|
||||
|
||||
let input = MyStruct {
|
||||
primitive_value: 123,
|
||||
option_value: Some(String::from("Hello world!")),
|
||||
option_value_complex: Some(SomeStruct { foo: 123 }),
|
||||
tuple_value: (PI, 1337),
|
||||
list_value: vec![-2, -1, 0, 1, 2],
|
||||
array_value: [-2, -1, 0, 1, 2],
|
||||
map_value: map,
|
||||
struct_value: SomeStruct { foo: 999999999 },
|
||||
tuple_struct_value: SomeTupleStruct(String::from("Tuple Struct")),
|
||||
unit_struct: SomeUnitStruct,
|
||||
unit_enum: SomeEnum::Unit,
|
||||
newtype_enum: SomeEnum::NewType(123),
|
||||
tuple_enum: SomeEnum::Tuple(1.23, 3.21),
|
||||
struct_enum: SomeEnum::Struct {
|
||||
foo: String::from("Struct variant value"),
|
||||
},
|
||||
ignored_struct: SomeIgnoredStruct { ignored: 123 },
|
||||
ignored_tuple_struct: SomeIgnoredTupleStruct(123),
|
||||
ignored_struct_variant: SomeIgnoredEnum::Struct {
|
||||
foo: String::from("Struct Variant"),
|
||||
},
|
||||
ignored_tuple_variant: SomeIgnoredEnum::Tuple(1.23, 3.45),
|
||||
custom_serialize: CustomSerialize {
|
||||
value: 100,
|
||||
inner_struct: SomeSerializableStruct { foo: 101 },
|
||||
},
|
||||
};
|
||||
|
||||
let input = get_my_struct();
|
||||
let registry = get_registry();
|
||||
|
||||
let serializer = ReflectSerializer::new(&input, ®istry);
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::{serde::Serializable, Reflect, TypeInfo, TypePath, Typed};
|
||||
use crate::{serde::Serializable, FromReflect, Reflect, TypeInfo, TypePath, Typed};
|
||||
use bevy_ptr::{Ptr, PtrMut};
|
||||
use bevy_utils::{HashMap, HashSet, TypeIdMap};
|
||||
use downcast_rs::{impl_downcast, Downcast};
|
||||
@ -435,14 +435,20 @@ pub struct ReflectSerialize {
|
||||
get_serializable: for<'a> fn(value: &'a dyn Reflect) -> Serializable,
|
||||
}
|
||||
|
||||
impl<T: Reflect + erased_serde::Serialize> FromType<T> for ReflectSerialize {
|
||||
impl<T: TypePath + FromReflect + erased_serde::Serialize> FromType<T> for ReflectSerialize {
|
||||
fn from_type() -> Self {
|
||||
ReflectSerialize {
|
||||
get_serializable: |value| {
|
||||
let value = value.downcast_ref::<T>().unwrap_or_else(|| {
|
||||
panic!("ReflectSerialize::get_serialize called with type `{}`, even though it was created for `{}`", value.reflect_type_path(), std::any::type_name::<T>())
|
||||
});
|
||||
Serializable::Borrowed(value)
|
||||
value
|
||||
.downcast_ref::<T>()
|
||||
.map(|value| Serializable::Borrowed(value))
|
||||
.or_else(|| T::from_reflect(value).map(|value| Serializable::Owned(Box::new(value))))
|
||||
.unwrap_or_else(|| {
|
||||
panic!(
|
||||
"FromReflect::from_reflect failed when called on type `{}` with this value: {value:?}",
|
||||
T::type_path(),
|
||||
);
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_render"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Provides rendering functionality for Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -37,25 +37,25 @@ webgpu = ["wgpu/webgpu"]
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.0" }
|
||||
bevy_asset = { path = "../bevy_asset", version = "0.13.0" }
|
||||
bevy_core = { path = "../bevy_core", version = "0.13.0" }
|
||||
bevy_derive = { path = "../bevy_derive", version = "0.13.0" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.0" }
|
||||
bevy_encase_derive = { path = "../bevy_encase_derive", version = "0.13.0" }
|
||||
bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.13.0" }
|
||||
bevy_log = { path = "../bevy_log", version = "0.13.0" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.0" }
|
||||
bevy_mikktspace = { path = "../bevy_mikktspace", version = "0.13.0" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.0", features = [
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.1" }
|
||||
bevy_asset = { path = "../bevy_asset", version = "0.13.1" }
|
||||
bevy_core = { path = "../bevy_core", version = "0.13.1" }
|
||||
bevy_derive = { path = "../bevy_derive", version = "0.13.1" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.1" }
|
||||
bevy_encase_derive = { path = "../bevy_encase_derive", version = "0.13.1" }
|
||||
bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.13.1" }
|
||||
bevy_log = { path = "../bevy_log", version = "0.13.1" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.1" }
|
||||
bevy_mikktspace = { path = "../bevy_mikktspace", version = "0.13.1" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.1", features = [
|
||||
"bevy",
|
||||
] }
|
||||
bevy_render_macros = { path = "macros", version = "0.13.0" }
|
||||
bevy_time = { path = "../bevy_time", version = "0.13.0" }
|
||||
bevy_transform = { path = "../bevy_transform", version = "0.13.0" }
|
||||
bevy_window = { path = "../bevy_window", version = "0.13.0" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.0" }
|
||||
bevy_tasks = { path = "../bevy_tasks", version = "0.13.0" }
|
||||
bevy_render_macros = { path = "macros", version = "0.13.1" }
|
||||
bevy_time = { path = "../bevy_time", version = "0.13.1" }
|
||||
bevy_transform = { path = "../bevy_transform", version = "0.13.1" }
|
||||
bevy_window = { path = "../bevy_window", version = "0.13.1" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.1" }
|
||||
bevy_tasks = { path = "../bevy_tasks", version = "0.13.1" }
|
||||
|
||||
# rendering
|
||||
image = { version = "0.24", default-features = false }
|
||||
@ -64,7 +64,7 @@ image = { version = "0.24", default-features = false }
|
||||
codespan-reporting = "0.11.0"
|
||||
# `fragile-send-sync-non-atomic-wasm` feature means we can't use WASM threads for rendering
|
||||
# It is enabled for now to avoid having to do a significant overhaul of the renderer just for wasm
|
||||
wgpu = { version = "0.19.1", default-features = false, features = [
|
||||
wgpu = { version = "0.19.3", default-features = false, features = [
|
||||
"wgsl",
|
||||
"dx12",
|
||||
"metal",
|
||||
@ -74,7 +74,7 @@ wgpu = { version = "0.19.1", default-features = false, features = [
|
||||
] }
|
||||
naga = { version = "0.19", features = ["wgsl-in"] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
bitflags = "2.3"
|
||||
bitflags = { version = "2.3", features = ["serde"] }
|
||||
bytemuck = { version = "1.5", features = ["derive"] }
|
||||
downcast-rs = "1.2.0"
|
||||
thread_local = "1.1"
|
||||
@ -105,9 +105,7 @@ naga_oil = { version = "0.13", default-features = false, features = [
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
naga_oil = "0.13"
|
||||
js-sys = "0.3"
|
||||
# web-sys doesn't follow semver for the WebGPU APIs as they are unstable
|
||||
# Make sure that WebGPU builds work when changing this!
|
||||
web-sys = { version = "=0.3.67", features = [
|
||||
web-sys = { version = "0.3.67", features = [
|
||||
'Blob',
|
||||
'Document',
|
||||
'Element',
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_render_macros"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Derive implementations for bevy_render"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -12,7 +12,7 @@ keywords = ["bevy"]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
bevy_macro_utils = { path = "../../bevy_macro_utils", version = "0.13.0" }
|
||||
bevy_macro_utils = { path = "../../bevy_macro_utils", version = "0.13.1" }
|
||||
|
||||
syn = "2.0"
|
||||
proc-macro2 = "1.0"
|
||||
|
@ -360,6 +360,7 @@ impl Plugin for RenderPlugin {
|
||||
.insert_resource(instance)
|
||||
.insert_resource(PipelineCache::new(
|
||||
device.clone(),
|
||||
render_adapter.clone(),
|
||||
self.synchronous_pipeline_compilation,
|
||||
))
|
||||
.insert_resource(device)
|
||||
|
@ -66,6 +66,13 @@ bitflags::bitflags! {
|
||||
///
|
||||
/// If you have an asset that doesn't actually need to end up in the render world, like an Image
|
||||
/// that will be decoded into another Image asset, use `MAIN_WORLD` only.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// On Wasm, it is not possible for now to free reserved memory. To control memory usage, load assets
|
||||
/// in sequence and unload one before loading the next. See this
|
||||
/// [discussion about memory management](https://github.com/WebAssembly/design/issues/1397) for more
|
||||
/// details.
|
||||
#[repr(transparent)]
|
||||
#[derive(Serialize, TypePath, Deserialize, Hash, Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub struct RenderAssetUsages: u8 {
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::renderer::RenderAdapter;
|
||||
use crate::{render_resource::*, renderer::RenderDevice, Extract};
|
||||
use bevy_asset::{AssetEvent, AssetId, Assets};
|
||||
use bevy_ecs::system::{Res, ResMut};
|
||||
@ -21,7 +22,7 @@ use thiserror::Error;
|
||||
#[cfg(feature = "shader_format_spirv")]
|
||||
use wgpu::util::make_spirv;
|
||||
use wgpu::{
|
||||
Features, PipelineLayoutDescriptor, PushConstantRange, ShaderModuleDescriptor,
|
||||
DownlevelFlags, Features, PipelineLayoutDescriptor, PushConstantRange, ShaderModuleDescriptor,
|
||||
VertexBufferLayout as RawVertexBufferLayout,
|
||||
};
|
||||
|
||||
@ -167,7 +168,7 @@ impl ShaderDefVal {
|
||||
}
|
||||
|
||||
impl ShaderCache {
|
||||
fn new(render_device: &RenderDevice) -> Self {
|
||||
fn new(render_device: &RenderDevice, render_adapter: &RenderAdapter) -> Self {
|
||||
const CAPABILITIES: &[(Features, Capabilities)] = &[
|
||||
(Features::PUSH_CONSTANTS, Capabilities::PUSH_CONSTANT),
|
||||
(Features::SHADER_F64, Capabilities::FLOAT64),
|
||||
@ -196,9 +197,13 @@ impl ShaderCache {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Check if this is supported, though I'm not sure if bevy works without this feature?
|
||||
// We can't compile for native at least without it.
|
||||
capabilities |= Capabilities::CUBE_ARRAY_TEXTURES;
|
||||
if render_adapter
|
||||
.get_downlevel_capabilities()
|
||||
.flags
|
||||
.contains(DownlevelFlags::CUBE_ARRAY_TEXTURES)
|
||||
{
|
||||
capabilities |= Capabilities::CUBE_ARRAY_TEXTURES;
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
let composer = naga_oil::compose::Composer::default();
|
||||
@ -279,9 +284,14 @@ impl ShaderCache {
|
||||
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
|
||||
{
|
||||
shader_defs.push("NO_ARRAY_TEXTURES_SUPPORT".into());
|
||||
shader_defs.push("NO_CUBE_ARRAY_TEXTURES_SUPPORT".into());
|
||||
shader_defs.push("SIXTEEN_BYTE_ALIGNMENT".into());
|
||||
}
|
||||
|
||||
if cfg!(ios_simulator) {
|
||||
shader_defs.push("NO_CUBE_ARRAY_TEXTURES_SUPPORT".into());
|
||||
}
|
||||
|
||||
shader_defs.push(ShaderDefVal::UInt(
|
||||
String::from("AVAILABLE_STORAGE_BUFFER_BINDINGS"),
|
||||
render_device.limits().max_storage_buffers_per_shader_stage,
|
||||
@ -491,9 +501,13 @@ impl PipelineCache {
|
||||
}
|
||||
|
||||
/// Create a new pipeline cache associated with the given render device.
|
||||
pub fn new(device: RenderDevice, synchronous_pipeline_compilation: bool) -> Self {
|
||||
pub fn new(
|
||||
device: RenderDevice,
|
||||
render_adapter: RenderAdapter,
|
||||
synchronous_pipeline_compilation: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
shader_cache: Arc::new(Mutex::new(ShaderCache::new(&device))),
|
||||
shader_cache: Arc::new(Mutex::new(ShaderCache::new(&device, &render_adapter))),
|
||||
device,
|
||||
layout_cache: default(),
|
||||
waiting_pipelines: default(),
|
||||
@ -881,7 +895,9 @@ impl PipelineCache {
|
||||
CachedPipelineState::Err(err) => match err {
|
||||
// Retry
|
||||
PipelineCacheError::ShaderNotLoaded(_)
|
||||
| PipelineCacheError::ShaderImportNotYetAvailable => {}
|
||||
| PipelineCacheError::ShaderImportNotYetAvailable => {
|
||||
cached_pipeline.state = CachedPipelineState::Queued;
|
||||
}
|
||||
|
||||
// Shader could not be processed ... retrying won't help
|
||||
PipelineCacheError::ProcessShaderError(err) => {
|
||||
|
@ -118,6 +118,8 @@ impl Plugin for ImagePlugin {
|
||||
feature = "bmp",
|
||||
feature = "basis-universal",
|
||||
feature = "ktx2",
|
||||
feature = "webp",
|
||||
feature = "pnm"
|
||||
))]
|
||||
app.preregister_asset_loader::<ImageLoader>(IMG_FILE_EXTENSIONS);
|
||||
}
|
||||
@ -131,6 +133,8 @@ impl Plugin for ImagePlugin {
|
||||
feature = "bmp",
|
||||
feature = "basis-universal",
|
||||
feature = "ktx2",
|
||||
feature = "webp",
|
||||
feature = "pnm"
|
||||
))]
|
||||
{
|
||||
app.init_asset_loader::<ImageLoader>();
|
||||
|
@ -498,7 +498,7 @@ pub fn prepare_view_targets(
|
||||
_ => Some(clear_color_global.0),
|
||||
};
|
||||
|
||||
let (a, b, sampled) = textures
|
||||
let (a, b, sampled, main_texture) = textures
|
||||
.entry((camera.target.clone(), view.hdr))
|
||||
.or_insert_with(|| {
|
||||
let descriptor = TextureDescriptor {
|
||||
@ -547,13 +547,14 @@ pub fn prepare_view_targets(
|
||||
} else {
|
||||
None
|
||||
};
|
||||
(a, b, sampled)
|
||||
let main_texture = Arc::new(AtomicUsize::new(0));
|
||||
(a, b, sampled, main_texture)
|
||||
});
|
||||
|
||||
let main_textures = MainTargetTextures {
|
||||
a: ColorAttachment::new(a.clone(), sampled.clone(), clear_color),
|
||||
b: ColorAttachment::new(b.clone(), sampled.clone(), clear_color),
|
||||
main_texture: Arc::new(AtomicUsize::new(0)),
|
||||
main_texture: main_texture.clone(),
|
||||
};
|
||||
|
||||
commands.entity(entity).insert(ViewTarget {
|
||||
|
@ -17,7 +17,8 @@ use std::{
|
||||
sync::PoisonError,
|
||||
};
|
||||
use wgpu::{
|
||||
BufferUsages, SurfaceTargetUnsafe, TextureFormat, TextureUsages, TextureViewDescriptor,
|
||||
BufferUsages, SurfaceConfiguration, SurfaceTargetUnsafe, TextureFormat, TextureUsages,
|
||||
TextureViewDescriptor,
|
||||
};
|
||||
|
||||
pub mod screenshot;
|
||||
@ -42,7 +43,7 @@ impl Plugin for WindowRenderPlugin {
|
||||
.add_systems(
|
||||
Render,
|
||||
create_surfaces
|
||||
.run_if(need_new_surfaces)
|
||||
.run_if(need_surface_configuration)
|
||||
.before(prepare_windows),
|
||||
)
|
||||
.add_systems(Render, prepare_windows.in_set(RenderSet::ManageViews));
|
||||
@ -198,7 +199,7 @@ fn extract_windows(
|
||||
struct SurfaceData {
|
||||
// TODO: what lifetime should this be?
|
||||
surface: wgpu::Surface<'static>,
|
||||
format: TextureFormat,
|
||||
configuration: SurfaceConfiguration,
|
||||
}
|
||||
|
||||
#[derive(Resource, Default)]
|
||||
@ -254,45 +255,12 @@ pub fn prepare_windows(
|
||||
continue;
|
||||
};
|
||||
|
||||
let surface_configuration = wgpu::SurfaceConfiguration {
|
||||
format: surface_data.format,
|
||||
width: window.physical_width,
|
||||
height: window.physical_height,
|
||||
usage: TextureUsages::RENDER_ATTACHMENT,
|
||||
present_mode: match window.present_mode {
|
||||
PresentMode::Fifo => wgpu::PresentMode::Fifo,
|
||||
PresentMode::FifoRelaxed => wgpu::PresentMode::FifoRelaxed,
|
||||
PresentMode::Mailbox => wgpu::PresentMode::Mailbox,
|
||||
PresentMode::Immediate => wgpu::PresentMode::Immediate,
|
||||
PresentMode::AutoVsync => wgpu::PresentMode::AutoVsync,
|
||||
PresentMode::AutoNoVsync => wgpu::PresentMode::AutoNoVsync,
|
||||
},
|
||||
// TODO: Expose this as a setting somewhere
|
||||
// 2 is wgpu's default/what we've been using so far.
|
||||
// 1 is the minimum, but may cause lower framerates due to the cpu waiting for the gpu to finish
|
||||
// all work for the previous frame before starting work on the next frame, which then means the gpu
|
||||
// has to wait for the cpu to finish to start on the next frame.
|
||||
desired_maximum_frame_latency: 2,
|
||||
alpha_mode: match window.alpha_mode {
|
||||
CompositeAlphaMode::Auto => wgpu::CompositeAlphaMode::Auto,
|
||||
CompositeAlphaMode::Opaque => wgpu::CompositeAlphaMode::Opaque,
|
||||
CompositeAlphaMode::PreMultiplied => wgpu::CompositeAlphaMode::PreMultiplied,
|
||||
CompositeAlphaMode::PostMultiplied => wgpu::CompositeAlphaMode::PostMultiplied,
|
||||
CompositeAlphaMode::Inherit => wgpu::CompositeAlphaMode::Inherit,
|
||||
},
|
||||
view_formats: if !surface_data.format.is_srgb() {
|
||||
vec![surface_data.format.add_srgb_suffix()]
|
||||
} else {
|
||||
vec![]
|
||||
},
|
||||
};
|
||||
|
||||
// This is an ugly hack to work around drivers that don't support MSAA.
|
||||
// This should be removed once https://github.com/bevyengine/bevy/issues/7194 lands and we're doing proper
|
||||
// feature detection for MSAA.
|
||||
// When removed, we can also remove the `.after(prepare_windows)` of `prepare_core_3d_depth_textures` and `prepare_prepass_textures`
|
||||
let sample_flags = render_adapter
|
||||
.get_texture_format_features(surface_configuration.format)
|
||||
.get_texture_format_features(surface_data.configuration.format)
|
||||
.flags;
|
||||
|
||||
if !sample_flags.sample_count_supported(msaa.samples()) {
|
||||
@ -340,7 +308,6 @@ pub fn prepare_windows(
|
||||
|
||||
let surface = &surface_data.surface;
|
||||
if not_already_configured || window.size_changed || window.present_mode_changed {
|
||||
render_device.configure_surface(surface, &surface_configuration);
|
||||
let frame = surface
|
||||
.get_current_texture()
|
||||
.expect("Error configuring surface");
|
||||
@ -351,7 +318,7 @@ pub fn prepare_windows(
|
||||
window.set_swapchain_texture(frame);
|
||||
}
|
||||
Err(wgpu::SurfaceError::Outdated) => {
|
||||
render_device.configure_surface(surface, &surface_configuration);
|
||||
render_device.configure_surface(surface, &surface_data.configuration);
|
||||
let frame = surface
|
||||
.get_current_texture()
|
||||
.expect("Error reconfiguring surface");
|
||||
@ -369,20 +336,20 @@ pub fn prepare_windows(
|
||||
}
|
||||
}
|
||||
};
|
||||
window.swap_chain_texture_format = Some(surface_data.format);
|
||||
window.swap_chain_texture_format = Some(surface_data.configuration.format);
|
||||
|
||||
if window.screenshot_func.is_some() {
|
||||
let texture = render_device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: Some("screenshot-capture-rendertarget"),
|
||||
size: wgpu::Extent3d {
|
||||
width: surface_configuration.width,
|
||||
height: surface_configuration.height,
|
||||
width: surface_data.configuration.width,
|
||||
height: surface_data.configuration.height,
|
||||
depth_or_array_layers: 1,
|
||||
},
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: surface_configuration.format.add_srgb_suffix(),
|
||||
format: surface_data.configuration.format.add_srgb_suffix(),
|
||||
usage: TextureUsages::RENDER_ATTACHMENT
|
||||
| TextureUsages::COPY_SRC
|
||||
| TextureUsages::TEXTURE_BINDING,
|
||||
@ -394,7 +361,7 @@ pub fn prepare_windows(
|
||||
size: screenshot::get_aligned_size(
|
||||
window.physical_width,
|
||||
window.physical_height,
|
||||
surface_data.format.pixel_size() as u32,
|
||||
surface_data.configuration.format.pixel_size() as u32,
|
||||
) as u64,
|
||||
usage: BufferUsages::MAP_READ | BufferUsages::COPY_DST,
|
||||
mapped_at_creation: false,
|
||||
@ -407,7 +374,7 @@ pub fn prepare_windows(
|
||||
let pipeline_id = pipelines.specialize(
|
||||
&pipeline_cache,
|
||||
&screenshot_pipeline,
|
||||
surface_configuration.format,
|
||||
surface_data.configuration.format,
|
||||
);
|
||||
window.swap_chain_texture_view = Some(texture_view);
|
||||
window.screenshot_memory = Some(ScreenshotPreparedState {
|
||||
@ -420,12 +387,15 @@ pub fn prepare_windows(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn need_new_surfaces(
|
||||
pub fn need_surface_configuration(
|
||||
windows: Res<ExtractedWindows>,
|
||||
window_surfaces: Res<WindowSurfaces>,
|
||||
) -> bool {
|
||||
for window in windows.windows.values() {
|
||||
if !window_surfaces.configured_windows.contains(&window.entity) {
|
||||
if !window_surfaces.configured_windows.contains(&window.entity)
|
||||
|| window.size_changed
|
||||
|| window.present_mode_changed
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -443,9 +413,10 @@ pub fn create_surfaces(
|
||||
mut window_surfaces: ResMut<WindowSurfaces>,
|
||||
render_instance: Res<RenderInstance>,
|
||||
render_adapter: Res<RenderAdapter>,
|
||||
render_device: Res<RenderDevice>,
|
||||
) {
|
||||
for window in windows.windows.values() {
|
||||
window_surfaces
|
||||
let data = window_surfaces
|
||||
.surfaces
|
||||
.entry(window.entity)
|
||||
.or_insert_with(|| {
|
||||
@ -477,7 +448,63 @@ pub fn create_surfaces(
|
||||
}
|
||||
}
|
||||
|
||||
SurfaceData { surface, format }
|
||||
let configuration = wgpu::SurfaceConfiguration {
|
||||
format,
|
||||
width: window.physical_width,
|
||||
height: window.physical_height,
|
||||
usage: TextureUsages::RENDER_ATTACHMENT,
|
||||
present_mode: match window.present_mode {
|
||||
PresentMode::Fifo => wgpu::PresentMode::Fifo,
|
||||
PresentMode::FifoRelaxed => wgpu::PresentMode::FifoRelaxed,
|
||||
PresentMode::Mailbox => wgpu::PresentMode::Mailbox,
|
||||
PresentMode::Immediate => wgpu::PresentMode::Immediate,
|
||||
PresentMode::AutoVsync => wgpu::PresentMode::AutoVsync,
|
||||
PresentMode::AutoNoVsync => wgpu::PresentMode::AutoNoVsync,
|
||||
},
|
||||
// TODO: Expose this as a setting somewhere
|
||||
// 2 is wgpu's default/what we've been using so far.
|
||||
// 1 is the minimum, but may cause lower framerates due to the cpu waiting for the gpu to finish
|
||||
// all work for the previous frame before starting work on the next frame, which then means the gpu
|
||||
// has to wait for the cpu to finish to start on the next frame.
|
||||
desired_maximum_frame_latency: 2,
|
||||
alpha_mode: match window.alpha_mode {
|
||||
CompositeAlphaMode::Auto => wgpu::CompositeAlphaMode::Auto,
|
||||
CompositeAlphaMode::Opaque => wgpu::CompositeAlphaMode::Opaque,
|
||||
CompositeAlphaMode::PreMultiplied => {
|
||||
wgpu::CompositeAlphaMode::PreMultiplied
|
||||
}
|
||||
CompositeAlphaMode::PostMultiplied => {
|
||||
wgpu::CompositeAlphaMode::PostMultiplied
|
||||
}
|
||||
CompositeAlphaMode::Inherit => wgpu::CompositeAlphaMode::Inherit,
|
||||
},
|
||||
view_formats: if !format.is_srgb() {
|
||||
vec![format.add_srgb_suffix()]
|
||||
} else {
|
||||
vec![]
|
||||
},
|
||||
};
|
||||
|
||||
render_device.configure_surface(&surface, &configuration);
|
||||
|
||||
SurfaceData {
|
||||
surface,
|
||||
configuration,
|
||||
}
|
||||
});
|
||||
|
||||
if window.size_changed || window.present_mode_changed {
|
||||
data.configuration.width = window.physical_width;
|
||||
data.configuration.height = window.physical_height;
|
||||
data.configuration.present_mode = match window.present_mode {
|
||||
PresentMode::Fifo => wgpu::PresentMode::Fifo,
|
||||
PresentMode::FifoRelaxed => wgpu::PresentMode::FifoRelaxed,
|
||||
PresentMode::Mailbox => wgpu::PresentMode::Mailbox,
|
||||
PresentMode::Immediate => wgpu::PresentMode::Immediate,
|
||||
PresentMode::AutoVsync => wgpu::PresentMode::AutoVsync,
|
||||
PresentMode::AutoNoVsync => wgpu::PresentMode::AutoNoVsync,
|
||||
};
|
||||
render_device.configure_surface(&data.surface, &data.configuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_scene"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Provides scene functionality for Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -14,17 +14,17 @@ serialize = ["dep:serde", "uuid/serde"]
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.0" }
|
||||
bevy_asset = { path = "../bevy_asset", version = "0.13.0" }
|
||||
bevy_derive = { path = "../bevy_derive", version = "0.13.0" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.0" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.0", features = [
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.1" }
|
||||
bevy_asset = { path = "../bevy_asset", version = "0.13.1" }
|
||||
bevy_derive = { path = "../bevy_derive", version = "0.13.1" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.1" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.1", features = [
|
||||
"bevy",
|
||||
] }
|
||||
bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.13.0" }
|
||||
bevy_transform = { path = "../bevy_transform", version = "0.13.0" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.0" }
|
||||
bevy_render = { path = "../bevy_render", version = "0.13.0", optional = true }
|
||||
bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.13.1" }
|
||||
bevy_transform = { path = "../bevy_transform", version = "0.13.1" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.1" }
|
||||
bevy_render = { path = "../bevy_render", version = "0.13.1", optional = true }
|
||||
|
||||
# other
|
||||
serde = { version = "1.0", features = ["derive"], optional = true }
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_sprite"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Provides sprite functionality for Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -14,19 +14,19 @@ webgpu = []
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.0" }
|
||||
bevy_asset = { path = "../bevy_asset", version = "0.13.0" }
|
||||
bevy_core_pipeline = { path = "../bevy_core_pipeline", version = "0.13.0" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.0" }
|
||||
bevy_log = { path = "../bevy_log", version = "0.13.0" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.0" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.0", features = [
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.1" }
|
||||
bevy_asset = { path = "../bevy_asset", version = "0.13.1" }
|
||||
bevy_core_pipeline = { path = "../bevy_core_pipeline", version = "0.13.1" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.1" }
|
||||
bevy_log = { path = "../bevy_log", version = "0.13.1" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.1" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.1", features = [
|
||||
"bevy",
|
||||
] }
|
||||
bevy_render = { path = "../bevy_render", version = "0.13.0" }
|
||||
bevy_transform = { path = "../bevy_transform", version = "0.13.0" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.0" }
|
||||
bevy_derive = { path = "../bevy_derive", version = "0.13.0" }
|
||||
bevy_render = { path = "../bevy_render", version = "0.13.1" }
|
||||
bevy_transform = { path = "../bevy_transform", version = "0.13.1" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.1" }
|
||||
bevy_derive = { path = "../bevy_derive", version = "0.13.1" }
|
||||
|
||||
# other
|
||||
bytemuck = { version = "1.5", features = ["derive"] }
|
||||
|
@ -32,6 +32,8 @@ pub struct Sprite {
|
||||
}
|
||||
|
||||
/// Controls how the image is altered when scaled.
|
||||
///
|
||||
/// Note: This is not yet compatible with texture atlases
|
||||
#[derive(Component, Debug, Clone, Reflect)]
|
||||
#[reflect(Component)]
|
||||
pub enum ImageScaleMode {
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_tasks"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "A task executor for Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_text"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Provides text functionality for Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -14,18 +14,18 @@ default_font = []
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.0" }
|
||||
bevy_asset = { path = "../bevy_asset", version = "0.13.0" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.0" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.0" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.0", features = [
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.1" }
|
||||
bevy_asset = { path = "../bevy_asset", version = "0.13.1" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.1" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.1" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.1", features = [
|
||||
"bevy",
|
||||
] }
|
||||
bevy_render = { path = "../bevy_render", version = "0.13.0" }
|
||||
bevy_sprite = { path = "../bevy_sprite", version = "0.13.0" }
|
||||
bevy_transform = { path = "../bevy_transform", version = "0.13.0" }
|
||||
bevy_window = { path = "../bevy_window", version = "0.13.0" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.0" }
|
||||
bevy_render = { path = "../bevy_render", version = "0.13.1" }
|
||||
bevy_sprite = { path = "../bevy_sprite", version = "0.13.1" }
|
||||
bevy_transform = { path = "../bevy_transform", version = "0.13.1" }
|
||||
bevy_window = { path = "../bevy_window", version = "0.13.1" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.1" }
|
||||
|
||||
# other
|
||||
ab_glyph = "0.2.6"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_time"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Provides time functionality for Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -15,14 +15,14 @@ bevy_ci_testing = ["bevy_app/bevy_ci_testing"]
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.0" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.0", features = [
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.1" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.1", features = [
|
||||
"bevy_reflect",
|
||||
] }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.0", features = [
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.1", features = [
|
||||
"bevy",
|
||||
] }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.0" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.1" }
|
||||
|
||||
# other
|
||||
crossbeam-channel = "0.5.0"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_transform"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Provides transform functionality for Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -10,21 +10,21 @@ keywords = ["bevy"]
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.0" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.0", features = [
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.1" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.1", features = [
|
||||
"bevy_reflect",
|
||||
] }
|
||||
bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.13.0" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.0" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.0", features = [
|
||||
bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.13.1" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.1" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.1", features = [
|
||||
"bevy",
|
||||
] }
|
||||
serde = { version = "1", features = ["derive"], optional = true }
|
||||
thiserror = "1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
bevy_tasks = { path = "../bevy_tasks", version = "0.13.0" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.0", features = ["approx"] }
|
||||
bevy_tasks = { path = "../bevy_tasks", version = "0.13.1" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.1", features = ["approx"] }
|
||||
approx = "0.5.1"
|
||||
|
||||
[features]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_ui"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "A custom ECS-driven UI framework built specifically for Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -10,25 +10,25 @@ keywords = ["bevy"]
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
bevy_a11y = { path = "../bevy_a11y", version = "0.13.0" }
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.0" }
|
||||
bevy_asset = { path = "../bevy_asset", version = "0.13.0" }
|
||||
bevy_core_pipeline = { path = "../bevy_core_pipeline", version = "0.13.0" }
|
||||
bevy_derive = { path = "../bevy_derive", version = "0.13.0" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.0" }
|
||||
bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.13.0" }
|
||||
bevy_input = { path = "../bevy_input", version = "0.13.0" }
|
||||
bevy_log = { path = "../bevy_log", version = "0.13.0" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.0" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.0", features = [
|
||||
bevy_a11y = { path = "../bevy_a11y", version = "0.13.1" }
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.1" }
|
||||
bevy_asset = { path = "../bevy_asset", version = "0.13.1" }
|
||||
bevy_core_pipeline = { path = "../bevy_core_pipeline", version = "0.13.1" }
|
||||
bevy_derive = { path = "../bevy_derive", version = "0.13.1" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.1" }
|
||||
bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.13.1" }
|
||||
bevy_input = { path = "../bevy_input", version = "0.13.1" }
|
||||
bevy_log = { path = "../bevy_log", version = "0.13.1" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.1" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.1", features = [
|
||||
"bevy",
|
||||
] }
|
||||
bevy_render = { path = "../bevy_render", version = "0.13.0" }
|
||||
bevy_sprite = { path = "../bevy_sprite", version = "0.13.0" }
|
||||
bevy_text = { path = "../bevy_text", version = "0.13.0", optional = true }
|
||||
bevy_transform = { path = "../bevy_transform", version = "0.13.0" }
|
||||
bevy_window = { path = "../bevy_window", version = "0.13.0" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.0" }
|
||||
bevy_render = { path = "../bevy_render", version = "0.13.1" }
|
||||
bevy_sprite = { path = "../bevy_sprite", version = "0.13.1" }
|
||||
bevy_text = { path = "../bevy_text", version = "0.13.1", optional = true }
|
||||
bevy_transform = { path = "../bevy_transform", version = "0.13.1" }
|
||||
bevy_window = { path = "../bevy_window", version = "0.13.1" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.1" }
|
||||
|
||||
# other
|
||||
taffy = { version = "0.3.10" }
|
||||
|
@ -251,9 +251,16 @@ pub fn ui_focus_system(
|
||||
// The mouse position relative to the node
|
||||
// (0., 0.) is the top-left corner, (1., 1.) is the bottom-right corner
|
||||
// Coordinates are relative to the entire node, not just the visible region.
|
||||
let relative_cursor_position = camera_cursor_positions
|
||||
.get(&camera_entity)
|
||||
.map(|cursor_position| (*cursor_position - node_rect.min) / node_rect.size());
|
||||
let relative_cursor_position =
|
||||
camera_cursor_positions
|
||||
.get(&camera_entity)
|
||||
.and_then(|cursor_position| {
|
||||
// ensure node size is non-zero in all dimensions, otherwise relative position will be
|
||||
// +/-inf. if the node is hidden, the visible rect min/max will also be -inf leading to
|
||||
// false positives for mouse_over (#12395)
|
||||
(node_rect.size().cmpgt(Vec2::ZERO).all())
|
||||
.then_some((*cursor_position - node_rect.min) / node_rect.size())
|
||||
});
|
||||
|
||||
// If the current cursor position is within the bounds of the node's visible area, consider it for
|
||||
// clicking
|
||||
|
@ -2,14 +2,13 @@ mod convert;
|
||||
pub mod debug;
|
||||
|
||||
use crate::{ContentSize, DefaultUiCamera, Node, Outline, Style, TargetCamera, UiScale};
|
||||
use bevy_ecs::entity::EntityHashMap;
|
||||
use bevy_ecs::{
|
||||
change_detection::{DetectChanges, DetectChangesMut},
|
||||
entity::Entity,
|
||||
entity::{Entity, EntityHashMap},
|
||||
event::EventReader,
|
||||
query::{With, Without},
|
||||
removal_detection::RemovedComponents,
|
||||
system::{Query, Res, ResMut, Resource},
|
||||
system::{Query, Res, ResMut, Resource, SystemParam},
|
||||
world::Ref,
|
||||
};
|
||||
use bevy_hierarchy::{Children, Parent};
|
||||
@ -53,6 +52,7 @@ struct RootNodePair {
|
||||
#[derive(Resource)]
|
||||
pub struct UiSurface {
|
||||
entity_to_taffy: EntityHashMap<taffy::node::Node>,
|
||||
camera_entity_to_taffy: EntityHashMap<taffy::node::Node>,
|
||||
camera_roots: EntityHashMap<Vec<RootNodePair>>,
|
||||
taffy: Taffy,
|
||||
}
|
||||
@ -79,6 +79,7 @@ impl Default for UiSurface {
|
||||
taffy.disable_rounding();
|
||||
Self {
|
||||
entity_to_taffy: Default::default(),
|
||||
camera_entity_to_taffy: Default::default(),
|
||||
camera_roots: Default::default(),
|
||||
taffy,
|
||||
}
|
||||
@ -167,6 +168,10 @@ without UI components as a child of an entity with UI components, results may be
|
||||
..default()
|
||||
};
|
||||
|
||||
let camera_node = *self
|
||||
.camera_entity_to_taffy
|
||||
.entry(camera_id)
|
||||
.or_insert_with(|| self.taffy.new_leaf(viewport_style.clone()).unwrap());
|
||||
let existing_roots = self.camera_roots.entry(camera_id).or_default();
|
||||
let mut new_roots = Vec::new();
|
||||
for entity in children {
|
||||
@ -181,24 +186,16 @@ without UI components as a child of an entity with UI components, results may be
|
||||
self.taffy.remove_child(previous_parent, node).unwrap();
|
||||
}
|
||||
|
||||
self.taffy.add_child(camera_node, node).unwrap();
|
||||
|
||||
RootNodePair {
|
||||
implicit_viewport_node: self
|
||||
.taffy
|
||||
.new_with_children(viewport_style.clone(), &[node])
|
||||
.unwrap(),
|
||||
implicit_viewport_node: camera_node,
|
||||
user_root_node: node,
|
||||
}
|
||||
});
|
||||
new_roots.push(root_node);
|
||||
}
|
||||
|
||||
// Cleanup the implicit root nodes of any user root nodes that have been removed
|
||||
for old_root in existing_roots {
|
||||
if !new_roots.contains(old_root) {
|
||||
self.taffy.remove(old_root.implicit_viewport_node).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
self.camera_roots.insert(camera_id, new_roots);
|
||||
}
|
||||
|
||||
@ -219,6 +216,15 @@ without UI components as a child of an entity with UI components, results may be
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes each camera entity from the internal map and then removes their associated node from taffy
|
||||
pub fn remove_camera_entities(&mut self, entities: impl IntoIterator<Item = Entity>) {
|
||||
for entity in entities {
|
||||
if let Some(node) = self.camera_entity_to_taffy.remove(&entity) {
|
||||
self.taffy.remove(node).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes each entity from the internal map and then removes their associated node from taffy
|
||||
pub fn remove_entities(&mut self, entities: impl IntoIterator<Item = Entity>) {
|
||||
for entity in entities {
|
||||
@ -253,6 +259,14 @@ pub enum LayoutError {
|
||||
TaffyError(#[from] taffy::error::TaffyError),
|
||||
}
|
||||
|
||||
#[derive(SystemParam)]
|
||||
pub struct UiLayoutSystemRemovedComponentParam<'w, 's> {
|
||||
removed_cameras: RemovedComponents<'w, 's, Camera>,
|
||||
removed_children: RemovedComponents<'w, 's, Children>,
|
||||
removed_content_sizes: RemovedComponents<'w, 's, ContentSize>,
|
||||
removed_nodes: RemovedComponents<'w, 's, Node>,
|
||||
}
|
||||
|
||||
/// Updates the UI's layout tree, computes the new layout geometry and then updates the sizes and transforms of all the UI nodes.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn ui_layout_system(
|
||||
@ -268,9 +282,7 @@ pub fn ui_layout_system(
|
||||
mut measure_query: Query<(Entity, &mut ContentSize)>,
|
||||
children_query: Query<(Entity, Ref<Children>), With<Node>>,
|
||||
just_children_query: Query<&Children>,
|
||||
mut removed_children: RemovedComponents<Children>,
|
||||
mut removed_content_sizes: RemovedComponents<ContentSize>,
|
||||
mut removed_nodes: RemovedComponents<Node>,
|
||||
mut removed_components: UiLayoutSystemRemovedComponentParam,
|
||||
mut node_transform_query: Query<(&mut Node, &mut Transform)>,
|
||||
) {
|
||||
struct CameraLayoutInfo {
|
||||
@ -357,7 +369,7 @@ pub fn ui_layout_system(
|
||||
scale_factor_events.clear();
|
||||
|
||||
// When a `ContentSize` component is removed from an entity, we need to remove the measure from the corresponding taffy node.
|
||||
for entity in removed_content_sizes.read() {
|
||||
for entity in removed_components.removed_content_sizes.read() {
|
||||
ui_surface.try_remove_measure(entity);
|
||||
}
|
||||
for (entity, mut content_size) in &mut measure_query {
|
||||
@ -367,15 +379,24 @@ pub fn ui_layout_system(
|
||||
}
|
||||
|
||||
// clean up removed nodes
|
||||
ui_surface.remove_entities(removed_nodes.read());
|
||||
ui_surface.remove_entities(removed_components.removed_nodes.read());
|
||||
|
||||
// clean up removed cameras
|
||||
ui_surface.remove_camera_entities(removed_components.removed_cameras.read());
|
||||
|
||||
// update camera children
|
||||
for (camera_id, CameraLayoutInfo { root_nodes, .. }) in &camera_layout_info {
|
||||
ui_surface.set_camera_children(*camera_id, root_nodes.iter().cloned());
|
||||
for (camera_id, _) in cameras.iter() {
|
||||
let root_nodes =
|
||||
if let Some(CameraLayoutInfo { root_nodes, .. }) = camera_layout_info.get(&camera_id) {
|
||||
root_nodes.iter().cloned()
|
||||
} else {
|
||||
[].iter().cloned()
|
||||
};
|
||||
ui_surface.set_camera_children(camera_id, root_nodes);
|
||||
}
|
||||
|
||||
// update and remove children
|
||||
for entity in removed_children.read() {
|
||||
for entity in removed_components.removed_children.read() {
|
||||
ui_surface.try_remove_children(entity);
|
||||
}
|
||||
for (entity, children) in &children_query {
|
||||
@ -411,7 +432,9 @@ pub fn ui_layout_system(
|
||||
mut absolute_location: Vec2,
|
||||
) {
|
||||
if let Ok((mut node, mut transform)) = node_transform_query.get_mut(entity) {
|
||||
let layout = ui_surface.get_layout(entity).unwrap();
|
||||
let Ok(layout) = ui_surface.get_layout(entity) else {
|
||||
return;
|
||||
};
|
||||
let layout_size =
|
||||
inverse_target_scale_factor * Vec2::new(layout.size.width, layout.size.height);
|
||||
let layout_location =
|
||||
@ -519,17 +542,20 @@ mod tests {
|
||||
use bevy_core_pipeline::core_2d::Camera2dBundle;
|
||||
use bevy_ecs::entity::Entity;
|
||||
use bevy_ecs::event::Events;
|
||||
use bevy_ecs::prelude::{Commands, Component, In, Query, With};
|
||||
use bevy_ecs::schedule::apply_deferred;
|
||||
use bevy_ecs::schedule::IntoSystemConfigs;
|
||||
use bevy_ecs::schedule::Schedule;
|
||||
use bevy_ecs::system::RunSystemOnce;
|
||||
use bevy_ecs::world::World;
|
||||
use bevy_hierarchy::despawn_with_children_recursive;
|
||||
use bevy_hierarchy::BuildWorldChildren;
|
||||
use bevy_hierarchy::Children;
|
||||
use bevy_math::vec2;
|
||||
use bevy_math::Vec2;
|
||||
use bevy_math::{vec2, UVec2};
|
||||
use bevy_render::camera::ManualTextureViews;
|
||||
use bevy_render::camera::OrthographicProjection;
|
||||
use bevy_render::prelude::Camera;
|
||||
use bevy_render::texture::Image;
|
||||
use bevy_utils::prelude::default;
|
||||
use bevy_utils::HashMap;
|
||||
@ -655,6 +681,54 @@ mod tests {
|
||||
assert!(ui_surface.entity_to_taffy.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ui_surface_tracks_camera_entities() {
|
||||
let (mut world, mut ui_schedule) = setup_ui_test_world();
|
||||
|
||||
// despawn all cameras so we can reset ui_surface back to a fresh state
|
||||
let camera_entities = world
|
||||
.query_filtered::<Entity, With<Camera>>()
|
||||
.iter(&world)
|
||||
.collect::<Vec<_>>();
|
||||
for camera_entity in camera_entities {
|
||||
world.despawn(camera_entity);
|
||||
}
|
||||
|
||||
ui_schedule.run(&mut world);
|
||||
|
||||
// no UI entities in world, none in UiSurface
|
||||
let ui_surface = world.resource::<UiSurface>();
|
||||
assert!(ui_surface.camera_entity_to_taffy.is_empty());
|
||||
|
||||
// respawn camera
|
||||
let camera_entity = world.spawn(Camera2dBundle::default()).id();
|
||||
|
||||
let ui_entity = world
|
||||
.spawn((NodeBundle::default(), TargetCamera(camera_entity)))
|
||||
.id();
|
||||
|
||||
// `ui_layout_system` should map `camera_entity` to a ui node in `UiSurface::camera_entity_to_taffy`
|
||||
ui_schedule.run(&mut world);
|
||||
|
||||
let ui_surface = world.resource::<UiSurface>();
|
||||
assert!(ui_surface
|
||||
.camera_entity_to_taffy
|
||||
.contains_key(&camera_entity));
|
||||
assert_eq!(ui_surface.camera_entity_to_taffy.len(), 1);
|
||||
|
||||
world.despawn(ui_entity);
|
||||
world.despawn(camera_entity);
|
||||
|
||||
// `ui_layout_system` should remove `camera_entity` from `UiSurface::camera_entity_to_taffy`
|
||||
ui_schedule.run(&mut world);
|
||||
|
||||
let ui_surface = world.resource::<UiSurface>();
|
||||
assert!(!ui_surface
|
||||
.camera_entity_to_taffy
|
||||
.contains_key(&camera_entity));
|
||||
assert!(ui_surface.camera_entity_to_taffy.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn despawning_a_ui_entity_should_remove_its_corresponding_ui_node() {
|
||||
@ -783,6 +857,149 @@ mod tests {
|
||||
assert!(ui_surface.entity_to_taffy.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ui_node_should_properly_update_when_changing_target_camera() {
|
||||
#[derive(Component)]
|
||||
struct MovingUiNode;
|
||||
|
||||
fn update_camera_viewports(
|
||||
primary_window_query: Query<&Window, With<PrimaryWindow>>,
|
||||
mut cameras: Query<&mut Camera>,
|
||||
) {
|
||||
let primary_window = primary_window_query
|
||||
.get_single()
|
||||
.expect("missing primary window");
|
||||
let camera_count = cameras.iter().len();
|
||||
for (camera_index, mut camera) in cameras.iter_mut().enumerate() {
|
||||
let viewport_width =
|
||||
primary_window.resolution.physical_width() / camera_count as u32;
|
||||
let viewport_height = primary_window.resolution.physical_height();
|
||||
let physical_position = UVec2::new(viewport_width * camera_index as u32, 0);
|
||||
let physical_size = UVec2::new(viewport_width, viewport_height);
|
||||
camera.viewport = Some(bevy_render::camera::Viewport {
|
||||
physical_position,
|
||||
physical_size,
|
||||
..default()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn move_ui_node(
|
||||
In(pos): In<Vec2>,
|
||||
mut commands: Commands,
|
||||
cameras: Query<(Entity, &Camera)>,
|
||||
moving_ui_query: Query<Entity, With<MovingUiNode>>,
|
||||
) {
|
||||
let (target_camera_entity, _) = cameras
|
||||
.iter()
|
||||
.find(|(_, camera)| {
|
||||
let Some(logical_viewport_rect) = camera.logical_viewport_rect() else {
|
||||
panic!("missing logical viewport")
|
||||
};
|
||||
// make sure cursor is in viewport and that viewport has at least 1px of size
|
||||
logical_viewport_rect.contains(pos)
|
||||
&& logical_viewport_rect.max.cmpge(Vec2::splat(0.)).any()
|
||||
})
|
||||
.expect("cursor position outside of camera viewport");
|
||||
for moving_ui_entity in moving_ui_query.iter() {
|
||||
commands
|
||||
.entity(moving_ui_entity)
|
||||
.insert(TargetCamera(target_camera_entity))
|
||||
.insert(Style {
|
||||
position_type: PositionType::Absolute,
|
||||
top: Val::Px(pos.y),
|
||||
left: Val::Px(pos.x),
|
||||
..default()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn do_move_and_test(
|
||||
world: &mut World,
|
||||
ui_schedule: &mut Schedule,
|
||||
new_pos: Vec2,
|
||||
expected_camera_entity: &Entity,
|
||||
) {
|
||||
world.run_system_once_with(new_pos, move_ui_node);
|
||||
ui_schedule.run(world);
|
||||
let (ui_node_entity, TargetCamera(target_camera_entity)) = world
|
||||
.query_filtered::<(Entity, &TargetCamera), With<MovingUiNode>>()
|
||||
.get_single(world)
|
||||
.expect("missing MovingUiNode");
|
||||
assert_eq!(expected_camera_entity, target_camera_entity);
|
||||
let ui_surface = world.resource::<UiSurface>();
|
||||
|
||||
let layout = ui_surface
|
||||
.get_layout(ui_node_entity)
|
||||
.expect("failed to get layout");
|
||||
|
||||
// negative test for #12255
|
||||
assert_eq!(Vec2::new(layout.location.x, layout.location.y), new_pos);
|
||||
}
|
||||
|
||||
fn get_taffy_node_count(world: &World) -> usize {
|
||||
world.resource::<UiSurface>().taffy.total_node_count()
|
||||
}
|
||||
|
||||
let (mut world, mut ui_schedule) = setup_ui_test_world();
|
||||
|
||||
world.spawn(Camera2dBundle {
|
||||
camera: Camera {
|
||||
order: 1,
|
||||
..default()
|
||||
},
|
||||
..default()
|
||||
});
|
||||
|
||||
world.spawn((
|
||||
NodeBundle {
|
||||
style: Style {
|
||||
position_type: PositionType::Absolute,
|
||||
top: Val::Px(0.),
|
||||
left: Val::Px(0.),
|
||||
..default()
|
||||
},
|
||||
..default()
|
||||
},
|
||||
MovingUiNode,
|
||||
));
|
||||
|
||||
ui_schedule.run(&mut world);
|
||||
|
||||
let pos_inc = Vec2::splat(1.);
|
||||
let total_cameras = world.query::<&Camera>().iter(&world).len();
|
||||
// add total cameras - 1 (the assumed default) to get an idea for how many nodes we should expect
|
||||
let expected_max_taffy_node_count = get_taffy_node_count(&world) + total_cameras - 1;
|
||||
|
||||
world.run_system_once(update_camera_viewports);
|
||||
|
||||
ui_schedule.run(&mut world);
|
||||
|
||||
let viewport_rects = world
|
||||
.query::<(Entity, &Camera)>()
|
||||
.iter(&world)
|
||||
.map(|(e, c)| (e, c.logical_viewport_rect().expect("missing viewport")))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
for (camera_entity, viewport) in viewport_rects.iter() {
|
||||
let target_pos = viewport.min + pos_inc;
|
||||
do_move_and_test(&mut world, &mut ui_schedule, target_pos, camera_entity);
|
||||
}
|
||||
|
||||
// reverse direction
|
||||
let mut viewport_rects = viewport_rects.clone();
|
||||
viewport_rects.reverse();
|
||||
for (camera_entity, viewport) in viewport_rects.iter() {
|
||||
let target_pos = viewport.max - pos_inc;
|
||||
do_move_and_test(&mut world, &mut ui_schedule, target_pos, camera_entity);
|
||||
}
|
||||
|
||||
let current_taffy_node_count = get_taffy_node_count(&world);
|
||||
if current_taffy_node_count > expected_max_taffy_node_count {
|
||||
panic!("extra taffy nodes detected: current: {current_taffy_node_count} max expected: {expected_max_taffy_node_count}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ui_node_should_be_set_to_its_content_size() {
|
||||
let (mut world, mut ui_schedule) = setup_ui_test_world();
|
||||
|
@ -596,10 +596,13 @@ pub fn extract_text_uinodes(
|
||||
// * Multiply by the rounded physical position by the inverse scale factor to return to logical coordinates
|
||||
|
||||
let logical_top_left = -0.5 * uinode.size();
|
||||
let physical_nearest_pixel = (logical_top_left * scale_factor).round();
|
||||
let logical_top_left_nearest_pixel = physical_nearest_pixel * inverse_scale_factor;
|
||||
let transform = Mat4::from(global_transform.affine())
|
||||
* Mat4::from_translation(logical_top_left_nearest_pixel.extend(0.));
|
||||
|
||||
let mut transform = global_transform.affine()
|
||||
* bevy_math::Affine3A::from_translation(logical_top_left.extend(0.));
|
||||
|
||||
transform.translation *= scale_factor;
|
||||
transform.translation = transform.translation.round();
|
||||
transform.translation *= inverse_scale_factor;
|
||||
|
||||
let mut color = Color::WHITE;
|
||||
let mut current_section = usize::MAX;
|
||||
|
@ -10,7 +10,7 @@ use bevy_sprite::{ImageScaleMode, TextureSlice};
|
||||
use bevy_transform::prelude::*;
|
||||
use bevy_utils::HashSet;
|
||||
|
||||
use crate::{widget::UiImageSize, BackgroundColor, CalculatedClip, ExtractedUiNode, Node, UiImage};
|
||||
use crate::{BackgroundColor, CalculatedClip, ExtractedUiNode, Node, UiImage};
|
||||
|
||||
/// Component storing texture slices for image nodes entities with a tiled or sliced [`ImageScaleMode`]
|
||||
///
|
||||
@ -119,13 +119,7 @@ pub(crate) fn compute_slices_on_asset_event(
|
||||
mut commands: Commands,
|
||||
mut events: EventReader<AssetEvent<Image>>,
|
||||
images: Res<Assets<Image>>,
|
||||
ui_nodes: Query<(
|
||||
Entity,
|
||||
&ImageScaleMode,
|
||||
&Node,
|
||||
Option<&UiImageSize>,
|
||||
&UiImage,
|
||||
)>,
|
||||
ui_nodes: Query<(Entity, &ImageScaleMode, &Node, &UiImage)>,
|
||||
) {
|
||||
// We store the asset ids of added/modified image assets
|
||||
let added_handles: HashSet<_> = events
|
||||
@ -139,12 +133,11 @@ pub(crate) fn compute_slices_on_asset_event(
|
||||
return;
|
||||
}
|
||||
// We recompute the sprite slices for sprite entities with a matching asset handle id
|
||||
for (entity, scale_mode, ui_node, size, image) in &ui_nodes {
|
||||
for (entity, scale_mode, ui_node, image) in &ui_nodes {
|
||||
if !added_handles.contains(&image.texture.id()) {
|
||||
continue;
|
||||
}
|
||||
let size = size.map(|s| s.size()).unwrap_or(ui_node.size());
|
||||
if let Some(slices) = compute_texture_slices(size, scale_mode, image, &images) {
|
||||
if let Some(slices) = compute_texture_slices(ui_node.size(), scale_mode, image, &images) {
|
||||
commands.entity(entity).insert(slices);
|
||||
}
|
||||
}
|
||||
@ -156,24 +149,12 @@ pub(crate) fn compute_slices_on_image_change(
|
||||
mut commands: Commands,
|
||||
images: Res<Assets<Image>>,
|
||||
changed_nodes: Query<
|
||||
(
|
||||
Entity,
|
||||
&ImageScaleMode,
|
||||
&Node,
|
||||
Option<&UiImageSize>,
|
||||
&UiImage,
|
||||
),
|
||||
Or<(
|
||||
Changed<ImageScaleMode>,
|
||||
Changed<UiImage>,
|
||||
Changed<UiImageSize>,
|
||||
Changed<Node>,
|
||||
)>,
|
||||
(Entity, &ImageScaleMode, &Node, &UiImage),
|
||||
Or<(Changed<ImageScaleMode>, Changed<UiImage>, Changed<Node>)>,
|
||||
>,
|
||||
) {
|
||||
for (entity, scale_mode, ui_node, size, image) in &changed_nodes {
|
||||
let size = size.map(|s| s.size()).unwrap_or(ui_node.size());
|
||||
if let Some(slices) = compute_texture_slices(size, scale_mode, image, &images) {
|
||||
for (entity, scale_mode, ui_node, image) in &changed_nodes {
|
||||
if let Some(slices) = compute_texture_slices(ui_node.size(), scale_mode, image, &images) {
|
||||
commands.entity(entity).insert(slices);
|
||||
}
|
||||
}
|
||||
|
@ -155,7 +155,9 @@ fn update_children_target_camera(
|
||||
|
||||
for &child in children {
|
||||
// Skip if the child has already been updated or update is not needed
|
||||
if updated_entities.contains(&child) || camera_to_set == node_query.get(child).unwrap() {
|
||||
if updated_entities.contains(&child)
|
||||
|| camera_to_set == node_query.get(child).ok().flatten()
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_utils"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "A collection of utils for Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -17,7 +17,7 @@ tracing = { version = "0.1", default-features = false, features = ["std"] }
|
||||
web-time = { version = "0.2" }
|
||||
uuid = { version = "1.1", features = ["v4", "serde"] }
|
||||
hashbrown = { version = "0.14", features = ["serde"] }
|
||||
bevy_utils_proc_macros = { version = "0.13.0", path = "macros" }
|
||||
bevy_utils_proc_macros = { version = "0.13.1", path = "macros" }
|
||||
petgraph = "0.6"
|
||||
thiserror = "1.0"
|
||||
nonmax = "0.5"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_utils_proc_macros"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
description = "Bevy Utils Proc Macros"
|
||||
edition = "2021"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_window"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "Provides windowing functionality for Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -14,16 +14,16 @@ serialize = ["serde", "smol_str/serde"]
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
bevy_a11y = { path = "../bevy_a11y", version = "0.13.0" }
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.0" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.0" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.0" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.0", features = [
|
||||
bevy_a11y = { path = "../bevy_a11y", version = "0.13.1" }
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.1" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.1" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.1" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.13.1", features = [
|
||||
"glam",
|
||||
] }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.0" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.1" }
|
||||
# Used for close_on_esc
|
||||
bevy_input = { path = "../bevy_input", version = "0.13.0" }
|
||||
bevy_input = { path = "../bevy_input", version = "0.13.1" }
|
||||
|
||||
# other
|
||||
serde = { version = "1.0", features = ["derive"], optional = true }
|
||||
|
@ -648,7 +648,7 @@ impl WindowResolution {
|
||||
|
||||
/// Builder method for adding a scale factor override to the resolution.
|
||||
pub fn with_scale_factor_override(mut self, scale_factor_override: f32) -> Self {
|
||||
self.scale_factor_override = Some(scale_factor_override);
|
||||
self.set_scale_factor_override(Some(scale_factor_override));
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_winit"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
edition = "2021"
|
||||
description = "A winit window and input backend for Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
@ -16,16 +16,16 @@ accesskit_unix = ["accesskit_winit/accesskit_unix", "accesskit_winit/async-io"]
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
bevy_a11y = { path = "../bevy_a11y", version = "0.13.0" }
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.0" }
|
||||
bevy_derive = { path = "../bevy_derive", version = "0.13.0" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.0" }
|
||||
bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.13.0" }
|
||||
bevy_input = { path = "../bevy_input", version = "0.13.0" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.0" }
|
||||
bevy_window = { path = "../bevy_window", version = "0.13.0" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.0" }
|
||||
bevy_tasks = { path = "../bevy_tasks", version = "0.13.0" }
|
||||
bevy_a11y = { path = "../bevy_a11y", version = "0.13.1" }
|
||||
bevy_app = { path = "../bevy_app", version = "0.13.1" }
|
||||
bevy_derive = { path = "../bevy_derive", version = "0.13.1" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.13.1" }
|
||||
bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.13.1" }
|
||||
bevy_input = { path = "../bevy_input", version = "0.13.1" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.13.1" }
|
||||
bevy_window = { path = "../bevy_window", version = "0.13.1" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.13.1" }
|
||||
bevy_tasks = { path = "../bevy_tasks", version = "0.13.1" }
|
||||
|
||||
# other
|
||||
# feature rwh_06 refers to window_raw_handle@v0.6
|
||||
|
@ -13,8 +13,9 @@ mod winit_windows;
|
||||
|
||||
use approx::relative_eq;
|
||||
use bevy_a11y::AccessibilityRequested;
|
||||
use bevy_utils::{Duration, Instant};
|
||||
use system::{changed_windows, create_windows, despawn_windows, CachedWindow};
|
||||
use bevy_utils::Instant;
|
||||
pub use system::create_windows;
|
||||
use system::{changed_windows, despawn_windows, CachedWindow};
|
||||
use winit::dpi::{LogicalSize, PhysicalSize};
|
||||
pub use winit_config::*;
|
||||
pub use winit_windows::*;
|
||||
@ -44,6 +45,7 @@ use bevy_window::{PrimaryWindow, RawHandleWrapper};
|
||||
#[cfg(target_os = "android")]
|
||||
pub use winit::platform::android::activity as android_activity;
|
||||
|
||||
use winit::event::StartCause;
|
||||
use winit::{
|
||||
event::{self, DeviceEvent, Event, WindowEvent},
|
||||
event_loop::{ControlFlow, EventLoop, EventLoopBuilder, EventLoopWindowTarget},
|
||||
@ -81,7 +83,7 @@ pub struct WinitPlugin {
|
||||
|
||||
impl Plugin for WinitPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
let mut event_loop_builder = EventLoopBuilder::<()>::with_user_event();
|
||||
let mut event_loop_builder = EventLoopBuilder::<UserEvent>::with_user_event();
|
||||
|
||||
// linux check is needed because x11 might be enabled on other platforms.
|
||||
#[cfg(all(target_os = "linux", feature = "x11"))]
|
||||
@ -181,8 +183,6 @@ struct WinitAppRunnerState {
|
||||
wait_elapsed: bool,
|
||||
/// The time the last update started.
|
||||
last_update: Instant,
|
||||
/// The time the next update is scheduled to start.
|
||||
scheduled_update: Option<Instant>,
|
||||
/// Number of "forced" updates to trigger on application start
|
||||
startup_forced_updates: u32,
|
||||
}
|
||||
@ -223,14 +223,14 @@ impl Default for WinitAppRunnerState {
|
||||
redraw_requested: false,
|
||||
wait_elapsed: false,
|
||||
last_update: Instant::now(),
|
||||
scheduled_update: None,
|
||||
// 3 seems to be enough, 5 is a safe margin
|
||||
startup_forced_updates: 5,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type CreateWindowParams<'w, 's, F = ()> = (
|
||||
/// The parameters of the [`create_windows`] system.
|
||||
pub type CreateWindowParams<'w, 's, F = ()> = (
|
||||
Commands<'w, 's>,
|
||||
Query<'w, 's, (Entity, &'static mut Window), F>,
|
||||
EventWriter<'w, WindowCreated>,
|
||||
@ -240,6 +240,15 @@ type CreateWindowParams<'w, 's, F = ()> = (
|
||||
Res<'w, AccessibilityRequested>,
|
||||
);
|
||||
|
||||
/// The [`winit::event_loop::EventLoopProxy`] with the specific [`winit::event::Event::UserEvent`] used in the [`winit_runner`].
|
||||
///
|
||||
/// The `EventLoopProxy` can be used to request a redraw from outside bevy.
|
||||
///
|
||||
/// Use `NonSend<EventLoopProxy>` to receive this resource.
|
||||
pub type EventLoopProxy = winit::event_loop::EventLoopProxy<UserEvent>;
|
||||
|
||||
type UserEvent = RequestRedraw;
|
||||
|
||||
/// The default [`App::runner`] for the [`WinitPlugin`] plugin.
|
||||
///
|
||||
/// Overriding the app's [runner](bevy_app::App::runner) while using `WinitPlugin` will bypass the
|
||||
@ -252,7 +261,7 @@ pub fn winit_runner(mut app: App) {
|
||||
|
||||
let event_loop = app
|
||||
.world
|
||||
.remove_non_send_resource::<EventLoop<()>>()
|
||||
.remove_non_send_resource::<EventLoop<UserEvent>>()
|
||||
.unwrap();
|
||||
|
||||
app.world
|
||||
@ -277,7 +286,7 @@ pub fn winit_runner(mut app: App) {
|
||||
let mut create_window =
|
||||
SystemState::<CreateWindowParams<Added<Window>>>::from_world(&mut app.world);
|
||||
// set up the event loop
|
||||
let event_handler = move |event, event_loop: &EventLoopWindowTarget<()>| {
|
||||
let event_handler = move |event, event_loop: &EventLoopWindowTarget<UserEvent>| {
|
||||
handle_winit_event(
|
||||
&mut app,
|
||||
&mut app_exit_event_reader,
|
||||
@ -312,8 +321,8 @@ fn handle_winit_event(
|
||||
)>,
|
||||
focused_windows_state: &mut SystemState<(Res<WinitSettings>, Query<&Window>)>,
|
||||
redraw_event_reader: &mut ManualEventReader<RequestRedraw>,
|
||||
event: Event<()>,
|
||||
event_loop: &EventLoopWindowTarget<()>,
|
||||
event: Event<UserEvent>,
|
||||
event_loop: &EventLoopWindowTarget<UserEvent>,
|
||||
) {
|
||||
#[cfg(feature = "trace")]
|
||||
let _span = bevy_utils::tracing::info_span!("winit event_handler").entered();
|
||||
@ -395,12 +404,14 @@ fn handle_winit_event(
|
||||
}
|
||||
}
|
||||
}
|
||||
Event::NewEvents(_) => {
|
||||
if let Some(t) = runner_state.scheduled_update {
|
||||
let now = Instant::now();
|
||||
let remaining = t.checked_duration_since(now).unwrap_or(Duration::ZERO);
|
||||
runner_state.wait_elapsed = remaining.is_zero();
|
||||
}
|
||||
Event::NewEvents(cause) => {
|
||||
runner_state.wait_elapsed = match cause {
|
||||
StartCause::WaitCancelled {
|
||||
requested_resume: Some(resume),
|
||||
..
|
||||
} => resume >= Instant::now(),
|
||||
_ => true,
|
||||
};
|
||||
}
|
||||
Event::WindowEvent {
|
||||
event, window_id, ..
|
||||
@ -690,6 +701,9 @@ fn handle_winit_event(
|
||||
event_loop.set_control_flow(ControlFlow::Wait);
|
||||
}
|
||||
}
|
||||
Event::UserEvent(RequestRedraw) => {
|
||||
runner_state.redraw_requested = true;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
@ -698,7 +712,7 @@ fn run_app_update_if_should(
|
||||
runner_state: &mut WinitAppRunnerState,
|
||||
app: &mut App,
|
||||
focused_windows_state: &mut SystemState<(Res<WinitSettings>, Query<&Window>)>,
|
||||
event_loop: &EventLoopWindowTarget<()>,
|
||||
event_loop: &EventLoopWindowTarget<UserEvent>,
|
||||
create_window: &mut SystemState<CreateWindowParams<Added<Window>>>,
|
||||
app_exit_event_reader: &mut ManualEventReader<AppExit>,
|
||||
redraw_event_reader: &mut ManualEventReader<RequestRedraw>,
|
||||
@ -732,6 +746,7 @@ fn run_app_update_if_should(
|
||||
match config.update_mode(focused) {
|
||||
UpdateMode::Continuous => {
|
||||
runner_state.redraw_requested = true;
|
||||
event_loop.set_control_flow(ControlFlow::Wait);
|
||||
}
|
||||
UpdateMode::Reactive { wait } | UpdateMode::ReactiveLowPower { wait } => {
|
||||
// TODO(bug): this is unexpected behavior.
|
||||
@ -740,10 +755,8 @@ fn run_app_update_if_should(
|
||||
// Need to verify the plateform specifics (whether this can occur in
|
||||
// rare-but-possible cases) and replace this with a panic or a log warn!
|
||||
if let Some(next) = runner_state.last_update.checked_add(*wait) {
|
||||
runner_state.scheduled_update = Some(next);
|
||||
event_loop.set_control_flow(ControlFlow::WaitUntil(next));
|
||||
} else {
|
||||
runner_state.scheduled_update = None;
|
||||
event_loop.set_control_flow(ControlFlow::Wait);
|
||||
}
|
||||
}
|
||||
|
@ -31,8 +31,8 @@ use crate::{
|
||||
/// If any of these entities are missing required components, those will be added with their
|
||||
/// default values.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn create_windows<F: QueryFilter + 'static>(
|
||||
event_loop: &EventLoopWindowTarget<()>,
|
||||
pub fn create_windows<F: QueryFilter + 'static>(
|
||||
event_loop: &EventLoopWindowTarget<crate::UserEvent>,
|
||||
(
|
||||
mut commands,
|
||||
mut created_windows,
|
||||
|
@ -28,6 +28,8 @@ impl WinitSettings {
|
||||
///
|
||||
/// [`Reactive`](UpdateMode::Reactive) if windows have focus,
|
||||
/// [`ReactiveLowPower`](UpdateMode::ReactiveLowPower) otherwise.
|
||||
///
|
||||
/// Use the [`EventLoopProxy`](crate::EventLoopProxy) to request a redraw from outside bevy.
|
||||
pub fn desktop_app() -> Self {
|
||||
WinitSettings {
|
||||
focused_mode: UpdateMode::Reactive {
|
||||
@ -72,6 +74,7 @@ pub enum UpdateMode {
|
||||
/// - a redraw has been requested by [`RequestRedraw`](bevy_window::RequestRedraw)
|
||||
/// - new [window](`winit::event::WindowEvent`) or [raw input](`winit::event::DeviceEvent`)
|
||||
/// events have appeared
|
||||
/// - a redraw has been requested with the [`EventLoopProxy`](crate::EventLoopProxy)
|
||||
Reactive {
|
||||
/// The approximate time from the start of one update to the next.
|
||||
///
|
||||
@ -84,6 +87,7 @@ pub enum UpdateMode {
|
||||
/// - `wait` time has elapsed since the previous update
|
||||
/// - a redraw has been requested by [`RequestRedraw`](bevy_window::RequestRedraw)
|
||||
/// - new [window events](`winit::event::WindowEvent`) have appeared
|
||||
/// - a redraw has been requested with the [`EventLoopProxy`](crate::EventLoopProxy)
|
||||
///
|
||||
/// **Note:** Unlike [`Reactive`](`UpdateMode::Reactive`), this mode will ignore events that
|
||||
/// don't come from interacting with a window, like [`MouseMotion`](winit::event::DeviceEvent::MouseMotion).
|
||||
|
@ -39,7 +39,7 @@ impl WinitWindows {
|
||||
/// Creates a `winit` window and associates it with our entity.
|
||||
pub fn create_window(
|
||||
&mut self,
|
||||
event_loop: &winit::event_loop::EventLoopWindowTarget<()>,
|
||||
event_loop: &winit::event_loop::EventLoopWindowTarget<crate::UserEvent>,
|
||||
entity: Entity,
|
||||
window: &Window,
|
||||
adapters: &mut AccessKitAdapters,
|
||||
|
@ -239,13 +239,6 @@ ruby -run -ehttpd examples/wasm
|
||||
Bevy support for WebGPU is being worked on, but is currently experimental.
|
||||
|
||||
To build for WebGPU, you'll need to enable the `webgpu` feature. This will override the `webgl2` feature, and builds with the `webgpu` feature enabled won't be able to run on browsers that don't support WebGPU.
|
||||
WebGPU depends on unstable APIs so you will also need to pass the `web_sys_unstable_apis` flag to your builds. For example:
|
||||
|
||||
```sh
|
||||
RUSTFLAGS=--cfg=web_sys_unstable_apis cargo build ...
|
||||
```
|
||||
|
||||
Check `wasm-bindgen` [docs on Unstable APIs](https://rustwasm.github.io/wasm-bindgen/web-sys/unstable-apis.html) for more details.
|
||||
|
||||
Bevy has an helper to build its examples:
|
||||
|
||||
|
@ -81,7 +81,7 @@ The default feature set enables most of the expected features of a game engine,
|
||||
|trace_tracy_memory|Tracing support, with memory profiling, exposing a port for Tracy|
|
||||
|wav|WAV audio format support|
|
||||
|wayland|Wayland display server support|
|
||||
|webgpu|Enable support for WebGPU in Wasm. When enabled, this feature will override the `webgl2` feature and you won't be able to run Wasm builds with WebGL2, only with WebGPU. Requires the `RUSTFLAGS` environment variable to be set to `--cfg=web_sys_unstable_apis` when building.|
|
||||
|webgpu|Enable support for WebGPU in Wasm. When enabled, this feature will override the `webgl2` feature and you won't be able to run Wasm builds with WebGL2, only with WebGPU.|
|
||||
|webp|WebP image format support|
|
||||
|wgpu_trace|Save a trace of all wgpu calls|
|
||||
|zlib|For KTX2 supercompression|
|
||||
|
@ -35,19 +35,20 @@ fn setup_scene(
|
||||
transform: Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
|
||||
..default()
|
||||
},
|
||||
BloomSettings::default(), // 3. Enable bloom for the camera
|
||||
// 3. Enable bloom for the camera
|
||||
BloomSettings::NATURAL,
|
||||
));
|
||||
|
||||
let material_emissive1 = materials.add(StandardMaterial {
|
||||
emissive: Color::rgb_linear(2300.0, 900.0, 300.0), // 4. Put something bright in a dark environment to see the effect
|
||||
emissive: Color::rgb_linear(23000.0, 9000.0, 3000.0), // 4. Put something bright in a dark environment to see the effect
|
||||
..default()
|
||||
});
|
||||
let material_emissive2 = materials.add(StandardMaterial {
|
||||
emissive: Color::rgb_linear(300.0, 2300.0, 900.0),
|
||||
emissive: Color::rgb_linear(3000.0, 23000.0, 9000.0),
|
||||
..default()
|
||||
});
|
||||
let material_emissive3 = materials.add(StandardMaterial {
|
||||
emissive: Color::rgb_linear(900.0, 300.0, 2300.0),
|
||||
emissive: Color::rgb_linear(9000.0, 3000.0, 23000.0),
|
||||
..default()
|
||||
});
|
||||
let material_non_emissive = materials.add(StandardMaterial {
|
||||
@ -59,6 +60,8 @@ fn setup_scene(
|
||||
|
||||
for x in -5..5 {
|
||||
for z in -5..5 {
|
||||
// This generates a pseudo-random integer between `[0, 6)`, but deterministically so
|
||||
// the same spheres are always the same colors.
|
||||
let mut hasher = DefaultHasher::new();
|
||||
(x, z).hash(&mut hasher);
|
||||
let rand = (hasher.finish() - 2) % 6;
|
||||
@ -89,7 +92,7 @@ fn setup_scene(
|
||||
"",
|
||||
TextStyle {
|
||||
font_size: 20.0,
|
||||
color: Color::BLACK,
|
||||
color: Color::WHITE,
|
||||
..default()
|
||||
},
|
||||
)
|
||||
@ -218,7 +221,7 @@ fn update_bloom_settings(
|
||||
*text = "Bloom: Off (Toggle: Space)".to_string();
|
||||
|
||||
if keycode.just_pressed(KeyCode::Space) {
|
||||
commands.entity(entity).insert(BloomSettings::default());
|
||||
commands.entity(entity).insert(BloomSettings::NATURAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ fn main() {
|
||||
.add_plugins(DefaultPlugins)
|
||||
.insert_resource(Parameters(PhysicalCameraParameters {
|
||||
aperture_f_stops: 1.0,
|
||||
shutter_speed_s: 1.0 / 100.0,
|
||||
shutter_speed_s: 1.0 / 125.0,
|
||||
sensitivity_iso: 100.0,
|
||||
}))
|
||||
.add_systems(Startup, setup)
|
||||
@ -132,7 +132,7 @@ fn setup(
|
||||
// transform: Transform::from_xyz(5.0, 8.0, 2.0),
|
||||
transform: Transform::from_xyz(1.0, 2.0, 0.0),
|
||||
point_light: PointLight {
|
||||
intensity: 4000.0, // lumens - roughly a 300W non-halogen incandescent bulb
|
||||
intensity: 100_000.0,
|
||||
color: Color::RED,
|
||||
shadows_enabled: true,
|
||||
..default()
|
||||
@ -157,7 +157,7 @@ fn setup(
|
||||
transform: Transform::from_xyz(-1.0, 2.0, 0.0)
|
||||
.looking_at(Vec3::new(-1.0, 0.0, 0.0), Vec3::Z),
|
||||
spot_light: SpotLight {
|
||||
intensity: 4000.0, // lumens - roughly a 300W non-halogen incandescent bulb
|
||||
intensity: 100_000.0,
|
||||
color: Color::GREEN,
|
||||
shadows_enabled: true,
|
||||
inner_angle: 0.6,
|
||||
@ -185,7 +185,7 @@ fn setup(
|
||||
// transform: Transform::from_xyz(5.0, 8.0, 2.0),
|
||||
transform: Transform::from_xyz(0.0, 4.0, 0.0),
|
||||
point_light: PointLight {
|
||||
intensity: 4000.0, // lumens - roughly a 300W non-halogen incandescent bulb
|
||||
intensity: 100_000.0,
|
||||
color: Color::BLUE,
|
||||
shadows_enabled: true,
|
||||
..default()
|
||||
|
@ -80,7 +80,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
CameraController::default(),
|
||||
Skybox {
|
||||
image: skybox_handle.clone(),
|
||||
brightness: 150.0,
|
||||
brightness: 1000.0,
|
||||
},
|
||||
));
|
||||
|
||||
|
@ -5,6 +5,13 @@ use std::f32::consts::*;
|
||||
use bevy::{pbr::NotShadowCaster, prelude::*};
|
||||
use rand::{rngs::StdRng, Rng, SeedableRng};
|
||||
|
||||
const INSTRUCTIONS: &str = "\
|
||||
Controls
|
||||
--------
|
||||
Horizontal Movement: WASD
|
||||
Vertical Movement: Space and Shift
|
||||
Rotate Camera: Left and Right Arrows";
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
.insert_resource(AmbientLight {
|
||||
@ -13,7 +20,7 @@ fn main() {
|
||||
})
|
||||
.add_plugins(DefaultPlugins)
|
||||
.add_systems(Startup, setup)
|
||||
.add_systems(Update, (light_sway, movement))
|
||||
.add_systems(Update, (light_sway, movement, rotation))
|
||||
.run();
|
||||
}
|
||||
|
||||
@ -27,30 +34,38 @@ fn setup(
|
||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||
) {
|
||||
// ground plane
|
||||
commands.spawn(PbrBundle {
|
||||
mesh: meshes.add(Plane3d::default().mesh().size(100.0, 100.0)),
|
||||
material: materials.add(Color::WHITE),
|
||||
..default()
|
||||
});
|
||||
commands.spawn((
|
||||
PbrBundle {
|
||||
mesh: meshes.add(Plane3d::default().mesh().size(100.0, 100.0)),
|
||||
material: materials.add(Color::WHITE),
|
||||
..default()
|
||||
},
|
||||
Movable,
|
||||
));
|
||||
|
||||
// cubes
|
||||
let mut rng = StdRng::seed_from_u64(19878367467713);
|
||||
let cube_mesh = meshes.add(Cuboid::new(0.5, 0.5, 0.5));
|
||||
let blue = materials.add(Color::rgb_u8(124, 144, 255));
|
||||
for _ in 0..40 {
|
||||
let x = rng.gen_range(-5.0..5.0);
|
||||
let y = rng.gen_range(0.0..3.0);
|
||||
let z = rng.gen_range(-5.0..5.0);
|
||||
commands.spawn((
|
||||
PbrBundle {
|
||||
mesh: cube_mesh.clone(),
|
||||
material: blue.clone(),
|
||||
transform: Transform::from_xyz(x, y, z),
|
||||
..default()
|
||||
},
|
||||
Movable,
|
||||
));
|
||||
}
|
||||
|
||||
commands.spawn_batch(
|
||||
std::iter::repeat_with(move || {
|
||||
let x = rng.gen_range(-5.0..5.0);
|
||||
let y = rng.gen_range(0.0..3.0);
|
||||
let z = rng.gen_range(-5.0..5.0);
|
||||
|
||||
(
|
||||
PbrBundle {
|
||||
mesh: cube_mesh.clone(),
|
||||
material: blue.clone(),
|
||||
transform: Transform::from_xyz(x, y, z),
|
||||
..default()
|
||||
},
|
||||
Movable,
|
||||
)
|
||||
})
|
||||
.take(40),
|
||||
);
|
||||
|
||||
let sphere_mesh = meshes.add(Sphere::new(0.05).mesh().uv(32, 18));
|
||||
let sphere_mesh_direction = meshes.add(Sphere::new(0.1).mesh().uv(32, 18));
|
||||
@ -64,6 +79,7 @@ fn setup(
|
||||
emissive: Color::rgba_linear(50.0, 0.0, 0.0, 0.0),
|
||||
..default()
|
||||
});
|
||||
|
||||
for x in 0..4 {
|
||||
for z in 0..4 {
|
||||
let x = x as f32 - 2.0;
|
||||
@ -74,7 +90,7 @@ fn setup(
|
||||
transform: Transform::from_xyz(1.0 + x, 2.0, z)
|
||||
.looking_at(Vec3::new(1.0 + x, 0.0, z), Vec3::X),
|
||||
spot_light: SpotLight {
|
||||
intensity: 4000.0, // lumens
|
||||
intensity: 40_000.0, // lumens
|
||||
color: Color::WHITE,
|
||||
shadows_enabled: true,
|
||||
inner_angle: PI / 4.0 * 0.85,
|
||||
@ -111,6 +127,22 @@ fn setup(
|
||||
transform: Transform::from_xyz(-4.0, 5.0, 10.0).looking_at(Vec3::ZERO, Vec3::Y),
|
||||
..default()
|
||||
});
|
||||
|
||||
commands.spawn(
|
||||
TextBundle::from_section(
|
||||
INSTRUCTIONS,
|
||||
TextStyle {
|
||||
font_size: 20.0,
|
||||
..default()
|
||||
},
|
||||
)
|
||||
.with_style(Style {
|
||||
position_type: PositionType::Absolute,
|
||||
top: Val::Px(12.0),
|
||||
left: Val::Px(12.0),
|
||||
..default()
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
fn light_sway(time: Res<Time>, mut query: Query<(&mut Transform, &mut SpotLight)>) {
|
||||
@ -132,27 +164,49 @@ fn movement(
|
||||
time: Res<Time>,
|
||||
mut query: Query<&mut Transform, With<Movable>>,
|
||||
) {
|
||||
for mut transform in &mut query {
|
||||
let mut direction = Vec3::ZERO;
|
||||
if input.pressed(KeyCode::ArrowUp) {
|
||||
direction.z -= 1.0;
|
||||
}
|
||||
if input.pressed(KeyCode::ArrowDown) {
|
||||
direction.z += 1.0;
|
||||
}
|
||||
if input.pressed(KeyCode::ArrowLeft) {
|
||||
direction.x -= 1.0;
|
||||
}
|
||||
if input.pressed(KeyCode::ArrowRight) {
|
||||
direction.x += 1.0;
|
||||
}
|
||||
if input.pressed(KeyCode::PageUp) {
|
||||
direction.y += 1.0;
|
||||
}
|
||||
if input.pressed(KeyCode::PageDown) {
|
||||
direction.y -= 1.0;
|
||||
}
|
||||
// Calculate translation to move the cubes and ground plane
|
||||
let mut translation = Vec3::ZERO;
|
||||
|
||||
transform.translation += time.delta_seconds() * 2.0 * direction;
|
||||
// Horizontal forward and backward movement
|
||||
if input.pressed(KeyCode::KeyW) {
|
||||
translation.z += 1.0;
|
||||
} else if input.pressed(KeyCode::KeyS) {
|
||||
translation.z -= 1.0;
|
||||
}
|
||||
|
||||
// Horizontal left and right movement
|
||||
if input.pressed(KeyCode::KeyA) {
|
||||
translation.x += 1.0;
|
||||
} else if input.pressed(KeyCode::KeyD) {
|
||||
translation.x -= 1.0;
|
||||
}
|
||||
|
||||
// Vertical movement
|
||||
if input.pressed(KeyCode::ShiftLeft) {
|
||||
translation.y += 1.0;
|
||||
} else if input.pressed(KeyCode::Space) {
|
||||
translation.y -= 1.0;
|
||||
}
|
||||
|
||||
translation *= 2.0 * time.delta_seconds();
|
||||
|
||||
// Apply translation
|
||||
for mut transform in &mut query {
|
||||
transform.translation += translation;
|
||||
}
|
||||
}
|
||||
|
||||
fn rotation(
|
||||
mut query: Query<&mut Transform, With<Camera>>,
|
||||
input: Res<ButtonInput<KeyCode>>,
|
||||
time: Res<Time>,
|
||||
) {
|
||||
let mut transform = query.single_mut();
|
||||
let delta = time.delta_seconds();
|
||||
|
||||
if input.pressed(KeyCode::ArrowLeft) {
|
||||
transform.rotate_around(Vec3::ZERO, Quat::from_rotation_y(delta));
|
||||
} else if input.pressed(KeyCode::ArrowRight) {
|
||||
transform.rotate_around(Vec3::ZERO, Quat::from_rotation_y(-delta));
|
||||
}
|
||||
}
|
||||
|
@ -576,13 +576,6 @@ ruby -run -ehttpd examples/wasm
|
||||
Bevy support for WebGPU is being worked on, but is currently experimental.
|
||||
|
||||
To build for WebGPU, you'll need to enable the `webgpu` feature. This will override the `webgl2` feature, and builds with the `webgpu` feature enabled won't be able to run on browsers that don't support WebGPU.
|
||||
WebGPU depends on unstable APIs so you will also need to pass the `web_sys_unstable_apis` flag to your builds. For example:
|
||||
|
||||
```sh
|
||||
RUSTFLAGS=--cfg=web_sys_unstable_apis cargo build ...
|
||||
```
|
||||
|
||||
Check `wasm-bindgen` [docs on Unstable APIs](https://rustwasm.github.io/wasm-bindgen/web-sys/unstable-apis.html) for more details.
|
||||
|
||||
Bevy has an helper to build its examples:
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user