From 8dd5692b3ed6fefe4850e98db3cf9a5110f4b9dd Mon Sep 17 00:00:00 2001 From: Jan Hohenheim Date: Sat, 2 Mar 2024 15:41:37 +0100 Subject: [PATCH 001/124] Add nightly hint to config.toml (#12257) # Objective - The build on Windows currently fails on stable when using the `config.toml` as described but commenting out all lines that say "Nightly" ## Solution - Add a missing nightly specifier for a flag that won't run on stable --- .cargo/config_fast_builds.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cargo/config_fast_builds.toml b/.cargo/config_fast_builds.toml index 4ee56c480c157..2d82ca39a89c0 100644 --- a/.cargo/config_fast_builds.toml +++ b/.cargo/config_fast_builds.toml @@ -30,7 +30,7 @@ rustflags = [ [target.x86_64-pc-windows-msvc] linker = "rust-lld.exe" # Use LLD Linker rustflags = [ - "-Zshare-generics=n", + "-Zshare-generics=n", # (Nightly) "-Zthreads=0", # (Nightly) Use improved multithreading with the recommended amount of threads. ] From 45f7af6282827d178d6c7269ce83368fe127beb2 Mon Sep 17 00:00:00 2001 From: Noah Date: Sat, 2 Mar 2024 09:42:29 -0500 Subject: [PATCH 002/124] Update engine_style_guide with guideline to link to the error code when using bevy engine error codes (#12253) # Objective - https://github.com/bevyengine/bevy/pull/12165 created the expectation that returned bevy errors will include a link to the relevant bevy error. That expectation is not formally established in the contributing guidelines which will lead to it not being upheld in future PRs that use the bevy error codes. This PR adds it to engine_style_guide.md to establish that convention officially --------- Co-authored-by: Afonso Lage --- .github/contributing/engine_style_guide.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/contributing/engine_style_guide.md b/.github/contributing/engine_style_guide.md index 5ccc1c59a2586..ff656373fdb4d 100644 --- a/.github/contributing/engine_style_guide.md +++ b/.github/contributing/engine_style_guide.md @@ -14,6 +14,7 @@ For more advice on contributing to the engine, see the [relevant section](../../ 4. Use \`variable_name\` code blocks in comments to signify that you're referring to specific types and variables. 5. Start comments with capital letters. End them with a period if they are sentence-like. 3. Use comments to organize long and complex stretches of code that can't sensibly be refactored into separate functions. +4. When using [Bevy error codes](https://bevyengine.org/learn/errors/) include a link to the relevant error on the Bevy website in the returned error message `... See: https://bevyengine.org/learn/errors/#b0003`. ## Rust API guidelines From eb52a489adfeb6457089beee83789a5dc6846090 Mon Sep 17 00:00:00 2001 From: James Liu Date: Sat, 2 Mar 2024 08:00:28 -0800 Subject: [PATCH 003/124] Batching: replace GpuArrayBufferIndex::index with a u32 (#12250) # Objective While mucking around with batch_and_prepare systems, it became apparent that `GpuArrayBufferIndex::index` doesn't need to be a NonMaxU32. ## Solution Replace it with a normal u32. This likely has some potential perf benefit by avoiding panics and the NOT operations, but I haven't been able to find any substantial gains, so this is primarily for code quality. --- ## Changelog Changed: `GpuArrayBufferIndex::index` is now a u32. ## Migration Guide `GpuArrayBuferIndex::index` is now a u32 instead of a `NonMaxU32`. Remove any calls to `NonMaxU32::get` on the member. --- crates/bevy_render/src/batching/mod.rs | 2 +- .../bevy_render/src/render_resource/batched_uniform_buffer.rs | 2 +- crates/bevy_render/src/render_resource/gpu_array_buffer.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/bevy_render/src/batching/mod.rs b/crates/bevy_render/src/batching/mod.rs index 859d56e98deb5..6f16617fe718a 100644 --- a/crates/bevy_render/src/batching/mod.rs +++ b/crates/bevy_render/src/batching/mod.rs @@ -88,7 +88,7 @@ pub fn batch_and_prepare_render_phase BatchedUniformBuffer { pub fn push(&mut self, component: T) -> GpuArrayBufferIndex { let result = GpuArrayBufferIndex { - index: NonMaxU32::new(self.temp.0.len() as u32).unwrap(), + index: self.temp.0.len() as u32, dynamic_offset: NonMaxU32::new(self.current_offset), element_type: PhantomData, }; diff --git a/crates/bevy_render/src/render_resource/gpu_array_buffer.rs b/crates/bevy_render/src/render_resource/gpu_array_buffer.rs index dbfe6a5962231..1d314f0a1da7c 100644 --- a/crates/bevy_render/src/render_resource/gpu_array_buffer.rs +++ b/crates/bevy_render/src/render_resource/gpu_array_buffer.rs @@ -57,7 +57,7 @@ impl GpuArrayBuffer { GpuArrayBuffer::Uniform(buffer) => buffer.push(value), GpuArrayBuffer::Storage(buffer) => { let buffer = buffer.get_mut(); - let index = NonMaxU32::new(buffer.len() as u32).unwrap(); + let index = buffer.len() as u32; buffer.push(value); GpuArrayBufferIndex { index, @@ -109,7 +109,7 @@ impl GpuArrayBuffer { #[derive(Component, Clone)] pub struct GpuArrayBufferIndex { /// The index to use in a shader into the array. - pub index: NonMaxU32, + pub index: u32, /// The dynamic offset to use when setting the bind group in a pass. /// Only used on platforms that don't support storage buffers. pub dynamic_offset: Option, From 0d172b29148a41940903c2ca4367e6e4b8c4ad18 Mon Sep 17 00:00:00 2001 From: James Liu Date: Sat, 2 Mar 2024 10:37:52 -0800 Subject: [PATCH 004/124] Document instability of Entity's internal representation (#12249) # Objective bevy_ecs has been developed with a de facto assumption that `Entity` is to be treated as an opaque identifier by external users, and that its internal representation is readable but in no way guaranteed to be stable between versions of bevy_ecs. This hasn't been clear to users, and the functions on the type that expose its guts speak a different story. ## Solution Explicitly document the lack of stability here and define internal representation changes as a non-breaking change under SemVer. Give it the same treatment that the standard lib gives `TypeId`. --- crates/bevy_ecs/src/entity/mod.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/crates/bevy_ecs/src/entity/mod.rs b/crates/bevy_ecs/src/entity/mod.rs index 3f397cf3dd5f5..9dbc26ac1a8cc 100644 --- a/crates/bevy_ecs/src/entity/mod.rs +++ b/crates/bevy_ecs/src/entity/mod.rs @@ -81,6 +81,17 @@ type IdCursor = isize; /// /// [generational index]: https://lucassardois.medium.com/generational-indices-guide-8e3c5f7fd594 /// +/// # Stability warning +/// For all intents and purposes, `Entity` should be treated as an opaque identifier. The internal bit +/// representation is liable to change from release to release as are the behaviors or performance +/// characteristics of any of its trait implementations (i.e. `Ord`, `Hash`, etc.). This means that changes in +/// `Entity`'s representation, though made readable through various functions on the type, are not considered +/// breaking changes under [SemVer]. +/// +/// In particular, directly serializing with `Serialize` and `Deserialize` make zero guarantee of long +/// term wire format compatibility. Changes in behavior will cause serialized `Entity` values persisted +/// to long term storage (i.e. disk, databases, etc.) will fail to deserialize upon being updated. +/// /// # Usage /// /// This data type is returned by iterating a `Query` that has `Entity` as part of its query fetch type parameter ([learn more]). @@ -127,6 +138,7 @@ type IdCursor = isize; /// [`EntityCommands`]: crate::system::EntityCommands /// [`Query::get`]: crate::system::Query::get /// [`World`]: crate::world::World +/// [SemVer]: https://semver.org/ #[derive(Clone, Copy)] #[cfg_attr(feature = "bevy_reflect", derive(Reflect))] #[cfg_attr( From 5619bd09d1668dc3b0f14833bb1c3d7cffa9f9ef Mon Sep 17 00:00:00 2001 From: James Liu Date: Sat, 2 Mar 2024 10:38:04 -0800 Subject: [PATCH 005/124] Replace bevy_log's tracing reexport with bevy_utils' (#12254) # Objective Fixes #11298. Make the use of bevy_log vs bevy_utils::tracing more consistent. ## Solution Replace all uses of bevy_log's logging macros with the reexport from bevy_utils. Remove bevy_log as a dependency where it's no longer needed anymore. Ideally we should just be using tracing directly, but given that all of these crates are already using bevy_utils, this likely isn't that great of a loss right now. --- crates/bevy_animation/Cargo.toml | 1 - crates/bevy_animation/src/lib.rs | 3 +-- crates/bevy_asset/Cargo.toml | 2 +- crates/bevy_asset/src/io/android.rs | 2 +- crates/bevy_asset/src/io/embedded/embedded_watcher.rs | 2 +- crates/bevy_asset/src/io/file/file_watcher.rs | 2 +- crates/bevy_asset/src/io/file/mod.rs | 2 +- crates/bevy_asset/src/io/processor_gated.rs | 2 +- crates/bevy_asset/src/io/source.rs | 2 +- crates/bevy_asset/src/io/wasm.rs | 2 +- crates/bevy_asset/src/lib.rs | 3 +-- crates/bevy_asset/src/meta.rs | 2 +- crates/bevy_asset/src/processor/log.rs | 2 +- crates/bevy_asset/src/processor/mod.rs | 2 +- crates/bevy_asset/src/server/info.rs | 2 +- crates/bevy_asset/src/server/loaders.rs | 2 +- crates/bevy_asset/src/server/mod.rs | 2 +- crates/bevy_core_pipeline/Cargo.toml | 1 - crates/bevy_core_pipeline/src/tonemapping/mod.rs | 8 +++++--- crates/bevy_diagnostic/Cargo.toml | 1 - crates/bevy_diagnostic/src/log_diagnostics_plugin.rs | 2 +- .../src/system_information_diagnostics_plugin.rs | 4 ++-- crates/bevy_gilrs/Cargo.toml | 1 - crates/bevy_gilrs/src/rumble.rs | 2 +- crates/bevy_gizmos/Cargo.toml | 1 - crates/bevy_gizmos/src/lib.rs | 4 +++- crates/bevy_gltf/Cargo.toml | 1 - crates/bevy_gltf/src/loader.rs | 8 ++++---- crates/bevy_hierarchy/Cargo.toml | 3 +-- crates/bevy_hierarchy/src/valid_parent_check_plugin.rs | 2 +- crates/bevy_render/Cargo.toml | 1 - crates/bevy_render/src/camera/camera.rs | 2 +- crates/bevy_render/src/extract_resource.rs | 2 +- crates/bevy_render/src/mesh/mesh/mod.rs | 2 +- crates/bevy_render/src/render_graph/app.rs | 2 +- .../src/render_resource/bind_group_layout_entries.rs | 2 +- crates/bevy_render/src/view/window/mod.rs | 2 +- crates/bevy_render/src/view/window/screenshot.rs | 2 +- crates/bevy_sprite/Cargo.toml | 1 - crates/bevy_sprite/src/mesh2d/material.rs | 2 +- crates/bevy_sprite/src/texture_atlas_builder.rs | 2 +- crates/bevy_sprite/src/texture_slice/mod.rs | 2 +- crates/bevy_sprite/src/texture_slice/slicer.rs | 2 +- crates/bevy_ui/Cargo.toml | 1 - crates/bevy_ui/src/layout/debug.rs | 2 +- crates/bevy_ui/src/layout/mod.rs | 2 +- 46 files changed, 47 insertions(+), 55 deletions(-) diff --git a/crates/bevy_animation/Cargo.toml b/crates/bevy_animation/Cargo.toml index eb8f48c12179b..d5892658270c1 100644 --- a/crates/bevy_animation/Cargo.toml +++ b/crates/bevy_animation/Cargo.toml @@ -13,7 +13,6 @@ keywords = ["bevy"] bevy_app = { path = "../bevy_app", version = "0.14.0-dev" } bevy_asset = { path = "../bevy_asset", version = "0.14.0-dev" } bevy_core = { path = "../bevy_core", version = "0.14.0-dev" } -bevy_log = { path = "../bevy_log", version = "0.14.0-dev" } bevy_math = { path = "../bevy_math", version = "0.14.0-dev" } bevy_reflect = { path = "../bevy_reflect", version = "0.14.0-dev", features = [ "bevy", diff --git a/crates/bevy_animation/src/lib.rs b/crates/bevy_animation/src/lib.rs index bef6c87157c30..67d1ec924b2a5 100644 --- a/crates/bevy_animation/src/lib.rs +++ b/crates/bevy_animation/src/lib.rs @@ -14,14 +14,13 @@ use bevy_core::Name; use bevy_ecs::entity::MapEntities; use bevy_ecs::prelude::*; use bevy_ecs::reflect::ReflectMapEntities; -use bevy_log::error; use bevy_math::{FloatExt, Quat, Vec3}; use bevy_reflect::Reflect; use bevy_render::mesh::morph::MorphWeights; use bevy_time::Time; use bevy_transform::{prelude::Transform, TransformSystem}; use bevy_utils::hashbrown::HashMap; -use bevy_utils::{NoOpHash, Uuid}; +use bevy_utils::{tracing::error, NoOpHash, Uuid}; use sha1_smol::Sha1; #[allow(missing_docs)] diff --git a/crates/bevy_asset/Cargo.toml b/crates/bevy_asset/Cargo.toml index 49534ba2a5c1d..4dfdb2bb02cc9 100644 --- a/crates/bevy_asset/Cargo.toml +++ b/crates/bevy_asset/Cargo.toml @@ -21,7 +21,6 @@ watch = [] bevy_app = { path = "../bevy_app", version = "0.14.0-dev" } bevy_asset_macros = { path = "macros", version = "0.14.0-dev" } bevy_ecs = { path = "../bevy_ecs", version = "0.14.0-dev" } -bevy_log = { path = "../bevy_log", version = "0.14.0-dev" } bevy_reflect = { path = "../bevy_reflect", version = "0.14.0-dev" } bevy_tasks = { path = "../bevy_tasks", version = "0.14.0-dev" } bevy_utils = { path = "../bevy_utils", version = "0.14.0-dev" } @@ -53,6 +52,7 @@ notify-debouncer-full = { version = "0.3.1", optional = true } [dev-dependencies] bevy_core = { path = "../bevy_core", version = "0.14.0-dev" } +bevy_log = { path = "../bevy_log", version = "0.14.0-dev" } [lints] workspace = true diff --git a/crates/bevy_asset/src/io/android.rs b/crates/bevy_asset/src/io/android.rs index f792a72b00383..38791b35e0071 100644 --- a/crates/bevy_asset/src/io/android.rs +++ b/crates/bevy_asset/src/io/android.rs @@ -1,7 +1,7 @@ use crate::io::{ get_meta_path, AssetReader, AssetReaderError, EmptyPathStream, PathStream, Reader, VecReader, }; -use bevy_log::error; +use bevy_utils::tracing::error; use bevy_utils::BoxedFuture; use std::{ffi::CString, path::Path}; diff --git a/crates/bevy_asset/src/io/embedded/embedded_watcher.rs b/crates/bevy_asset/src/io/embedded/embedded_watcher.rs index 1e7f3057bbfd2..485593599c489 100644 --- a/crates/bevy_asset/src/io/embedded/embedded_watcher.rs +++ b/crates/bevy_asset/src/io/embedded/embedded_watcher.rs @@ -3,7 +3,7 @@ use crate::io::{ memory::Dir, AssetSourceEvent, AssetWatcher, }; -use bevy_log::warn; +use bevy_utils::tracing::warn; use bevy_utils::{Duration, HashMap}; use notify_debouncer_full::{notify::RecommendedWatcher, Debouncer, FileIdMap}; use parking_lot::RwLock; diff --git a/crates/bevy_asset/src/io/file/file_watcher.rs b/crates/bevy_asset/src/io/file/file_watcher.rs index 720adb7ed965b..fbed3f8a0ecbe 100644 --- a/crates/bevy_asset/src/io/file/file_watcher.rs +++ b/crates/bevy_asset/src/io/file/file_watcher.rs @@ -1,6 +1,6 @@ use crate::io::{AssetSourceEvent, AssetWatcher}; use crate::path::normalize_path; -use bevy_log::error; +use bevy_utils::tracing::error; use bevy_utils::Duration; use crossbeam_channel::Sender; use notify_debouncer_full::{ diff --git a/crates/bevy_asset/src/io/file/mod.rs b/crates/bevy_asset/src/io/file/mod.rs index 25bd1e5175f22..19a9ffb0cdae8 100644 --- a/crates/bevy_asset/src/io/file/mod.rs +++ b/crates/bevy_asset/src/io/file/mod.rs @@ -6,7 +6,7 @@ mod file_asset; #[cfg(not(feature = "multi-threaded"))] mod sync_file_asset; -use bevy_log::error; +use bevy_utils::tracing::error; #[cfg(feature = "file_watcher")] pub use file_watcher::*; diff --git a/crates/bevy_asset/src/io/processor_gated.rs b/crates/bevy_asset/src/io/processor_gated.rs index ed5aacb0a911f..b86460f04b6fd 100644 --- a/crates/bevy_asset/src/io/processor_gated.rs +++ b/crates/bevy_asset/src/io/processor_gated.rs @@ -4,7 +4,7 @@ use crate::{ AssetPath, }; use async_lock::RwLockReadGuardArc; -use bevy_log::trace; +use bevy_utils::tracing::trace; use bevy_utils::BoxedFuture; use futures_io::AsyncRead; use std::{path::Path, pin::Pin, sync::Arc}; diff --git a/crates/bevy_asset/src/io/source.rs b/crates/bevy_asset/src/io/source.rs index 690eee2da1d2f..7293a73bea418 100644 --- a/crates/bevy_asset/src/io/source.rs +++ b/crates/bevy_asset/src/io/source.rs @@ -6,7 +6,7 @@ use crate::{ processor::AssetProcessorData, }; use bevy_ecs::system::Resource; -use bevy_log::{error, warn}; +use bevy_utils::tracing::{error, warn}; use bevy_utils::{CowArc, Duration, HashMap}; use std::{fmt::Display, hash::Hash, sync::Arc}; use thiserror::Error; diff --git a/crates/bevy_asset/src/io/wasm.rs b/crates/bevy_asset/src/io/wasm.rs index 7ee60ecfdb8c9..aab497ddfa7cc 100644 --- a/crates/bevy_asset/src/io/wasm.rs +++ b/crates/bevy_asset/src/io/wasm.rs @@ -1,7 +1,7 @@ use crate::io::{ get_meta_path, AssetReader, AssetReaderError, EmptyPathStream, PathStream, Reader, VecReader, }; -use bevy_log::error; +use bevy_utils::tracing::error; use bevy_utils::BoxedFuture; use js_sys::{Uint8Array, JSON}; use std::path::{Path, PathBuf}; diff --git a/crates/bevy_asset/src/lib.rs b/crates/bevy_asset/src/lib.rs index 9fa056e3bced7..d5789d4a54277 100644 --- a/crates/bevy_asset/src/lib.rs +++ b/crates/bevy_asset/src/lib.rs @@ -55,9 +55,8 @@ use bevy_ecs::{ system::Resource, world::FromWorld, }; -use bevy_log::error; use bevy_reflect::{FromReflect, GetTypeRegistration, Reflect, TypePath}; -use bevy_utils::HashSet; +use bevy_utils::{tracing::error, HashSet}; use std::{any::TypeId, sync::Arc}; #[cfg(all(feature = "file_watcher", not(feature = "multi-threaded")))] diff --git a/crates/bevy_asset/src/meta.rs b/crates/bevy_asset/src/meta.rs index e8758999f7d7e..f20e0c2e32288 100644 --- a/crates/bevy_asset/src/meta.rs +++ b/crates/bevy_asset/src/meta.rs @@ -1,6 +1,6 @@ use crate::{self as bevy_asset, DeserializeMetaError, VisitAssetDependencies}; use crate::{loader::AssetLoader, processor::Process, Asset, AssetPath}; -use bevy_log::error; +use bevy_utils::tracing::error; use downcast_rs::{impl_downcast, Downcast}; use ron::ser::PrettyConfig; use serde::{Deserialize, Serialize}; diff --git a/crates/bevy_asset/src/processor/log.rs b/crates/bevy_asset/src/processor/log.rs index 642de9b127142..64207295e751b 100644 --- a/crates/bevy_asset/src/processor/log.rs +++ b/crates/bevy_asset/src/processor/log.rs @@ -1,6 +1,6 @@ use crate::AssetPath; use async_fs::File; -use bevy_log::error; +use bevy_utils::tracing::error; use bevy_utils::HashSet; use futures_lite::{AsyncReadExt, AsyncWriteExt}; use std::path::PathBuf; diff --git a/crates/bevy_asset/src/processor/mod.rs b/crates/bevy_asset/src/processor/mod.rs index 625a484330078..ace12c8f7301b 100644 --- a/crates/bevy_asset/src/processor/mod.rs +++ b/crates/bevy_asset/src/processor/mod.rs @@ -17,8 +17,8 @@ use crate::{ MissingAssetLoaderForExtensionError, }; use bevy_ecs::prelude::*; -use bevy_log::{debug, error, trace, warn}; use bevy_tasks::IoTaskPool; +use bevy_utils::tracing::{debug, error, trace, warn}; use bevy_utils::{BoxedFuture, HashMap, HashSet}; use futures_io::ErrorKind; use futures_lite::{AsyncReadExt, AsyncWriteExt, StreamExt}; diff --git a/crates/bevy_asset/src/server/info.rs b/crates/bevy_asset/src/server/info.rs index 6e9b758fa77ca..5de02e7cc16ec 100644 --- a/crates/bevy_asset/src/server/info.rs +++ b/crates/bevy_asset/src/server/info.rs @@ -5,7 +5,7 @@ use crate::{ UntypedAssetId, UntypedHandle, }; use bevy_ecs::world::World; -use bevy_log::warn; +use bevy_utils::tracing::warn; use bevy_utils::{Entry, HashMap, HashSet, TypeIdMap}; use crossbeam_channel::Sender; use std::{ diff --git a/crates/bevy_asset/src/server/loaders.rs b/crates/bevy_asset/src/server/loaders.rs index 65f21d6b9b52f..98cc3bce9d28f 100644 --- a/crates/bevy_asset/src/server/loaders.rs +++ b/crates/bevy_asset/src/server/loaders.rs @@ -3,8 +3,8 @@ use crate::{ path::AssetPath, }; use async_broadcast::RecvError; -use bevy_log::{error, warn}; use bevy_tasks::IoTaskPool; +use bevy_utils::tracing::{error, warn}; use bevy_utils::{HashMap, TypeIdMap}; use std::{any::TypeId, sync::Arc}; use thiserror::Error; diff --git a/crates/bevy_asset/src/server/mod.rs b/crates/bevy_asset/src/server/mod.rs index cc0825d3aaa57..2be2848aece48 100644 --- a/crates/bevy_asset/src/server/mod.rs +++ b/crates/bevy_asset/src/server/mod.rs @@ -18,8 +18,8 @@ use crate::{ UntypedAssetLoadFailedEvent, UntypedHandle, }; use bevy_ecs::prelude::*; -use bevy_log::{error, info}; use bevy_tasks::IoTaskPool; +use bevy_utils::tracing::{error, info}; use bevy_utils::{CowArc, HashSet}; use crossbeam_channel::{Receiver, Sender}; use futures_lite::StreamExt; diff --git a/crates/bevy_core_pipeline/Cargo.toml b/crates/bevy_core_pipeline/Cargo.toml index 7b7aaee4aff32..824e78ee89923 100644 --- a/crates/bevy_core_pipeline/Cargo.toml +++ b/crates/bevy_core_pipeline/Cargo.toml @@ -27,7 +27,6 @@ bevy_core = { path = "../bevy_core", version = "0.14.0-dev" } bevy_color = { path = "../bevy_color", version = "0.14.0-dev" } bevy_derive = { path = "../bevy_derive", version = "0.14.0-dev" } bevy_ecs = { path = "../bevy_ecs", version = "0.14.0-dev" } -bevy_log = { path = "../bevy_log", version = "0.14.0-dev" } bevy_reflect = { path = "../bevy_reflect", version = "0.14.0-dev" } bevy_render = { path = "../bevy_render", version = "0.14.0-dev" } bevy_transform = { path = "../bevy_transform", version = "0.14.0-dev" } diff --git a/crates/bevy_core_pipeline/src/tonemapping/mod.rs b/crates/bevy_core_pipeline/src/tonemapping/mod.rs index 0045d9e05047e..7726ff1e36a15 100644 --- a/crates/bevy_core_pipeline/src/tonemapping/mod.rs +++ b/crates/bevy_core_pipeline/src/tonemapping/mod.rs @@ -14,6 +14,8 @@ use bevy_render::renderer::RenderDevice; use bevy_render::texture::{CompressedImageFormats, Image, ImageSampler, ImageType}; use bevy_render::view::{ViewTarget, ViewUniform}; use bevy_render::{render_resource::*, Render, RenderApp, RenderSet}; +#[cfg(not(feature = "tonemapping_luts"))] +use bevy_utils::tracing::error; mod node; @@ -199,7 +201,7 @@ impl SpecializedRenderPipeline for TonemappingPipeline { Tonemapping::AcesFitted => shader_defs.push("TONEMAP_METHOD_ACES_FITTED".into()), Tonemapping::AgX => { #[cfg(not(feature = "tonemapping_luts"))] - bevy_log::error!( + error!( "AgX tonemapping requires the `tonemapping_luts` feature. Either enable the `tonemapping_luts` feature for bevy in `Cargo.toml` (recommended), or use a different `Tonemapping` method in your `Camera2dBundle`/`Camera3dBundle`." @@ -211,7 +213,7 @@ impl SpecializedRenderPipeline for TonemappingPipeline { } Tonemapping::TonyMcMapface => { #[cfg(not(feature = "tonemapping_luts"))] - bevy_log::error!( + error!( "TonyMcMapFace tonemapping requires the `tonemapping_luts` feature. Either enable the `tonemapping_luts` feature for bevy in `Cargo.toml` (recommended), or use a different `Tonemapping` method in your `Camera2dBundle`/`Camera3dBundle`." @@ -220,7 +222,7 @@ impl SpecializedRenderPipeline for TonemappingPipeline { } Tonemapping::BlenderFilmic => { #[cfg(not(feature = "tonemapping_luts"))] - bevy_log::error!( + error!( "BlenderFilmic tonemapping requires the `tonemapping_luts` feature. Either enable the `tonemapping_luts` feature for bevy in `Cargo.toml` (recommended), or use a different `Tonemapping` method in your `Camera2dBundle`/`Camera3dBundle`." diff --git a/crates/bevy_diagnostic/Cargo.toml b/crates/bevy_diagnostic/Cargo.toml index 0ba362ab71d8d..f0a3ade496ce4 100644 --- a/crates/bevy_diagnostic/Cargo.toml +++ b/crates/bevy_diagnostic/Cargo.toml @@ -19,7 +19,6 @@ features = [] bevy_app = { path = "../bevy_app", version = "0.14.0-dev" } bevy_core = { path = "../bevy_core", version = "0.14.0-dev" } bevy_ecs = { path = "../bevy_ecs", version = "0.14.0-dev" } -bevy_log = { path = "../bevy_log", version = "0.14.0-dev" } bevy_time = { path = "../bevy_time", version = "0.14.0-dev" } bevy_utils = { path = "../bevy_utils", version = "0.14.0-dev" } diff --git a/crates/bevy_diagnostic/src/log_diagnostics_plugin.rs b/crates/bevy_diagnostic/src/log_diagnostics_plugin.rs index f3f57683086c1..2f007edcaaf50 100644 --- a/crates/bevy_diagnostic/src/log_diagnostics_plugin.rs +++ b/crates/bevy_diagnostic/src/log_diagnostics_plugin.rs @@ -1,8 +1,8 @@ use super::{Diagnostic, DiagnosticPath, DiagnosticsStore}; use bevy_app::prelude::*; use bevy_ecs::prelude::*; -use bevy_log::{debug, info}; use bevy_time::{Real, Time, Timer, TimerMode}; +use bevy_utils::tracing::{debug, info}; use bevy_utils::Duration; /// An App Plugin that logs diagnostics to the console. diff --git a/crates/bevy_diagnostic/src/system_information_diagnostics_plugin.rs b/crates/bevy_diagnostic/src/system_information_diagnostics_plugin.rs index 1fe0f62148508..0ffe3d479b2af 100644 --- a/crates/bevy_diagnostic/src/system_information_diagnostics_plugin.rs +++ b/crates/bevy_diagnostic/src/system_information_diagnostics_plugin.rs @@ -40,7 +40,7 @@ impl SystemInformationDiagnosticsPlugin { ))] pub mod internal { use bevy_ecs::{prelude::ResMut, system::Local}; - use bevy_log::info; + use bevy_utils::tracing::info; use sysinfo::{CpuRefreshKind, MemoryRefreshKind, RefreshKind, System}; use crate::{Diagnostic, Diagnostics, DiagnosticsStore}; @@ -136,7 +136,7 @@ pub mod internal { )))] pub mod internal { pub(crate) fn setup_system() { - bevy_log::warn!("This platform and/or configuration is not supported!"); + bevy_utils::tracing::warn!("This platform and/or configuration is not supported!"); } pub(crate) fn diagnostic_system() { diff --git a/crates/bevy_gilrs/Cargo.toml b/crates/bevy_gilrs/Cargo.toml index 000d8692265c2..bf0bd644abd26 100644 --- a/crates/bevy_gilrs/Cargo.toml +++ b/crates/bevy_gilrs/Cargo.toml @@ -13,7 +13,6 @@ keywords = ["bevy"] bevy_app = { path = "../bevy_app", version = "0.14.0-dev" } bevy_ecs = { path = "../bevy_ecs", version = "0.14.0-dev" } bevy_input = { path = "../bevy_input", version = "0.14.0-dev" } -bevy_log = { path = "../bevy_log", version = "0.14.0-dev" } bevy_utils = { path = "../bevy_utils", version = "0.14.0-dev" } bevy_time = { path = "../bevy_time", version = "0.14.0-dev" } diff --git a/crates/bevy_gilrs/src/rumble.rs b/crates/bevy_gilrs/src/rumble.rs index c982a52ce2fa5..b59abef9a066f 100644 --- a/crates/bevy_gilrs/src/rumble.rs +++ b/crates/bevy_gilrs/src/rumble.rs @@ -4,8 +4,8 @@ use bevy_ecs::prelude::{EventReader, Res, ResMut, Resource}; #[cfg(target_arch = "wasm32")] use bevy_ecs::system::NonSendMut; use bevy_input::gamepad::{GamepadRumbleIntensity, GamepadRumbleRequest}; -use bevy_log::{debug, warn}; use bevy_time::{Real, Time}; +use bevy_utils::tracing::{debug, warn}; use bevy_utils::{synccell::SyncCell, Duration, HashMap}; use gilrs::{ ff::{self, BaseEffect, BaseEffectType, Repeat, Replay}, diff --git a/crates/bevy_gizmos/Cargo.toml b/crates/bevy_gizmos/Cargo.toml index b573c5d6d921d..205759c974ee2 100644 --- a/crates/bevy_gizmos/Cargo.toml +++ b/crates/bevy_gizmos/Cargo.toml @@ -27,7 +27,6 @@ bevy_core = { path = "../bevy_core", version = "0.14.0-dev" } bevy_reflect = { path = "../bevy_reflect", version = "0.14.0-dev" } bevy_core_pipeline = { path = "../bevy_core_pipeline", version = "0.14.0-dev" } bevy_transform = { path = "../bevy_transform", version = "0.14.0-dev" } -bevy_log = { path = "../bevy_log", version = "0.14.0-dev" } bevy_gizmos_macros = { path = "macros", version = "0.14.0-dev" } [lints] diff --git a/crates/bevy_gizmos/src/lib.rs b/crates/bevy_gizmos/src/lib.rs index dc0db0cbfa96a..1a72e7171949e 100644 --- a/crates/bevy_gizmos/src/lib.rs +++ b/crates/bevy_gizmos/src/lib.rs @@ -96,7 +96,9 @@ impl Plugin for GizmoPlugin { fn build(&self, app: &mut bevy_app::App) { // Gizmos cannot work without either a 3D or 2D renderer. #[cfg(all(not(feature = "bevy_pbr"), not(feature = "bevy_sprite")))] - bevy_log::error!("bevy_gizmos requires either bevy_pbr or bevy_sprite. Please enable one."); + bevy_utils::tracing::error!( + "bevy_gizmos requires either bevy_pbr or bevy_sprite. Please enable one." + ); load_internal_asset!(app, LINE_SHADER_HANDLE, "lines.wgsl", Shader::from_wgsl); diff --git a/crates/bevy_gltf/Cargo.toml b/crates/bevy_gltf/Cargo.toml index 2d7817f6f4572..e1a29899db8de 100644 --- a/crates/bevy_gltf/Cargo.toml +++ b/crates/bevy_gltf/Cargo.toml @@ -22,7 +22,6 @@ bevy_core = { path = "../bevy_core", version = "0.14.0-dev" } bevy_core_pipeline = { path = "../bevy_core_pipeline", version = "0.14.0-dev" } bevy_ecs = { path = "../bevy_ecs", version = "0.14.0-dev" } bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.14.0-dev" } -bevy_log = { path = "../bevy_log", version = "0.14.0-dev" } bevy_math = { path = "../bevy_math", version = "0.14.0-dev" } bevy_pbr = { path = "../bevy_pbr", version = "0.14.0-dev" } bevy_reflect = { path = "../bevy_reflect", version = "0.14.0-dev", features = [ diff --git a/crates/bevy_gltf/src/loader.rs b/crates/bevy_gltf/src/loader.rs index ca6a309684e95..276eb9f8f677f 100644 --- a/crates/bevy_gltf/src/loader.rs +++ b/crates/bevy_gltf/src/loader.rs @@ -9,7 +9,6 @@ use bevy_core_pipeline::prelude::Camera3dBundle; use bevy_ecs::entity::EntityHashMap; use bevy_ecs::{entity::Entity, world::World}; use bevy_hierarchy::{BuildWorldChildren, WorldChildBuilder}; -use bevy_log::{error, info_span, warn}; use bevy_math::{Affine2, Mat4, Vec3}; use bevy_pbr::{ DirectionalLight, DirectionalLightBundle, PbrBundle, PointLight, PointLightBundle, SpotLight, @@ -36,6 +35,7 @@ use bevy_scene::Scene; #[cfg(not(target_arch = "wasm32"))] use bevy_tasks::IoTaskPool; use bevy_transform::components::Transform; +use bevy_utils::tracing::{error, info_span, warn}; use bevy_utils::{ smallvec::{smallvec, SmallVec}, HashMap, HashSet, @@ -474,9 +474,9 @@ async fn load_gltf<'a, 'b, 'c>( let vertex_count_after = mesh.count_vertices(); if vertex_count_before != vertex_count_after { - bevy_log::debug!("Missing vertex normals in indexed geometry, computing them as flat. Vertex count increased from {} to {}", vertex_count_before, vertex_count_after); + bevy_utils::tracing::debug!("Missing vertex normals in indexed geometry, computing them as flat. Vertex count increased from {} to {}", vertex_count_before, vertex_count_after); } else { - bevy_log::debug!( + bevy_utils::tracing::debug!( "Missing vertex normals in indexed geometry, computing them as flat." ); } @@ -490,7 +490,7 @@ async fn load_gltf<'a, 'b, 'c>( } else if mesh.attribute(Mesh::ATTRIBUTE_NORMAL).is_some() && primitive.material().normal_texture().is_some() { - bevy_log::debug!( + bevy_utils::tracing::debug!( "Missing vertex tangents for {}, computing them using the mikktspace algorithm. Consider using a tool such as Blender to pre-compute the tangents.", file_name ); diff --git a/crates/bevy_hierarchy/Cargo.toml b/crates/bevy_hierarchy/Cargo.toml index 96ffbbf08ac05..ede2cabe6054c 100644 --- a/crates/bevy_hierarchy/Cargo.toml +++ b/crates/bevy_hierarchy/Cargo.toml @@ -11,7 +11,7 @@ keywords = ["bevy"] [features] default = ["bevy_app"] trace = [] -bevy_app = ["reflect", "dep:bevy_app", "bevy_core", "bevy_log"] +bevy_app = ["reflect", "dep:bevy_app", "bevy_core"] reflect = ["bevy_ecs/bevy_reflect", "bevy_reflect"] [dependencies] @@ -19,7 +19,6 @@ reflect = ["bevy_ecs/bevy_reflect", "bevy_reflect"] bevy_app = { path = "../bevy_app", version = "0.14.0-dev", optional = true } bevy_core = { path = "../bevy_core", version = "0.14.0-dev", optional = true } bevy_ecs = { path = "../bevy_ecs", version = "0.14.0-dev", default-features = false } -bevy_log = { path = "../bevy_log", version = "0.14.0-dev", optional = true } bevy_reflect = { path = "../bevy_reflect", version = "0.14.0-dev", features = [ "bevy", ], optional = true } diff --git a/crates/bevy_hierarchy/src/valid_parent_check_plugin.rs b/crates/bevy_hierarchy/src/valid_parent_check_plugin.rs index d5d0783c1e328..c3d766bcde7d6 100644 --- a/crates/bevy_hierarchy/src/valid_parent_check_plugin.rs +++ b/crates/bevy_hierarchy/src/valid_parent_check_plugin.rs @@ -64,7 +64,7 @@ pub fn check_hierarchy_component_has_valid_parent( let parent = parent.get(); if !component_query.contains(parent) && !already_diagnosed.contains(&entity) { already_diagnosed.insert(entity); - bevy_log::warn!( + bevy_utils::tracing::warn!( "warning[B0004]: {name} with the {ty_name} component has a parent without {ty_name}.\n\ This will cause inconsistent behaviors! See: https://bevyengine.org/learn/errors/#b0004", ty_name = get_short_name(std::any::type_name::()), diff --git a/crates/bevy_render/Cargo.toml b/crates/bevy_render/Cargo.toml index 03ac8038e3cbb..84b58b00032a3 100644 --- a/crates/bevy_render/Cargo.toml +++ b/crates/bevy_render/Cargo.toml @@ -46,7 +46,6 @@ bevy_derive = { path = "../bevy_derive", version = "0.14.0-dev" } bevy_ecs = { path = "../bevy_ecs", version = "0.14.0-dev" } bevy_encase_derive = { path = "../bevy_encase_derive", version = "0.14.0-dev" } bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.14.0-dev" } -bevy_log = { path = "../bevy_log", version = "0.14.0-dev" } bevy_math = { path = "../bevy_math", version = "0.14.0-dev" } bevy_mikktspace = { path = "../bevy_mikktspace", version = "0.14.0-dev" } bevy_reflect = { path = "../bevy_reflect", version = "0.14.0-dev", features = [ diff --git a/crates/bevy_render/src/camera/camera.rs b/crates/bevy_render/src/camera/camera.rs index 31f81714adc17..ca22a773dc767 100644 --- a/crates/bevy_render/src/camera/camera.rs +++ b/crates/bevy_render/src/camera/camera.rs @@ -20,11 +20,11 @@ use bevy_ecs::{ reflect::ReflectComponent, system::{Commands, Query, Res, ResMut, Resource}, }; -use bevy_log::warn; use bevy_math::{vec2, Dir3, Mat4, Ray3d, Rect, URect, UVec2, UVec4, Vec2, Vec3}; use bevy_reflect::prelude::*; use bevy_render_macros::ExtractComponent; use bevy_transform::components::GlobalTransform; +use bevy_utils::tracing::warn; use bevy_utils::{HashMap, HashSet}; use bevy_window::{ NormalizedWindowRef, PrimaryWindow, Window, WindowCreated, WindowRef, WindowResized, diff --git a/crates/bevy_render/src/extract_resource.rs b/crates/bevy_render/src/extract_resource.rs index 7a928bd291570..038a612fe21f6 100644 --- a/crates/bevy_render/src/extract_resource.rs +++ b/crates/bevy_render/src/extract_resource.rs @@ -51,7 +51,7 @@ pub fn extract_resource( } else { #[cfg(debug_assertions)] if !main_resource.is_added() { - bevy_log::warn_once!( + bevy_utils::warn_once!( "Removing resource {} from render world not expected, adding using `Commands`. This may decrease performance", std::any::type_name::() diff --git a/crates/bevy_render/src/mesh/mesh/mod.rs b/crates/bevy_render/src/mesh/mesh/mod.rs index 33a21e62d6b58..ae57a9a297c4e 100644 --- a/crates/bevy_render/src/mesh/mesh/mod.rs +++ b/crates/bevy_render/src/mesh/mesh/mod.rs @@ -17,10 +17,10 @@ use bevy_ecs::system::{ lifetimeless::{SRes, SResMut}, SystemParamItem, }; -use bevy_log::warn; use bevy_math::*; use bevy_reflect::Reflect; use bevy_utils::tracing::error; +use bevy_utils::tracing::warn; use std::{collections::BTreeMap, hash::Hash, iter::FusedIterator}; use thiserror::Error; use wgpu::{ diff --git a/crates/bevy_render/src/render_graph/app.rs b/crates/bevy_render/src/render_graph/app.rs index 97ababa312b73..94082590aa86b 100644 --- a/crates/bevy_render/src/render_graph/app.rs +++ b/crates/bevy_render/src/render_graph/app.rs @@ -1,6 +1,6 @@ use bevy_app::App; use bevy_ecs::world::FromWorld; -use bevy_log::warn; +use bevy_utils::tracing::warn; use super::{IntoRenderNodeArray, Node, RenderGraph, RenderLabel, RenderSubGraph}; diff --git a/crates/bevy_render/src/render_resource/bind_group_layout_entries.rs b/crates/bevy_render/src/render_resource/bind_group_layout_entries.rs index b877d38c027e1..7bb9ff1cafd21 100644 --- a/crates/bevy_render/src/render_resource/bind_group_layout_entries.rs +++ b/crates/bevy_render/src/render_resource/bind_group_layout_entries.rs @@ -222,7 +222,7 @@ impl IntoBindGroupLayoutEntryBuilder for BindingType { impl IntoBindGroupLayoutEntryBuilder for BindGroupLayoutEntry { fn into_bind_group_layout_entry_builder(self) -> BindGroupLayoutEntryBuilder { if self.binding != u32::MAX { - bevy_log::warn!("The BindGroupLayoutEntries api ignores the binding index when converting a raw wgpu::BindGroupLayoutEntry. You can ignore this warning by setting it to u32::MAX."); + bevy_utils::tracing::warn!("The BindGroupLayoutEntries api ignores the binding index when converting a raw wgpu::BindGroupLayoutEntry. You can ignore this warning by setting it to u32::MAX."); } BindGroupLayoutEntryBuilder { ty: self.ty, diff --git a/crates/bevy_render/src/view/window/mod.rs b/crates/bevy_render/src/view/window/mod.rs index 6bca35efdea2d..64d089cee0f7c 100644 --- a/crates/bevy_render/src/view/window/mod.rs +++ b/crates/bevy_render/src/view/window/mod.rs @@ -276,7 +276,7 @@ pub fn prepare_windows( format!("MSAA {}x", fallback.samples()) }; - bevy_log::warn!( + bevy_utils::tracing::warn!( "MSAA {}x is not supported on this device. Falling back to {}.", msaa.samples(), fallback_str, diff --git a/crates/bevy_render/src/view/window/screenshot.rs b/crates/bevy_render/src/view/window/screenshot.rs index c13a60f88524c..ca93f73afd81f 100644 --- a/crates/bevy_render/src/view/window/screenshot.rs +++ b/crates/bevy_render/src/view/window/screenshot.rs @@ -3,8 +3,8 @@ use std::{borrow::Cow, path::Path, sync::PoisonError}; use bevy_app::Plugin; use bevy_asset::{load_internal_asset, Handle}; use bevy_ecs::{entity::EntityHashMap, prelude::*}; -use bevy_log::{error, info, info_span}; use bevy_tasks::AsyncComputeTaskPool; +use bevy_utils::tracing::{error, info, info_span}; use std::sync::Mutex; use thiserror::Error; use wgpu::{ diff --git a/crates/bevy_sprite/Cargo.toml b/crates/bevy_sprite/Cargo.toml index ce8c402de2e08..01fea40918265 100644 --- a/crates/bevy_sprite/Cargo.toml +++ b/crates/bevy_sprite/Cargo.toml @@ -19,7 +19,6 @@ bevy_asset = { path = "../bevy_asset", version = "0.14.0-dev" } bevy_color = { path = "../bevy_color", version = "0.14.0-dev" } bevy_core_pipeline = { path = "../bevy_core_pipeline", version = "0.14.0-dev" } bevy_ecs = { path = "../bevy_ecs", version = "0.14.0-dev" } -bevy_log = { path = "../bevy_log", version = "0.14.0-dev" } bevy_math = { path = "../bevy_math", version = "0.14.0-dev" } bevy_reflect = { path = "../bevy_reflect", version = "0.14.0-dev", features = [ "bevy", diff --git a/crates/bevy_sprite/src/mesh2d/material.rs b/crates/bevy_sprite/src/mesh2d/material.rs index a8588c73f80e3..2b5772c686559 100644 --- a/crates/bevy_sprite/src/mesh2d/material.rs +++ b/crates/bevy_sprite/src/mesh2d/material.rs @@ -10,7 +10,6 @@ use bevy_ecs::{ prelude::*, system::{lifetimeless::SRes, SystemParamItem}, }; -use bevy_log::error; use bevy_render::{ mesh::{Mesh, MeshVertexBufferLayoutRef}, prelude::Image, @@ -30,6 +29,7 @@ use bevy_render::{ Extract, ExtractSchedule, Render, RenderApp, RenderSet, }; use bevy_transform::components::{GlobalTransform, Transform}; +use bevy_utils::tracing::error; use bevy_utils::{FloatOrd, HashMap, HashSet}; use std::hash::Hash; use std::marker::PhantomData; diff --git a/crates/bevy_sprite/src/texture_atlas_builder.rs b/crates/bevy_sprite/src/texture_atlas_builder.rs index 23327db5e9947..126d00fe0da80 100644 --- a/crates/bevy_sprite/src/texture_atlas_builder.rs +++ b/crates/bevy_sprite/src/texture_atlas_builder.rs @@ -1,11 +1,11 @@ use bevy_asset::AssetId; -use bevy_log::{debug, error, warn}; use bevy_math::{URect, UVec2}; use bevy_render::{ render_asset::RenderAssetUsages, render_resource::{Extent3d, TextureDimension, TextureFormat}, texture::{Image, TextureFormatPixelInfo}, }; +use bevy_utils::tracing::{debug, error, warn}; use bevy_utils::HashMap; use rectangle_pack::{ contains_smallest_box, pack_rects, volume_heuristic, GroupedRectsToPlace, PackedLocation, diff --git a/crates/bevy_sprite/src/texture_slice/mod.rs b/crates/bevy_sprite/src/texture_slice/mod.rs index d617634acd3bd..516f025ca6676 100644 --- a/crates/bevy_sprite/src/texture_slice/mod.rs +++ b/crates/bevy_sprite/src/texture_slice/mod.rs @@ -86,7 +86,7 @@ impl TextureSlice { remaining_columns -= size_y; } if slices.len() > 1_000 { - bevy_log::warn!("One of your tiled textures has generated {} slices. You might want to use higher stretch values to avoid a great performance cost", slices.len()); + bevy_utils::tracing::warn!("One of your tiled textures has generated {} slices. You might want to use higher stretch values to avoid a great performance cost", slices.len()); } slices } diff --git a/crates/bevy_sprite/src/texture_slice/slicer.rs b/crates/bevy_sprite/src/texture_slice/slicer.rs index f048d6d880a53..ab12ce47488e5 100644 --- a/crates/bevy_sprite/src/texture_slice/slicer.rs +++ b/crates/bevy_sprite/src/texture_slice/slicer.rs @@ -207,7 +207,7 @@ impl TextureSlicer { || self.border.top >= rect_size.y || self.border.bottom >= rect_size.y { - bevy_log::error!( + bevy_utils::tracing::error!( "TextureSlicer::border has out of bounds values. No slicing will be applied" ); return vec![TextureSlice { diff --git a/crates/bevy_ui/Cargo.toml b/crates/bevy_ui/Cargo.toml index 3f2649257755f..a417a5bfac8e0 100644 --- a/crates/bevy_ui/Cargo.toml +++ b/crates/bevy_ui/Cargo.toml @@ -19,7 +19,6 @@ bevy_derive = { path = "../bevy_derive", version = "0.14.0-dev" } bevy_ecs = { path = "../bevy_ecs", version = "0.14.0-dev" } bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.14.0-dev" } bevy_input = { path = "../bevy_input", version = "0.14.0-dev" } -bevy_log = { path = "../bevy_log", version = "0.14.0-dev" } bevy_math = { path = "../bevy_math", version = "0.14.0-dev" } bevy_reflect = { path = "../bevy_reflect", version = "0.14.0-dev", features = [ "bevy", diff --git a/crates/bevy_ui/src/layout/debug.rs b/crates/bevy_ui/src/layout/debug.rs index 37fb5c2b88845..8d5f27e169eca 100644 --- a/crates/bevy_ui/src/layout/debug.rs +++ b/crates/bevy_ui/src/layout/debug.rs @@ -25,7 +25,7 @@ pub fn print_ui_layout_tree(ui_surface: &UiSurface) { &mut out, ); } - bevy_log::info!("Layout tree for camera entity: {entity:?}\n{out}"); + bevy_utils::tracing::info!("Layout tree for camera entity: {entity:?}\n{out}"); } } diff --git a/crates/bevy_ui/src/layout/mod.rs b/crates/bevy_ui/src/layout/mod.rs index 9c69a6e0d982b..7d1fa732b3797 100644 --- a/crates/bevy_ui/src/layout/mod.rs +++ b/crates/bevy_ui/src/layout/mod.rs @@ -13,10 +13,10 @@ use bevy_ecs::{ world::Ref, }; use bevy_hierarchy::{Children, Parent}; -use bevy_log::warn; use bevy_math::{UVec2, Vec2}; use bevy_render::camera::{Camera, NormalizedRenderTarget}; use bevy_transform::components::Transform; +use bevy_utils::tracing::warn; use bevy_utils::{default, HashMap, HashSet}; use bevy_window::{PrimaryWindow, Window, WindowScaleFactorChanged}; use std::fmt; From 04ec10552c30615378205222a80aaca5ff82a4dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Sat, 2 Mar 2024 23:20:44 +0100 Subject: [PATCH 006/124] PBR: use attenuation instead of base_color for attenuation (#12266) # Objective - Copy paste error in #12163 ## Solution - Fix it --- crates/bevy_pbr/src/pbr_material.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/bevy_pbr/src/pbr_material.rs b/crates/bevy_pbr/src/pbr_material.rs index a83509267d2ec..92af53df2a8d5 100644 --- a/crates/bevy_pbr/src/pbr_material.rs +++ b/crates/bevy_pbr/src/pbr_material.rs @@ -727,7 +727,9 @@ impl AsBindGroupShaderType for StandardMaterial { thickness: self.thickness, ior: self.ior, attenuation_distance: self.attenuation_distance, - attenuation_color: LinearRgba::from(self.base_color).to_f32_array().into(), + attenuation_color: LinearRgba::from(self.attenuation_color) + .to_f32_array() + .into(), flags: flags.bits(), alpha_cutoff, parallax_depth_scale: self.parallax_depth_scale, From 13cbb9cf10001fe07f20b3bc51753a55f3211728 Mon Sep 17 00:00:00 2001 From: targrub <62773321+targrub@users.noreply.github.com> Date: Sat, 2 Mar 2024 18:13:45 -0500 Subject: [PATCH 007/124] Move commands module into bevy::ecs::world (#12234) # Objective Fixes https://github.com/bevyengine/bevy/issues/11628 ## Migration Guide `Command` and `CommandQueue` have migrated from `bevy_ecs::system` to `bevy_ecs::world`, so `use bevy_ecs::world::{Command, CommandQueue};` when necessary. --- benches/benches/bevy_ecs/world/commands.rs | 4 +- .../bevy_ecs/src/reflect/entity_commands.rs | 3 +- crates/bevy_ecs/src/system/commands/mod.rs | 58 ++----------------- crates/bevy_ecs/src/system/system_registry.rs | 4 +- .../commands => world}/command_queue.rs | 14 ++++- crates/bevy_ecs/src/world/mod.rs | 41 ++++++++++++- .../bevy_ecs/src/world/unsafe_world_cell.rs | 4 +- crates/bevy_hierarchy/src/child_builder.rs | 8 +-- crates/bevy_hierarchy/src/hierarchy.rs | 8 +-- crates/bevy_scene/src/dynamic_scene.rs | 2 +- crates/bevy_scene/src/scene_spawner.rs | 4 +- crates/bevy_transform/src/commands.rs | 2 +- crates/bevy_transform/src/systems.rs | 2 +- crates/bevy_ui/src/stack.rs | 4 +- examples/async_tasks/async_compute.rs | 3 +- 15 files changed, 81 insertions(+), 80 deletions(-) rename crates/bevy_ecs/src/{system/commands => world}/command_queue.rs (97%) diff --git a/benches/benches/bevy_ecs/world/commands.rs b/benches/benches/bevy_ecs/world/commands.rs index 70cf1351acfcb..2b3d84195aff8 100644 --- a/benches/benches/bevy_ecs/world/commands.rs +++ b/benches/benches/bevy_ecs/world/commands.rs @@ -1,8 +1,8 @@ use bevy_ecs::{ component::Component, entity::Entity, - system::{Command, CommandQueue, Commands}, - world::World, + system::Commands, + world::{Command, CommandQueue, World}, }; use criterion::{black_box, Criterion}; diff --git a/crates/bevy_ecs/src/reflect/entity_commands.rs b/crates/bevy_ecs/src/reflect/entity_commands.rs index 7f69130d801c3..8545b346bd15a 100644 --- a/crates/bevy_ecs/src/reflect/entity_commands.rs +++ b/crates/bevy_ecs/src/reflect/entity_commands.rs @@ -1,6 +1,7 @@ use crate::prelude::Mut; use crate::reflect::AppTypeRegistry; -use crate::system::{Command, EntityCommands, Resource}; +use crate::system::{EntityCommands, Resource}; +use crate::world::Command; use crate::{entity::Entity, reflect::ReflectComponent, world::World}; use bevy_reflect::{Reflect, TypeRegistry}; use std::borrow::Cow; diff --git a/crates/bevy_ecs/src/system/commands/mod.rs b/crates/bevy_ecs/src/system/commands/mod.rs index 65fa06ed7c6a7..a48be90868054 100644 --- a/crates/bevy_ecs/src/system/commands/mod.rs +++ b/crates/bevy_ecs/src/system/commands/mod.rs @@ -1,57 +1,18 @@ -mod command_queue; mod parallel_scope; +use super::{Deferred, Resource}; use crate::{ self as bevy_ecs, bundle::Bundle, entity::{Entities, Entity}, system::{RunSystemWithInput, SystemId}, - world::{EntityWorldMut, FromWorld, World}, + world::{Command, CommandQueue, EntityWorldMut, FromWorld, World}, }; use bevy_ecs_macros::SystemParam; use bevy_utils::tracing::{error, info}; -pub use command_queue::CommandQueue; pub use parallel_scope::*; use std::marker::PhantomData; -use super::{Deferred, Resource, SystemBuffer, SystemMeta}; - -/// A [`World`] mutation. -/// -/// Should be used with [`Commands::add`]. -/// -/// # Usage -/// -/// ``` -/// # use bevy_ecs::prelude::*; -/// # use bevy_ecs::system::Command; -/// // Our world resource -/// #[derive(Resource, Default)] -/// struct Counter(u64); -/// -/// // Our custom command -/// struct AddToCounter(u64); -/// -/// impl Command for AddToCounter { -/// fn apply(self, world: &mut World) { -/// let mut counter = world.get_resource_or_insert_with(Counter::default); -/// counter.0 += self.0; -/// } -/// } -/// -/// fn some_system(mut commands: Commands) { -/// commands.add(AddToCounter(42)); -/// } -/// ``` -pub trait Command: Send + 'static { - /// Applies this command, causing it to mutate the provided `world`. - /// - /// This method is used to define what a command "does" when it is ultimately applied. - /// Because this method takes `self`, you can store data or settings on the type that implements this trait. - /// This data is set by the system or other source of the command, and then ultimately read in this method. - fn apply(self, world: &mut World); -} - /// A [`Command`] queue to perform structural changes to the [`World`]. /// /// Since each command requires exclusive access to the `World`, @@ -115,15 +76,6 @@ pub struct Commands<'w, 's> { entities: &'w Entities, } -impl SystemBuffer for CommandQueue { - #[inline] - fn apply(&mut self, _system_meta: &SystemMeta, world: &mut World) { - #[cfg(feature = "trace")] - let _span_guard = _system_meta.commands_span.enter(); - self.apply(world); - } -} - impl<'w, 's> Commands<'w, 's> { /// Returns a new `Commands` instance from a [`CommandQueue`] and a [`World`]. /// @@ -581,7 +533,7 @@ impl<'w, 's> Commands<'w, 's> { /// # Example /// /// ``` - /// # use bevy_ecs::{system::Command, prelude::*}; + /// # use bevy_ecs::{world::Command, prelude::*}; /// #[derive(Resource, Default)] /// struct Counter(u64); /// @@ -1138,8 +1090,8 @@ mod tests { use crate::{ self as bevy_ecs, component::Component, - system::{CommandQueue, Commands, Resource}, - world::World, + system::{Commands, Resource}, + world::{CommandQueue, World}, }; use std::sync::{ atomic::{AtomicUsize, Ordering}, diff --git a/crates/bevy_ecs/src/system/system_registry.rs b/crates/bevy_ecs/src/system/system_registry.rs index f4722f1511a4b..ec65b0be84f48 100644 --- a/crates/bevy_ecs/src/system/system_registry.rs +++ b/crates/bevy_ecs/src/system/system_registry.rs @@ -1,6 +1,6 @@ use crate::entity::Entity; -use crate::system::{BoxedSystem, Command, IntoSystem}; -use crate::world::World; +use crate::system::{BoxedSystem, IntoSystem}; +use crate::world::{Command, World}; use crate::{self as bevy_ecs}; use bevy_ecs_macros::Component; use thiserror::Error; diff --git a/crates/bevy_ecs/src/system/commands/command_queue.rs b/crates/bevy_ecs/src/world/command_queue.rs similarity index 97% rename from crates/bevy_ecs/src/system/commands/command_queue.rs rename to crates/bevy_ecs/src/world/command_queue.rs index a9dcd6f965de2..3103e3486ce2d 100644 --- a/crates/bevy_ecs/src/system/commands/command_queue.rs +++ b/crates/bevy_ecs/src/world/command_queue.rs @@ -1,10 +1,11 @@ +use crate::system::{SystemBuffer, SystemMeta}; + use std::{fmt::Debug, mem::MaybeUninit}; use bevy_ptr::{OwningPtr, Unaligned}; use bevy_utils::tracing::warn; -use super::Command; -use crate::world::World; +use crate::world::{Command, World}; struct CommandMeta { /// SAFETY: The `value` must point to a value of type `T: Command`, @@ -234,6 +235,15 @@ impl Drop for CommandQueue { } } +impl SystemBuffer for CommandQueue { + #[inline] + fn apply(&mut self, _system_meta: &SystemMeta, world: &mut World) { + #[cfg(feature = "trace")] + let _span_guard = _system_meta.commands_span.enter(); + self.apply(world); + } +} + #[cfg(test)] mod test { use super::*; diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 81691f6a6a70c..2b9e6e276adb8 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -1,5 +1,6 @@ //! Defines the [`World`] and APIs for accessing it directly. +mod command_queue; mod deferred_world; mod entity_ref; pub mod error; @@ -8,6 +9,7 @@ pub mod unsafe_world_cell; mod world_cell; pub use crate::change_detection::{Mut, Ref, CHECK_TICK_THRESHOLD}; +pub use crate::world::command_queue::CommandQueue; pub use deferred_world::DeferredWorld; pub use entity_ref::{ EntityMut, EntityRef, EntityWorldMut, Entry, FilteredEntityMut, FilteredEntityRef, @@ -30,7 +32,7 @@ use crate::{ removal_detection::RemovedComponentEvents, schedule::{Schedule, ScheduleLabel, Schedules}, storage::{ResourceData, Storages}, - system::{CommandQueue, Commands, Res, Resource}, + system::{Commands, Res, Resource}, world::error::TryRunScheduleError, }; use bevy_ptr::{OwningPtr, Ptr}; @@ -43,9 +45,44 @@ use std::{ }; mod identifier; +use self::unsafe_world_cell::{UnsafeEntityCell, UnsafeWorldCell}; pub use identifier::WorldId; -use self::unsafe_world_cell::{UnsafeEntityCell, UnsafeWorldCell}; +/// A [`World`] mutation. +/// +/// Should be used with [`Commands::add`]. +/// +/// # Usage +/// +/// ``` +/// # use bevy_ecs::prelude::*; +/// # use bevy_ecs::world::Command; +/// // Our world resource +/// #[derive(Resource, Default)] +/// struct Counter(u64); +/// +/// // Our custom command +/// struct AddToCounter(u64); +/// +/// impl Command for AddToCounter { +/// fn apply(self, world: &mut World) { +/// let mut counter = world.get_resource_or_insert_with(Counter::default); +/// counter.0 += self.0; +/// } +/// } +/// +/// fn some_system(mut commands: Commands) { +/// commands.add(AddToCounter(42)); +/// } +/// ``` +pub trait Command: Send + 'static { + /// Applies this command, causing it to mutate the provided `world`. + /// + /// This method is used to define what a command "does" when it is ultimately applied. + /// Because this method takes `self`, you can store data or settings on the type that implements this trait. + /// This data is set by the system or other source of the command, and then ultimately read in this method. + fn apply(self, world: &mut World); +} /// Stores and exposes operations on [entities](Entity), [components](Component), resources, /// and their associated metadata. diff --git a/crates/bevy_ecs/src/world/unsafe_world_cell.rs b/crates/bevy_ecs/src/world/unsafe_world_cell.rs index b786a3cfb4425..977158d87cd52 100644 --- a/crates/bevy_ecs/src/world/unsafe_world_cell.rs +++ b/crates/bevy_ecs/src/world/unsafe_world_cell.rs @@ -2,7 +2,7 @@ #![warn(unsafe_op_in_unsafe_fn)] -use super::{Mut, Ref, World, WorldId}; +use super::{command_queue::CommandQueue, Mut, Ref, World, WorldId}; use crate::{ archetype::{Archetype, ArchetypeComponentId, Archetypes}, bundle::Bundles, @@ -14,7 +14,7 @@ use crate::{ prelude::Component, removal_detection::RemovedComponentEvents, storage::{Column, ComponentSparseSet, Storages}, - system::{CommandQueue, Res, Resource}, + system::{Res, Resource}, }; use bevy_ptr::Ptr; use std::{any::TypeId, cell::UnsafeCell, fmt::Debug, marker::PhantomData, ptr, ptr::addr_of_mut}; diff --git a/crates/bevy_hierarchy/src/child_builder.rs b/crates/bevy_hierarchy/src/child_builder.rs index d119afe95ee70..b6ec13fe73372 100644 --- a/crates/bevy_hierarchy/src/child_builder.rs +++ b/crates/bevy_hierarchy/src/child_builder.rs @@ -3,8 +3,8 @@ use bevy_ecs::{ bundle::Bundle, entity::Entity, prelude::Events, - system::{Command, Commands, EntityCommands}, - world::{EntityWorldMut, World}, + system::{Commands, EntityCommands}, + world::{Command, EntityWorldMut, World}, }; use bevy_utils::smallvec::{smallvec, SmallVec}; @@ -702,8 +702,8 @@ mod tests { component::Component, entity::Entity, event::Events, - system::{CommandQueue, Commands}, - world::World, + system::Commands, + world::{CommandQueue, World}, }; /// Assert the (non)existence and state of the child's [`Parent`] component. diff --git a/crates/bevy_hierarchy/src/hierarchy.rs b/crates/bevy_hierarchy/src/hierarchy.rs index d707be839c76f..26f26233a0fe5 100644 --- a/crates/bevy_hierarchy/src/hierarchy.rs +++ b/crates/bevy_hierarchy/src/hierarchy.rs @@ -1,8 +1,8 @@ use crate::components::{Children, Parent}; use bevy_ecs::{ entity::Entity, - system::{Command, EntityCommands}, - world::{EntityWorldMut, World}, + system::EntityCommands, + world::{Command, EntityWorldMut, World}, }; use bevy_utils::tracing::debug; @@ -139,8 +139,8 @@ impl<'w> DespawnRecursiveExt for EntityWorldMut<'w> { mod tests { use bevy_ecs::{ component::Component, - system::{CommandQueue, Commands}, - world::World, + system::Commands, + world::{CommandQueue, World}, }; use super::DespawnRecursiveExt; diff --git a/crates/bevy_scene/src/dynamic_scene.rs b/crates/bevy_scene/src/dynamic_scene.rs index 2cf9a190e1fd4..ac2f98ffae8bb 100644 --- a/crates/bevy_scene/src/dynamic_scene.rs +++ b/crates/bevy_scene/src/dynamic_scene.rs @@ -193,7 +193,7 @@ where #[cfg(test)] mod tests { use bevy_ecs::entity::EntityHashMap; - use bevy_ecs::{reflect::AppTypeRegistry, system::Command, world::World}; + use bevy_ecs::{reflect::AppTypeRegistry, world::Command, world::World}; use bevy_hierarchy::{Parent, PushChild}; use crate::dynamic_scene_builder::DynamicSceneBuilder; diff --git a/crates/bevy_scene/src/scene_spawner.rs b/crates/bevy_scene/src/scene_spawner.rs index d8e0ea63acb5a..86c0c30d9a3d9 100644 --- a/crates/bevy_scene/src/scene_spawner.rs +++ b/crates/bevy_scene/src/scene_spawner.rs @@ -5,8 +5,8 @@ use bevy_ecs::{ entity::Entity, event::{Event, Events, ManualEventReader}, reflect::AppTypeRegistry, - system::{Command, Resource}, - world::{Mut, World}, + system::Resource, + world::{Command, Mut, World}, }; use bevy_hierarchy::{Parent, PushChild}; use bevy_utils::{tracing::error, HashMap, HashSet}; diff --git a/crates/bevy_transform/src/commands.rs b/crates/bevy_transform/src/commands.rs index 1a2f0d4c8abfb..8cbad487ba5e9 100644 --- a/crates/bevy_transform/src/commands.rs +++ b/crates/bevy_transform/src/commands.rs @@ -1,7 +1,7 @@ //! Extension to [`EntityCommands`] to modify `bevy_hierarchy` hierarchies //! while preserving [`GlobalTransform`]. -use bevy_ecs::{prelude::Entity, system::Command, system::EntityCommands, world::World}; +use bevy_ecs::{prelude::Entity, system::EntityCommands, world::Command, world::World}; use bevy_hierarchy::{PushChild, RemoveParent}; use crate::{GlobalTransform, Transform}; diff --git a/crates/bevy_transform/src/systems.rs b/crates/bevy_transform/src/systems.rs index 8f6bac916a739..bdbce91e941bb 100644 --- a/crates/bevy_transform/src/systems.rs +++ b/crates/bevy_transform/src/systems.rs @@ -182,7 +182,7 @@ unsafe fn propagate_recursive( mod test { use bevy_app::prelude::*; use bevy_ecs::prelude::*; - use bevy_ecs::system::CommandQueue; + use bevy_ecs::world::CommandQueue; use bevy_math::{vec3, Vec3}; use bevy_tasks::{ComputeTaskPool, TaskPool}; diff --git a/crates/bevy_ui/src/stack.rs b/crates/bevy_ui/src/stack.rs index ec389daa59144..6acc994b6f71e 100644 --- a/crates/bevy_ui/src/stack.rs +++ b/crates/bevy_ui/src/stack.rs @@ -126,8 +126,8 @@ mod tests { use bevy_ecs::{ component::Component, schedule::Schedule, - system::{CommandQueue, Commands}, - world::World, + system::Commands, + world::{CommandQueue, World}, }; use bevy_hierarchy::BuildChildren; diff --git a/examples/async_tasks/async_compute.rs b/examples/async_tasks/async_compute.rs index 0227c2841b41a..bf4b8a26ec807 100644 --- a/examples/async_tasks/async_compute.rs +++ b/examples/async_tasks/async_compute.rs @@ -2,7 +2,8 @@ //! to spawn, poll, and complete tasks across systems and system ticks. use bevy::{ - ecs::system::{CommandQueue, SystemState}, + ecs::system::SystemState, + ecs::world::CommandQueue, prelude::*, tasks::{block_on, futures_lite::future, AsyncComputeTaskPool, Task}, }; From d5c32bdc23c302dd801fac5a04b3a186491d8aaf Mon Sep 17 00:00:00 2001 From: geekvest <126322776+geekvest@users.noreply.github.com> Date: Sun, 3 Mar 2024 15:58:22 +0800 Subject: [PATCH 008/124] remove repetitive code (#12270) Signed-off-by: geekvest --- crates/bevy_asset/src/path.rs | 2 +- crates/bevy_ecs/src/bundle.rs | 2 +- crates/bevy_ecs/src/query/builder.rs | 2 +- crates/bevy_ecs/src/world/deferred_world.rs | 2 +- crates/bevy_ecs/src/world/mod.rs | 4 ++-- crates/bevy_ecs/src/world/world_cell.rs | 4 ++-- crates/bevy_gizmos/src/lib.rs | 2 +- crates/bevy_tasks/src/thread_executor.rs | 2 +- examples/time/virtual_time.rs | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/crates/bevy_asset/src/path.rs b/crates/bevy_asset/src/path.rs index b9247cf04518f..e49db629362f0 100644 --- a/crates/bevy_asset/src/path.rs +++ b/crates/bevy_asset/src/path.rs @@ -381,7 +381,7 @@ impl<'a> AssetPath<'a> { /// Resolves an embedded asset path via concatenation. The result will be an `AssetPath` which /// is resolved relative to this path. This is similar in operation to `resolve`, except that - /// the the 'file' portion of the base path (that is, any characters after the last '/') + /// the 'file' portion of the base path (that is, any characters after the last '/') /// is removed before concatenation, in accordance with the behavior specified in /// IETF RFC 1808 "Relative URIs". /// diff --git a/crates/bevy_ecs/src/bundle.rs b/crates/bevy_ecs/src/bundle.rs index f6af2e9be024d..2804618cbb206 100644 --- a/crates/bevy_ecs/src/bundle.rs +++ b/crates/bevy_ecs/src/bundle.rs @@ -348,7 +348,7 @@ impl BundleInfo { &self.component_ids } - /// Returns an iterator over the the [ID](ComponentId) of each component stored in this bundle. + /// Returns an iterator over the [ID](ComponentId) of each component stored in this bundle. #[inline] pub fn iter_components(&self) -> impl Iterator + '_ { self.component_ids.iter().cloned() diff --git a/crates/bevy_ecs/src/query/builder.rs b/crates/bevy_ecs/src/query/builder.rs index 160999e9e84b4..b19c5a6b516d8 100644 --- a/crates/bevy_ecs/src/query/builder.rs +++ b/crates/bevy_ecs/src/query/builder.rs @@ -204,7 +204,7 @@ impl<'w, D: QueryData, F: QueryFilter> QueryBuilder<'w, D, F> { self } - /// Returns a reference to the the [`FilteredAccess`] that will be provided to the built [`Query`]. + /// Returns a reference to the [`FilteredAccess`] that will be provided to the built [`Query`]. pub fn access(&self) -> &FilteredAccess { &self.access } diff --git a/crates/bevy_ecs/src/world/deferred_world.rs b/crates/bevy_ecs/src/world/deferred_world.rs index 81352445a9047..f9d5fc53a6b84 100644 --- a/crates/bevy_ecs/src/world/deferred_world.rs +++ b/crates/bevy_ecs/src/world/deferred_world.rs @@ -165,7 +165,7 @@ impl<'w> DeferredWorld<'w> { None => panic!( "Requested non-send resource {} does not exist in the `World`. Did you forget to add it using `app.insert_non_send_resource` / `app.init_non_send_resource`? - Non-send resources can also be be added by plugins.", + Non-send resources can also be added by plugins.", std::any::type_name::() ), } diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 2b9e6e276adb8..a36c244ef7cc0 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -1484,7 +1484,7 @@ impl World { None => panic!( "Requested non-send resource {} does not exist in the `World`. Did you forget to add it using `app.insert_non_send_resource` / `app.init_non_send_resource`? - Non-send resources can also be be added by plugins.", + Non-send resources can also be added by plugins.", std::any::type_name::() ), } @@ -1506,7 +1506,7 @@ impl World { None => panic!( "Requested non-send resource {} does not exist in the `World`. Did you forget to add it using `app.insert_non_send_resource` / `app.init_non_send_resource`? - Non-send resources can also be be added by plugins.", + Non-send resources can also be added by plugins.", std::any::type_name::() ), } diff --git a/crates/bevy_ecs/src/world/world_cell.rs b/crates/bevy_ecs/src/world/world_cell.rs index 852858ba607b3..2ae79b32306e6 100644 --- a/crates/bevy_ecs/src/world/world_cell.rs +++ b/crates/bevy_ecs/src/world/world_cell.rs @@ -296,7 +296,7 @@ impl<'w> WorldCell<'w> { None => panic!( "Requested non-send resource {} does not exist in the `World`. Did you forget to add it using `app.insert_non_send_resource` / `app.init_non_send_resource`? - Non-send resources can also be be added by plugins.", + Non-send resources can also be added by plugins.", std::any::type_name::() ), } @@ -330,7 +330,7 @@ impl<'w> WorldCell<'w> { None => panic!( "Requested non-send resource {} does not exist in the `World`. Did you forget to add it using `app.insert_non_send_resource` / `app.init_non_send_resource`? - Non-send resources can also be be added by plugins.", + Non-send resources can also be added by plugins.", std::any::type_name::() ), } diff --git a/crates/bevy_gizmos/src/lib.rs b/crates/bevy_gizmos/src/lib.rs index 1a72e7171949e..93634e78c0aa7 100644 --- a/crates/bevy_gizmos/src/lib.rs +++ b/crates/bevy_gizmos/src/lib.rs @@ -14,7 +14,7 @@ //! //! See the documentation on [Gizmos](crate::gizmos::Gizmos) for more examples. -/// Label for the the render systems handling the +/// System set label for the systems handling the rendering of gizmos. #[derive(SystemSet, Clone, Debug, Hash, PartialEq, Eq)] pub enum GizmoRenderSystem { /// Adds gizmos to the [`Transparent2d`](bevy_core_pipeline::core_2d::Transparent2d) render phase diff --git a/crates/bevy_tasks/src/thread_executor.rs b/crates/bevy_tasks/src/thread_executor.rs index dc989f902c12d..cc6b272efb4ff 100644 --- a/crates/bevy_tasks/src/thread_executor.rs +++ b/crates/bevy_tasks/src/thread_executor.rs @@ -106,7 +106,7 @@ impl<'task, 'ticker> ThreadExecutorTicker<'task, 'ticker> { } /// Synchronously try to tick a task on the executor. - /// Returns false if if does not find a task to tick. + /// Returns false if does not find a task to tick. pub fn try_tick(&self) -> bool { self.executor.executor.try_tick() } diff --git a/examples/time/virtual_time.rs b/examples/time/virtual_time.rs index 0e5fddd7d9f51..52cec835f8f95 100644 --- a/examples/time/virtual_time.rs +++ b/examples/time/virtual_time.rs @@ -146,7 +146,7 @@ fn move_real_time_sprites( for mut transform in sprite_query.iter_mut() { // move roughly half the screen in a `Real` second // when the time is scaled the speed is going to change - // and the sprite will stay still the the time is paused + // and the sprite will stay still the time is paused transform.translation.x = get_sprite_translation_x(time.elapsed_seconds()); } } From 8cf5fbbf94bc2ede732b360d3dc2a8a5d918381b Mon Sep 17 00:00:00 2001 From: Thierry Berger Date: Sun, 3 Mar 2024 15:33:30 +0100 Subject: [PATCH 009/124] Fix fit_canvas_to_parent (#11278) Follow up to #11057 Implemented suggestions from reviewers from: a simpler fit_canvas_to_parent leads to an explicit CSS setting to the canvas. From my understanding, it has do be set after wgpu creation due to wgpu overriding the canvas width/height: https://github.com/gfx-rs/wgpu/blob/4400a5847080d1164bdca93a90622414963ed9f3/examples/src/utils.rs#L68-L74 # Changelog - Re-enable a `fit_canvas_to_parent`, it's removal from https://github.com/bevyengine/bevy/pull/11057 was problematic. Still, its inner working is more simple than before: bevy doesn't handle its resizing, winit does. ## Migration Guide - Cancels the migration from https://github.com/bevyengine/bevy/pull/11057 --- crates/bevy_window/src/window.rs | 9 +++++++++ crates/bevy_winit/Cargo.toml | 1 - crates/bevy_winit/src/system.rs | 14 ++++++++++++++ examples/wasm/index.html | 2 -- examples/window/window_settings.rs | 2 ++ tools/example-showcase/window-settings-wasm.patch | 6 ++++-- 6 files changed, 29 insertions(+), 5 deletions(-) diff --git a/crates/bevy_window/src/window.rs b/crates/bevy_window/src/window.rs index b6079158615a1..2f476bca644f9 100644 --- a/crates/bevy_window/src/window.rs +++ b/crates/bevy_window/src/window.rs @@ -206,6 +206,14 @@ pub struct Window { /// /// This value has no effect on non-web platforms. pub canvas: Option, + /// Whether or not to fit the canvas element's size to its parent element's size. + /// + /// **Warning**: this will not behave as expected for parents that set their size according to the size of their + /// children. This creates a "feedback loop" that will result in the canvas growing on each resize. When using this + /// feature, ensure the parent's size is not affected by its children. + /// + /// This value has no effect on non-web platforms. + pub fit_canvas_to_parent: bool, /// Whether or not to stop events from propagating out of the canvas element /// /// When `true`, this will prevent common browser hotkeys like F5, F12, Ctrl+R, tab, etc. @@ -274,6 +282,7 @@ impl Default for Window { transparent: false, focused: true, window_level: Default::default(), + fit_canvas_to_parent: false, prevent_default_event_handling: true, canvas: None, window_theme: None, diff --git a/crates/bevy_winit/Cargo.toml b/crates/bevy_winit/Cargo.toml index 6477c90db6dd5..aaeb19d77a36e 100644 --- a/crates/bevy_winit/Cargo.toml +++ b/crates/bevy_winit/Cargo.toml @@ -45,7 +45,6 @@ winit = { version = "0.29", default-features = false, features = [ [target.'cfg(target_arch = "wasm32")'.dependencies] wasm-bindgen = { version = "0.2" } web-sys = "0.3" - crossbeam-channel = "0.5" [package.metadata.docs.rs] diff --git a/crates/bevy_winit/src/system.rs b/crates/bevy_winit/src/system.rs index b027461075970..af6d017f26da5 100644 --- a/crates/bevy_winit/src/system.rs +++ b/crates/bevy_winit/src/system.rs @@ -17,6 +17,9 @@ use winit::{ event_loop::EventLoopWindowTarget, }; +#[cfg(target_arch = "wasm32")] +use winit::platform::web::WindowExtWebSys; + use crate::{ converters::{ self, convert_enabled_buttons, convert_window_level, convert_window_theme, @@ -80,6 +83,17 @@ pub(crate) fn create_windows( window: window.clone(), }); + #[cfg(target_arch = "wasm32")] + { + if window.fit_canvas_to_parent { + let canvas = winit_window + .canvas() + .expect("window.canvas() can only be called in main thread."); + let style = canvas.style(); + style.set_property("width", "100%").unwrap(); + style.set_property("height", "100%").unwrap(); + } + } window_created_events.send(WindowCreated { window: entity }); } } diff --git a/examples/wasm/index.html b/examples/wasm/index.html index 0fa46de41877f..1688962669241 100644 --- a/examples/wasm/index.html +++ b/examples/wasm/index.html @@ -15,8 +15,6 @@ background-size: 20px 20px; } canvas { - width: 100%; - height: 100%; background-color: white; } diff --git a/examples/window/window_settings.rs b/examples/window/window_settings.rs index 31ea347e64db6..2e509e2fba7eb 100644 --- a/examples/window/window_settings.rs +++ b/examples/window/window_settings.rs @@ -17,6 +17,8 @@ fn main() { name: Some("bevy.app".into()), resolution: (500., 300.).into(), present_mode: PresentMode::AutoVsync, + // Tells wasm to resize the window according to the available canvas + fit_canvas_to_parent: true, // Tells wasm not to override default event handling, like F5, Ctrl+R etc. prevent_default_event_handling: false, window_theme: Some(WindowTheme::Dark), diff --git a/tools/example-showcase/window-settings-wasm.patch b/tools/example-showcase/window-settings-wasm.patch index 02e8965901869..5fcb1fba9556c 100644 --- a/tools/example-showcase/window-settings-wasm.patch +++ b/tools/example-showcase/window-settings-wasm.patch @@ -1,11 +1,13 @@ diff --git a/crates/bevy_window/src/window.rs b/crates/bevy_window/src/window.rs -index 7b5c75d38..8e9404b93 100644 +index 87cdfb050..1d87a0bf5 100644 --- a/crates/bevy_window/src/window.rs +++ b/crates/bevy_window/src/window.rs -@@ -245,8 +245,8 @@ impl Default for Window { +@@ -266,9 +266,9 @@ impl Default for Window { transparent: false, focused: true, window_level: Default::default(), +- fit_canvas_to_parent: false, ++ fit_canvas_to_parent: true, prevent_default_event_handling: true, - canvas: None, + canvas: Some("#bevy".to_string()), From 57733bbec321b7fd0509fd4a7cd573e0f5858f48 Mon Sep 17 00:00:00 2001 From: James Liu Date: Sun, 3 Mar 2024 06:55:27 -0800 Subject: [PATCH 010/124] Use NonMaxUsize for non-component SparseSets (#12083) # Objective Adoption of #2104 and #11843. The `Option` wastes 3-7 bytes of memory per potential entry, and represents a scaling memory overhead as the ID space grows. The goal of this PR is to reduce memory usage without significantly impacting common use cases. Co-Authored By: @NathanSWard Co-Authored By: @tygyh ## Solution Replace `usize` in `SparseSet`'s sparse array with `nonmax::NonMaxUsize`. NonMaxUsize wraps a NonZeroUsize, and applies a bitwise NOT to the value when accessing it. This allows the compiler to niche the value and eliminate the extra padding used for the `Option` inside the sparse array, while moving the niche value from 0 to usize::MAX instead. Checking the [diff in x86 generated assembly](https://github.com/james7132/bevy_asm_tests/commit/6e4da653cc02afa0aad5a962a4ff50522df2bf54), this change actually results in fewer instructions generated. One potential downside is that it seems to have moved a load before a branch, which means we may be incurring a cache miss even if the element is not there. Note: unlike #2104 and #11843, this PR only targets the metadata stores for the ECS and not the component storage itself. Due to #9907 targeting `Entity::generation` instead of `Entity::index`, `ComponentSparseSet` storing only up to `u32::MAX` elements would become a correctness issue. This will come with a cost when inserting items into the SparseSet, as now there is a potential for a panic. These cost are really only incurred when constructing a new Table, Archetype, or Resource that has never been seen before by the World. All operations that are fairly cold and not on any particular hotpath, even for command application. --- ## Changelog Changed: `SparseSet` now can only store up to `usize::MAX - 1` elements instead of `usize::MAX`. Changed: `SparseSet` now uses 33-50% less memory overhead per stored item. --- crates/bevy_ecs/Cargo.toml | 1 + crates/bevy_ecs/src/storage/sparse_set.rs | 28 +++++++++++++---------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/crates/bevy_ecs/Cargo.toml b/crates/bevy_ecs/Cargo.toml index b3372469694d0..db804278b4b2f 100644 --- a/crates/bevy_ecs/Cargo.toml +++ b/crates/bevy_ecs/Cargo.toml @@ -28,6 +28,7 @@ fixedbitset = "0.4.2" rustc-hash = "1.1" serde = "1" thiserror = "1.0" +nonmax = "0.5" [dev-dependencies] rand = "0.8" diff --git a/crates/bevy_ecs/src/storage/sparse_set.rs b/crates/bevy_ecs/src/storage/sparse_set.rs index dfb03f88681d2..dffdb71db961e 100644 --- a/crates/bevy_ecs/src/storage/sparse_set.rs +++ b/crates/bevy_ecs/src/storage/sparse_set.rs @@ -4,6 +4,7 @@ use crate::{ storage::{Column, TableRow}, }; use bevy_ptr::{OwningPtr, Ptr}; +use nonmax::NonMaxUsize; use std::{cell::UnsafeCell, hash::Hash, marker::PhantomData}; type EntityIndex = u32; @@ -335,7 +336,7 @@ impl ComponentSparseSet { pub struct SparseSet { dense: Vec, indices: Vec, - sparse: SparseArray, + sparse: SparseArray, } /// A space-optimized version of [`SparseSet`] that cannot be changed @@ -344,7 +345,7 @@ pub struct SparseSet { pub(crate) struct ImmutableSparseSet { dense: Box<[V]>, indices: Box<[I]>, - sparse: ImmutableSparseArray, + sparse: ImmutableSparseArray, } macro_rules! impl_sparse_set { @@ -368,7 +369,7 @@ macro_rules! impl_sparse_set { pub fn get(&self, index: I) -> Option<&V> { self.sparse.get(index).map(|dense_index| { // SAFETY: if the sparse index points to something in the dense vec, it exists - unsafe { self.dense.get_unchecked(*dense_index) } + unsafe { self.dense.get_unchecked(dense_index.get()) } }) } @@ -379,7 +380,7 @@ macro_rules! impl_sparse_set { let dense = &mut self.dense; self.sparse.get(index).map(move |dense_index| { // SAFETY: if the sparse index points to something in the dense vec, it exists - unsafe { dense.get_unchecked_mut(*dense_index) } + unsafe { dense.get_unchecked_mut(dense_index.get()) } }) } @@ -454,10 +455,11 @@ impl SparseSet { if let Some(dense_index) = self.sparse.get(index.clone()).cloned() { // SAFETY: dense indices stored in self.sparse always exist unsafe { - *self.dense.get_unchecked_mut(dense_index) = value; + *self.dense.get_unchecked_mut(dense_index.get()) = value; } } else { - self.sparse.insert(index.clone(), self.dense.len()); + self.sparse + .insert(index.clone(), NonMaxUsize::new(self.dense.len()).unwrap()); self.indices.push(index); self.dense.push(value); } @@ -468,11 +470,12 @@ impl SparseSet { pub fn get_or_insert_with(&mut self, index: I, func: impl FnOnce() -> V) -> &mut V { if let Some(dense_index) = self.sparse.get(index.clone()).cloned() { // SAFETY: dense indices stored in self.sparse always exist - unsafe { self.dense.get_unchecked_mut(dense_index) } + unsafe { self.dense.get_unchecked_mut(dense_index.get()) } } else { let value = func(); let dense_index = self.dense.len(); - self.sparse.insert(index.clone(), dense_index); + self.sparse + .insert(index.clone(), NonMaxUsize::new(dense_index).unwrap()); self.indices.push(index); self.dense.push(value); // SAFETY: dense index was just populated above @@ -491,11 +494,12 @@ impl SparseSet { /// Returns `None` if `index` does not have a value in the sparse set. pub fn remove(&mut self, index: I) -> Option { self.sparse.remove(index).map(|dense_index| { - let is_last = dense_index == self.dense.len() - 1; - let value = self.dense.swap_remove(dense_index); - self.indices.swap_remove(dense_index); + let index = dense_index.get(); + let is_last = index == self.dense.len() - 1; + let value = self.dense.swap_remove(index); + self.indices.swap_remove(index); if !is_last { - let swapped_index = self.indices[dense_index].clone(); + let swapped_index = self.indices[index].clone(); *self.sparse.get_mut(swapped_index).unwrap() = dense_index; } value From 6032978ebac8fc35cb6e580dd7217e391a8f8207 Mon Sep 17 00:00:00 2001 From: Joona Aalto Date: Sun, 3 Mar 2024 19:44:16 +0200 Subject: [PATCH 011/124] Implement `Mul` between `f32` and direction types (#12276) # Objective Bevy's `Dir3` and `Dir3A` only implement `Mul` and not vice versa, and `Dir2` can not be multiplied by `f32` at all. They all should implement multiplication both ways, just like Glam's vector types. ## Solution Implement `Mul`, `Mul`, and `Mul` for `f32`, and `Mul` for `Dir2`. --- crates/bevy_math/src/direction.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/crates/bevy_math/src/direction.rs b/crates/bevy_math/src/direction.rs index 8ac785878f6af..50a5218d74577 100644 --- a/crates/bevy_math/src/direction.rs +++ b/crates/bevy_math/src/direction.rs @@ -132,6 +132,20 @@ impl std::ops::Neg for Dir2 { } } +impl std::ops::Mul for Dir2 { + type Output = Vec2; + fn mul(self, rhs: f32) -> Self::Output { + self.0 * rhs + } +} + +impl std::ops::Mul for f32 { + type Output = Vec2; + fn mul(self, rhs: Dir2) -> Self::Output { + self * rhs.0 + } +} + #[cfg(feature = "approx")] impl approx::AbsDiffEq for Dir2 { type Epsilon = f32; @@ -261,6 +275,13 @@ impl std::ops::Mul for Dir3 { } } +impl std::ops::Mul for f32 { + type Output = Vec3; + fn mul(self, rhs: Dir3) -> Self::Output { + self * rhs.0 + } +} + impl std::ops::Mul for Quat { type Output = Dir3; @@ -408,6 +429,13 @@ impl std::ops::Mul for Dir3A { } } +impl std::ops::Mul for f32 { + type Output = Vec3A; + fn mul(self, rhs: Dir3A) -> Self::Output { + self * rhs.0 + } +} + impl std::ops::Mul for Quat { type Output = Dir3A; From de0ed293fa96643476ac98c5511a7c588e9b5ebb Mon Sep 17 00:00:00 2001 From: Kanabenki Date: Sun, 3 Mar 2024 19:50:46 +0100 Subject: [PATCH 012/124] Add basic light gizmos (#12228) # Objective - Part of #9400. - Add light gizmos for `SpotLight`, `PointLight` and `DirectionalLight`. ## Solution - Add a `ShowLightGizmo` and its related gizmo group and plugin, that shows a gizmo for all lights of an entities when inserted on it. Light display can also be toggled globally through the gizmo config in the same way it can already be done for `Aabb`s. - Add distinct segment setters for height and base one `Cone3dBuilder`. This allow having a properly rounded base without too much edges along the height. The doc comments explain how to ensure height and base connect when setting different values. Gizmo for the three light types without radius with the depth bias set to -1: ![without-radius](https://github.com/bevyengine/bevy/assets/18357657/699d0154-f367-4727-9b09-8b458d96a0e2) With Radius: ![with-radius](https://github.com/bevyengine/bevy/assets/18357657/f3af003e-dbba-427a-a305-c5cc1676e340) Possible future improvements: - Add a billboarded sprite with a distinct sprite for each light type. - Display the intensity of the light somehow (no idea how to represent that apart from some text). --- ## Changelog ### Added - The new `ShowLightGizmo`, part of the `LightGizmoPlugin` and configurable globally with `LightGizmoConfigGroup`, allows drawing gizmo for `PointLight`, `SpotLight` and `DirectionalLight`. The gizmos color behavior can be controlled with the `LightGizmoColor` member of `ShowLightGizmo` and `LightGizmoConfigGroup`. - The cone gizmo builder (`Cone3dBuilder`) now allows setting a differing number of segments for the base and height. --------- Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com> --- Cargo.toml | 11 + crates/bevy_gizmos/src/lib.rs | 6 +- crates/bevy_gizmos/src/light.rs | 324 ++++++++++++++++++++++ crates/bevy_gizmos/src/primitives/dim3.rs | 40 ++- examples/README.md | 1 + examples/gizmos/light_gizmos.rs | 190 +++++++++++++ 6 files changed, 563 insertions(+), 9 deletions(-) create mode 100644 crates/bevy_gizmos/src/light.rs create mode 100644 examples/gizmos/light_gizmos.rs diff --git a/Cargo.toml b/Cargo.toml index 03021605904ef..c146352a6d0c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2680,6 +2680,17 @@ description = "A scene showcasing 3D gizmos" category = "Gizmos" wasm = true +[[example]] +name = "light_gizmos" +path = "examples/gizmos/light_gizmos.rs" +doc-scrape-examples = true + +[package.metadata.example.light_gizmos] +name = "Light Gizmos" +description = "A scene showcasing light gizmos" +category = "Gizmos" +wasm = true + [profile.wasm-release] inherits = "release" opt-level = "z" diff --git a/crates/bevy_gizmos/src/lib.rs b/crates/bevy_gizmos/src/lib.rs index 93634e78c0aa7..134bfd15514fa 100644 --- a/crates/bevy_gizmos/src/lib.rs +++ b/crates/bevy_gizmos/src/lib.rs @@ -32,6 +32,7 @@ pub mod circles; pub mod config; pub mod gizmos; pub mod grid; +pub mod light; pub mod primitives; #[cfg(feature = "bevy_sprite")] @@ -46,6 +47,7 @@ pub mod prelude { aabb::{AabbGizmoConfigGroup, ShowAabbGizmo}, config::{DefaultGizmoConfigGroup, GizmoConfig, GizmoConfigGroup, GizmoConfigStore}, gizmos::Gizmos, + light::{LightGizmoColor, LightGizmoConfigGroup, ShowLightGizmo}, primitives::{dim2::GizmoPrimitive2d, dim3::GizmoPrimitive3d}, AppGizmoBuilder, }; @@ -85,6 +87,7 @@ use config::{ DefaultGizmoConfigGroup, GizmoConfig, GizmoConfigGroup, GizmoConfigStore, GizmoMeshConfig, }; use gizmos::GizmoStorage; +use light::LightGizmoPlugin; use std::{any::TypeId, mem}; const LINE_SHADER_HANDLE: Handle = Handle::weak_from_u128(7414812689238026784); @@ -110,7 +113,8 @@ impl Plugin for GizmoPlugin { .init_resource::() // We insert the Resource GizmoConfigStore into the world implicitly here if it does not exist. .init_gizmo_group::() - .add_plugins(AabbGizmoPlugin); + .add_plugins(AabbGizmoPlugin) + .add_plugins(LightGizmoPlugin); let Ok(render_app) = app.get_sub_app_mut(RenderApp) else { return; diff --git a/crates/bevy_gizmos/src/light.rs b/crates/bevy_gizmos/src/light.rs new file mode 100644 index 0000000000000..52d69a400cdbb --- /dev/null +++ b/crates/bevy_gizmos/src/light.rs @@ -0,0 +1,324 @@ +//! A module adding debug visualization of [`PointLight`]s, [`SpotLight`]s and [`DirectionalLight`]s. + +use std::f32::consts::PI; + +use crate::{self as bevy_gizmos, primitives::dim3::GizmoPrimitive3d}; + +use bevy_app::{Plugin, PostUpdate}; +use bevy_color::{ + palettes::basic::{BLUE, GREEN, RED}, + Color, Oklcha, +}; +use bevy_ecs::{ + component::Component, + entity::Entity, + query::Without, + reflect::ReflectComponent, + schedule::IntoSystemConfigs, + system::{Query, Res}, +}; +use bevy_math::{ + primitives::{Cone, Sphere}, + Quat, Vec3, +}; +use bevy_pbr::{DirectionalLight, PointLight, SpotLight}; +use bevy_reflect::{std_traits::ReflectDefault, Reflect}; +use bevy_transform::{components::GlobalTransform, TransformSystem}; + +use crate::{ + config::{GizmoConfigGroup, GizmoConfigStore}, + gizmos::Gizmos, + AppGizmoBuilder, +}; + +/// Draws a standard sphere for the radius and an axis sphere for the range. +fn point_light_gizmo( + transform: &GlobalTransform, + point_light: &PointLight, + color: Color, + gizmos: &mut Gizmos, +) { + let position = transform.translation(); + gizmos + .primitive_3d( + Sphere { + radius: point_light.radius, + }, + position, + Quat::IDENTITY, + color, + ) + .segments(16); + gizmos + .sphere(position, Quat::IDENTITY, point_light.range, color) + .circle_segments(32); +} + +/// Draws a sphere for the radius, two cones for the inner and outer angles, plus two 3d arcs crossing the +/// farthest point of effect of the spot light along its direction. +fn spot_light_gizmo( + transform: &GlobalTransform, + spot_light: &SpotLight, + color: Color, + gizmos: &mut Gizmos, +) { + let (_, rotation, translation) = transform.to_scale_rotation_translation(); + gizmos + .primitive_3d( + Sphere { + radius: spot_light.radius, + }, + translation, + Quat::IDENTITY, + color, + ) + .segments(16); + + // Offset the tip of the cone to the light position. + for angle in [spot_light.inner_angle, spot_light.outer_angle] { + let height = spot_light.range * angle.cos(); + let position = translation + rotation * Vec3::NEG_Z * height / 2.0; + gizmos + .primitive_3d( + Cone { + radius: spot_light.range * angle.sin(), + height, + }, + position, + rotation * Quat::from_rotation_x(PI / 2.0), + color, + ) + .height_segments(4) + .base_segments(32); + } + + for arc_rotation in [ + Quat::from_rotation_y(PI / 2.0 - spot_light.outer_angle), + Quat::from_euler( + bevy_math::EulerRot::XZY, + 0.0, + PI / 2.0, + PI / 2.0 - spot_light.outer_angle, + ), + ] { + gizmos + .arc_3d( + 2.0 * spot_light.outer_angle, + spot_light.range, + translation, + rotation * arc_rotation, + color, + ) + .segments(16); + } +} + +/// Draws an arrow alongside the directional light direction. +fn directional_light_gizmo( + transform: &GlobalTransform, + color: Color, + gizmos: &mut Gizmos, +) { + let (_, rotation, translation) = transform.to_scale_rotation_translation(); + gizmos + .arrow(translation, translation + rotation * Vec3::NEG_Z, color) + .with_tip_length(0.3); +} + +/// A [`Plugin`] that provides visualization of [`PointLight`]s, [`SpotLight`]s +/// and [`DirectionalLight`]s for debugging. +pub struct LightGizmoPlugin; + +impl Plugin for LightGizmoPlugin { + fn build(&self, app: &mut bevy_app::App) { + app.register_type::() + .init_gizmo_group::() + .add_systems( + PostUpdate, + ( + draw_lights, + draw_all_lights.run_if(|config: Res| { + config.config::().1.draw_all + }), + ) + .after(TransformSystem::TransformPropagate), + ); + } +} + +/// Configures how a color is attributed to a light gizmo. +#[derive(Debug, Clone, Copy, Default, Reflect)] +pub enum LightGizmoColor { + /// User-specified color. + Manual(Color), + /// Random color derived from the light's [`Entity`]. + Varied, + /// Take the color of the represented light. + #[default] + MatchLightColor, + /// Take the color provided by [`LightGizmoConfigGroup`] depending on the light kind. + ByLightType, +} + +/// The [`GizmoConfigGroup`] used to configure the visualization of lights. +#[derive(Clone, Reflect, GizmoConfigGroup)] +pub struct LightGizmoConfigGroup { + /// Draw a gizmo for all lights if true. + /// + /// Defaults to `false`. + pub draw_all: bool, + /// Default color strategy for all light gizmos. + /// + /// Defaults to [`LightGizmoColor::MatchLightColor`]. + pub color: LightGizmoColor, + /// [`Color`] to use for drawing a [`PointLight`] gizmo when [`LightGizmoColor::ByLightType`] is used. + /// + /// Defaults to [`RED`]. + pub point_light_color: Color, + /// [`Color`] to use for drawing a [`SpotLight`] gizmo when [`LightGizmoColor::ByLightType`] is used. + /// + /// Defaults to [`GREEN`]. + pub spot_light_color: Color, + /// [`Color`] to use for drawing a [`DirectionalLight`] gizmo when [`LightGizmoColor::ByLightType`] is used. + /// + /// Defaults to [`BLUE`]. + pub directional_light_color: Color, +} + +impl Default for LightGizmoConfigGroup { + fn default() -> Self { + Self { + draw_all: false, + color: LightGizmoColor::MatchLightColor, + point_light_color: RED.into(), + spot_light_color: GREEN.into(), + directional_light_color: BLUE.into(), + } + } +} + +/// Add this [`Component`] to an entity to draw any of its lights components +/// ([`PointLight`], [`SpotLight`] and [`DirectionalLight`]). +#[derive(Component, Reflect, Default, Debug)] +#[reflect(Component, Default)] +pub struct ShowLightGizmo { + /// Default color strategy for this light gizmo. if [`None`], use the one provided by [`LightGizmoConfigGroup`]. + /// + /// Defaults to [`None`]. + pub color: Option, +} + +fn draw_lights( + point_query: Query<(Entity, &PointLight, &GlobalTransform, &ShowLightGizmo)>, + spot_query: Query<(Entity, &SpotLight, &GlobalTransform, &ShowLightGizmo)>, + directional_query: Query<(Entity, &DirectionalLight, &GlobalTransform, &ShowLightGizmo)>, + mut gizmos: Gizmos, +) { + let color = |entity: Entity, gizmo_color: Option, light_color, type_color| { + match gizmo_color.unwrap_or(gizmos.config_ext.color) { + LightGizmoColor::Manual(color) => color, + LightGizmoColor::Varied => Oklcha::sequential_dispersed(entity.index()).into(), + LightGizmoColor::MatchLightColor => light_color, + LightGizmoColor::ByLightType => type_color, + } + }; + for (entity, light, transform, light_gizmo) in &point_query { + let color = color( + entity, + light_gizmo.color, + light.color, + gizmos.config_ext.point_light_color, + ); + point_light_gizmo(transform, light, color, &mut gizmos); + } + for (entity, light, transform, light_gizmo) in &spot_query { + let color = color( + entity, + light_gizmo.color, + light.color, + gizmos.config_ext.spot_light_color, + ); + spot_light_gizmo(transform, light, color, &mut gizmos); + } + for (entity, light, transform, light_gizmo) in &directional_query { + let color = color( + entity, + light_gizmo.color, + light.color, + gizmos.config_ext.directional_light_color, + ); + directional_light_gizmo(transform, color, &mut gizmos); + } +} + +fn draw_all_lights( + point_query: Query<(Entity, &PointLight, &GlobalTransform), Without>, + spot_query: Query<(Entity, &SpotLight, &GlobalTransform), Without>, + directional_query: Query< + (Entity, &DirectionalLight, &GlobalTransform), + Without, + >, + mut gizmos: Gizmos, +) { + match gizmos.config_ext.color { + LightGizmoColor::Manual(color) => { + for (_, light, transform) in &point_query { + point_light_gizmo(transform, light, color, &mut gizmos); + } + for (_, light, transform) in &spot_query { + spot_light_gizmo(transform, light, color, &mut gizmos); + } + for (_, _, transform) in &directional_query { + directional_light_gizmo(transform, color, &mut gizmos); + } + } + LightGizmoColor::Varied => { + let color = |entity: Entity| Oklcha::sequential_dispersed(entity.index()).into(); + for (entity, light, transform) in &point_query { + point_light_gizmo(transform, light, color(entity), &mut gizmos); + } + for (entity, light, transform) in &spot_query { + spot_light_gizmo(transform, light, color(entity), &mut gizmos); + } + for (entity, _, transform) in &directional_query { + directional_light_gizmo(transform, color(entity), &mut gizmos); + } + } + LightGizmoColor::MatchLightColor => { + for (_, light, transform) in &point_query { + point_light_gizmo(transform, light, light.color, &mut gizmos); + } + for (_, light, transform) in &spot_query { + spot_light_gizmo(transform, light, light.color, &mut gizmos); + } + for (_, light, transform) in &directional_query { + directional_light_gizmo(transform, light.color, &mut gizmos); + } + } + LightGizmoColor::ByLightType => { + for (_, light, transform) in &point_query { + point_light_gizmo( + transform, + light, + gizmos.config_ext.point_light_color, + &mut gizmos, + ); + } + for (_, light, transform) in &spot_query { + spot_light_gizmo( + transform, + light, + gizmos.config_ext.spot_light_color, + &mut gizmos, + ); + } + for (_, _, transform) in &directional_query { + directional_light_gizmo( + transform, + gizmos.config_ext.directional_light_color, + &mut gizmos, + ); + } + } + } +} diff --git a/crates/bevy_gizmos/src/primitives/dim3.rs b/crates/bevy_gizmos/src/primitives/dim3.rs index 6359517a68f66..eae53b1fcf3b4 100644 --- a/crates/bevy_gizmos/src/primitives/dim3.rs +++ b/crates/bevy_gizmos/src/primitives/dim3.rs @@ -609,14 +609,36 @@ pub struct Cone3dBuilder<'a, 'w, 's, T: GizmoConfigGroup> { // Color of the cone color: Color, - // Number of segments used to approximate the cone geometry - segments: usize, + // Number of segments used to approximate the cone base geometry + base_segments: usize, + + // Number of segments used to approximate the cone height geometry + height_segments: usize, } impl Cone3dBuilder<'_, '_, '_, T> { - /// Set the number of segments used to approximate the cone geometry. + /// Set the number of segments used to approximate the cone geometry for its base and height. pub fn segments(mut self, segments: usize) -> Self { - self.segments = segments; + self.base_segments = segments; + self.height_segments = segments; + self + } + + /// Set the number of segments to approximate the height of the cone geometry. + /// + /// `segments` should be a multiple of the value passed to [`Self::height_segments`] + /// for the height to connect properly with the base. + pub fn base_segments(mut self, segments: usize) -> Self { + self.base_segments = segments; + self + } + + /// Set the number of segments to approximate the height of the cone geometry. + /// + /// `segments` should be a divisor of the value passed to [`Self::base_segments`] + /// for the height to connect properly with the base. + pub fn height_segments(mut self, segments: usize) -> Self { + self.height_segments = segments; self } } @@ -638,7 +660,8 @@ impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d for Gizmos<'w, 's, T> { position, rotation, color, - segments: DEFAULT_NUMBER_SEGMENTS, + base_segments: DEFAULT_NUMBER_SEGMENTS, + height_segments: DEFAULT_NUMBER_SEGMENTS, } } } @@ -656,7 +679,8 @@ impl Drop for Cone3dBuilder<'_, '_, '_, T> { position, rotation, color, - segments, + base_segments, + height_segments, } = self; let half_height = *height * 0.5; @@ -665,7 +689,7 @@ impl Drop for Cone3dBuilder<'_, '_, '_, T> { draw_circle_3d( gizmos, *radius, - *segments, + *base_segments, *rotation, *position - *rotation * Vec3::Y * half_height, *color, @@ -673,7 +697,7 @@ impl Drop for Cone3dBuilder<'_, '_, '_, T> { // connect the base circle with the tip of the cone let end = Vec3::Y * half_height; - circle_coordinates(*radius, *segments) + circle_coordinates(*radius, *height_segments) .map(|p| Vec3::new(p.x, -half_height, p.y)) .map(move |p| [p, end]) .map(|ps| ps.map(rotate_then_translate_3d(*rotation, *position))) diff --git a/examples/README.md b/examples/README.md index 9d534101bce7d..9354b362901b2 100644 --- a/examples/README.md +++ b/examples/README.md @@ -266,6 +266,7 @@ Example | Description --- | --- [2D Gizmos](../examples/gizmos/2d_gizmos.rs) | A scene showcasing 2D gizmos [3D Gizmos](../examples/gizmos/3d_gizmos.rs) | A scene showcasing 3D gizmos +[Light Gizmos](../examples/gizmos/light_gizmos.rs) | A scene showcasing light gizmos ## Input diff --git a/examples/gizmos/light_gizmos.rs b/examples/gizmos/light_gizmos.rs new file mode 100644 index 0000000000000..e06b6c0e8dedd --- /dev/null +++ b/examples/gizmos/light_gizmos.rs @@ -0,0 +1,190 @@ +//! This example demonstrates how to visualize lights properties through the gizmo API. + +use std::f32::consts::{FRAC_PI_2, PI}; + +use bevy::{ + color::palettes::css::{DARK_CYAN, GOLD, GRAY, PURPLE}, + gizmos::light::{LightGizmoColor, LightGizmoConfigGroup}, + prelude::*, +}; + +fn main() { + App::new() + .add_plugins(DefaultPlugins) + .add_systems(Startup, setup) + .add_systems(Update, rotate_camera) + .add_systems(Update, update_config) + .run(); +} + +#[derive(Component)] +struct GizmoColorText; + +fn gizmo_color_text(config: &LightGizmoConfigGroup) -> String { + match config.color { + LightGizmoColor::Manual(color) => format!("Manual {}", Srgba::from(color).to_hex()), + LightGizmoColor::Varied => "Random from entity".to_owned(), + LightGizmoColor::MatchLightColor => "Match light color".to_owned(), + LightGizmoColor::ByLightType => { + format!( + "Point {}, Spot {}, Directional {}", + Srgba::from(config.point_light_color).to_hex(), + Srgba::from(config.spot_light_color).to_hex(), + Srgba::from(config.directional_light_color).to_hex() + ) + } + } +} + +fn setup( + mut commands: Commands, + mut meshes: ResMut>, + mut materials: ResMut>, + mut config_store: ResMut, +) { + // Circular base. + commands.spawn(PbrBundle { + mesh: meshes.add(Circle::new(4.0)), + material: materials.add(Color::WHITE), + transform: Transform::from_rotation(Quat::from_rotation_x(-FRAC_PI_2)), + ..default() + }); + + // Cubes. + { + let mesh = meshes.add(Cuboid::new(1.0, 1.0, 1.0)); + let material = materials.add(Color::srgb_u8(124, 144, 255)); + for x in [-2.0, 0.0, 2.0] { + commands.spawn(PbrBundle { + mesh: mesh.clone(), + material: material.clone(), + transform: Transform::from_xyz(x, 0.5, 0.0), + ..default() + }); + } + } + + // Lights. + { + commands.spawn(PointLightBundle { + point_light: PointLight { + shadows_enabled: true, + range: 2.0, + color: DARK_CYAN.into(), + ..default() + }, + transform: Transform::from_xyz(0.0, 1.5, 0.0), + ..default() + }); + commands.spawn(SpotLightBundle { + spot_light: SpotLight { + shadows_enabled: true, + range: 3.5, + color: PURPLE.into(), + outer_angle: PI / 4.0, + inner_angle: PI / 4.0 * 0.8, + ..default() + }, + transform: Transform::from_xyz(4.0, 2.0, 0.0).looking_at(Vec3::X * 1.5, Vec3::Y), + ..default() + }); + commands.spawn(DirectionalLightBundle { + directional_light: DirectionalLight { + color: GOLD.into(), + illuminance: DirectionalLight::default().illuminance * 0.05, + shadows_enabled: true, + ..default() + }, + transform: Transform::from_xyz(-4.0, 2.0, 0.0).looking_at(Vec3::NEG_X * 1.5, Vec3::Y), + ..default() + }); + } + + // Camera. + commands.spawn(Camera3dBundle { + transform: Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y), + ..default() + }); + + // Example instructions and gizmo config. + { + let text_style = TextStyle { + font_size: 20.0, + ..default() + }; + commands.spawn( + TextBundle::from_section( + "Press 'D' to toggle drawing gizmos on top of everything else in the scene\n\ + Hold 'Left' or 'Right' to change the line width of the gizmos\n\ + Press 'A' to toggle drawing of the light gizmos\n\ + Press 'C' to cycle between the light gizmos coloring modes", + text_style.clone(), + ) + .with_style(Style { + position_type: PositionType::Absolute, + top: Val::Px(12.0), + left: Val::Px(12.0), + ..default() + }), + ); + + let (_, light_config) = config_store.config_mut::(); + light_config.draw_all = true; + light_config.color = LightGizmoColor::MatchLightColor; + + commands.spawn(( + TextBundle::from_sections([ + TextSection::new("Gizmo color mode: ", text_style.clone()), + TextSection::new(gizmo_color_text(light_config), text_style), + ]) + .with_style(Style { + position_type: PositionType::Absolute, + bottom: Val::Px(12.0), + left: Val::Px(12.0), + ..default() + }), + GizmoColorText, + )); + } +} + +fn rotate_camera(mut query: Query<&mut Transform, With>, time: Res