diff --git a/Cargo.toml b/Cargo.toml index 667ded884e219..05ca30f4aae61 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -155,6 +155,9 @@ bevy_winit = ["bevy_internal/bevy_winit"] # Adds support for rendering gizmos bevy_gizmos = ["bevy_internal/bevy_gizmos", "bevy_color"] +# Provides a collection of developer tools +bevy_dev_tools = ["bevy_internal/bevy_dev_tools"] + # Tracing support, saving a file in Chrome Tracing format trace_chrome = ["trace", "bevy_internal/trace_chrome"] @@ -321,6 +324,9 @@ bevy_debug_stepping = ["bevy_internal/bevy_debug_stepping"] # Enables processing meshes into meshlet meshes for bevy_pbr meshlet_processor = ["bevy_internal/meshlet_processor"] +# Enable support for the ios_simulator by downgrading some rendering capabilities +ios_simulator = ["bevy_internal/ios_simulator"] + [dependencies] bevy_dylib = { path = "crates/bevy_dylib", version = "0.14.0-dev", default-features = false, optional = true } bevy_internal = { path = "crates/bevy_internal", version = "0.14.0-dev", default-features = false } @@ -1251,6 +1257,17 @@ description = "Embed an asset in the application binary and load it" category = "Assets" wasm = true +[[example]] +name = "extra_asset_source" +path = "examples/asset/extra_source.rs" +doc-scrape-examples = true + +[package.metadata.example.extra_asset_source] +name = "Extra asset source" +description = "Load an asset from a non-standard asset source" +category = "Assets" +wasm = true + [[example]] name = "hot_asset_reloading" path = "examples/asset/hot_asset_reloading.rs" @@ -1702,6 +1719,17 @@ description = "Displays each contributor as a bouncy bevy-ball!" category = "Games" wasm = true +[[example]] +name = "desk_toy" +path = "examples/games/desk_toy.rs" +doc-scrape-examples = true + +[package.metadata.example.desk_toy] +name = "Desk Toy" +description = "Bevy logo as a desk toy using transparent windows! Now with Googly Eyes!" +category = "Games" +wasm = false + [[example]] name = "game_menu" path = "examples/games/game_menu.rs" diff --git a/crates/bevy_animation/src/lib.rs b/crates/bevy_animation/src/lib.rs index 67d1ec924b2a5..c420e8d98abc5 100644 --- a/crates/bevy_animation/src/lib.rs +++ b/crates/bevy_animation/src/lib.rs @@ -687,10 +687,6 @@ impl Plugin for AnimationPlugin { app.init_asset::() .register_asset_reflect::() .register_type::() - .register_type::() - .register_type::>() - .register_type::() - .register_type::() .register_type::() .add_systems( PostUpdate, diff --git a/crates/bevy_app/Cargo.toml b/crates/bevy_app/Cargo.toml index 020245b6449dc..e42d986f1a669 100644 --- a/crates/bevy_app/Cargo.toml +++ b/crates/bevy_app/Cargo.toml @@ -10,7 +10,6 @@ keywords = ["bevy"] [features] trace = [] -bevy_ci_testing = ["serde", "ron"] bevy_debug_stepping = [] default = ["bevy_reflect", "bevy_debug_stepping"] bevy_reflect = ["dep:bevy_reflect", "bevy_ecs/bevy_reflect"] diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index f08a3e73bd788..f339b5d8002f5 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -188,11 +188,6 @@ impl Default for App { app.add_event::(); - #[cfg(feature = "bevy_ci_testing")] - { - crate::ci_testing::setup_app(&mut app); - } - app } } diff --git a/crates/bevy_app/src/lib.rs b/crates/bevy_app/src/lib.rs index 8f6ba7972f272..721cf1618a724 100644 --- a/crates/bevy_app/src/lib.rs +++ b/crates/bevy_app/src/lib.rs @@ -6,9 +6,6 @@ mod plugin; mod plugin_group; mod schedule_runner; -#[cfg(feature = "bevy_ci_testing")] -pub mod ci_testing; - pub use app::*; pub use bevy_derive::DynamicPlugin; pub use main_schedule::*; diff --git a/crates/bevy_asset/src/lib.rs b/crates/bevy_asset/src/lib.rs index d5789d4a54277..803f76c6e3590 100644 --- a/crates/bevy_asset/src/lib.rs +++ b/crates/bevy_asset/src/lib.rs @@ -378,7 +378,6 @@ impl AssetApp for App { .add_event::>() .add_event::>() .register_type::>() - .register_type::>() .add_systems( First, Assets::::asset_events diff --git a/crates/bevy_core/Cargo.toml b/crates/bevy_core/Cargo.toml index 5a9ab295991cf..cd769fcb0f36f 100644 --- a/crates/bevy_core/Cargo.toml +++ b/crates/bevy_core/Cargo.toml @@ -17,7 +17,6 @@ bevy_app = { path = "../bevy_app", version = "0.14.0-dev", features = [ bevy_ecs = { path = "../bevy_ecs", version = "0.14.0-dev", features = [ "bevy_reflect", ] } -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_core/src/lib.rs b/crates/bevy_core/src/lib.rs index 7cf8da08b6809..3dc709a15e05d 100644 --- a/crates/bevy_core/src/lib.rs +++ b/crates/bevy_core/src/lib.rs @@ -19,17 +19,9 @@ pub mod prelude { } use bevy_app::prelude::*; -use bevy_ecs::component::{ComponentId, ComponentTicks, Tick}; use bevy_ecs::prelude::*; -use bevy_reflect::{ReflectDeserialize, ReflectSerialize}; -use bevy_utils::{Duration, HashSet, Instant, Uuid}; -use std::borrow::Cow; -use std::ffi::OsString; use std::marker::PhantomData; -use std::ops::Range; -use std::path::{Path, PathBuf}; -#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))] use bevy_tasks::tick_global_task_pools_on_main_thread; @@ -40,78 +32,9 @@ pub struct TypeRegistrationPlugin; impl Plugin for TypeRegistrationPlugin { fn build(&self, app: &mut App) { app.register_type::(); - - register_ecs_types(app); - register_rust_types(app); - register_math_types(app); } } -fn register_ecs_types(app: &mut App) { - app.register_type::() - .register_type::() - .register_type::() - .register_type::(); -} - -fn register_rust_types(app: &mut App) { - app.register_type::>() - .register_type_data::, ReflectSerialize>() - .register_type_data::, ReflectDeserialize>() - .register_type::() - .register_type::() - .register_type::() - .register_type::>() - .register_type::>() - .register_type::>() - .register_type::>() - .register_type::>() - .register_type::>() - .register_type::>() - .register_type::>() - .register_type::() - .register_type::() - .register_type::(); -} - -fn register_math_types(app: &mut App) { - app.register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::>() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::>() - .register_type::>(); -} - /// Setup of default task pools: [`AsyncComputeTaskPool`](bevy_tasks::AsyncComputeTaskPool), /// [`ComputeTaskPool`](bevy_tasks::ComputeTaskPool), [`IoTaskPool`](bevy_tasks::IoTaskPool). #[derive(Default)] diff --git a/crates/bevy_core_pipeline/src/core_3d/mod.rs b/crates/bevy_core_pipeline/src/core_3d/mod.rs index ece71016219d0..c796d32825b8e 100644 --- a/crates/bevy_core_pipeline/src/core_3d/mod.rs +++ b/crates/bevy_core_pipeline/src/core_3d/mod.rs @@ -93,8 +93,6 @@ pub struct Core3dPlugin; impl Plugin for Core3dPlugin { fn build(&self, app: &mut App) { app.register_type::() - .register_type::() - .register_type::() .register_type::() .add_plugins((SkyboxPlugin, ExtractComponentPlugin::::default())) .add_systems(PostUpdate, check_msaa); diff --git a/crates/bevy_core_pipeline/src/fxaa/mod.rs b/crates/bevy_core_pipeline/src/fxaa/mod.rs index bae09b4467c15..f1442910850eb 100644 --- a/crates/bevy_core_pipeline/src/fxaa/mod.rs +++ b/crates/bevy_core_pipeline/src/fxaa/mod.rs @@ -86,7 +86,7 @@ impl Plugin for FxaaPlugin { fn build(&self, app: &mut App) { load_internal_asset!(app, FXAA_SHADER_HANDLE, "fxaa.wgsl", Shader::from_wgsl); - app.register_type::().register_type::(); + app.register_type::(); app.add_plugins(ExtractComponentPlugin::::default()); let Ok(render_app) = app.get_sub_app_mut(RenderApp) else { diff --git a/crates/bevy_dev_tools/Cargo.toml b/crates/bevy_dev_tools/Cargo.toml new file mode 100644 index 0000000000000..eb6597d8bd7ff --- /dev/null +++ b/crates/bevy_dev_tools/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "bevy_dev_tools" +version = "0.14.0-dev" +edition = "2021" +description = "Collection of developer tools for the Bevy Engine" +homepage = "https://bevyengine.org" +repository = "https://github.com/bevyengine/bevy" +license = "MIT OR Apache-2.0" +keywords = ["bevy"] + +[features] +bevy_ci_testing = ["serde", "ron"] + +[dependencies] +# bevy +bevy_app = { path = "../bevy_app", version = "0.14.0-dev" } +bevy_utils = { path = "../bevy_utils", version = "0.14.0-dev" } +bevy_ecs = { path = "../bevy_ecs", version = "0.14.0-dev" } + +# other +serde = { version = "1.0", features = ["derive"], optional = true } +ron = { version = "0.8.0", optional = true } + +[lints] +workspace = true diff --git a/crates/bevy_app/src/ci_testing.rs b/crates/bevy_dev_tools/src/ci_testing.rs similarity index 98% rename from crates/bevy_app/src/ci_testing.rs rename to crates/bevy_dev_tools/src/ci_testing.rs index 3ba0dde78e307..db2d4a14fc70e 100644 --- a/crates/bevy_app/src/ci_testing.rs +++ b/crates/bevy_dev_tools/src/ci_testing.rs @@ -1,6 +1,6 @@ //! Utilities for testing in CI environments. -use crate::{app::AppExit, App, Update}; +use bevy_app::{App, AppExit, Update}; use serde::Deserialize; use bevy_ecs::prelude::Resource; diff --git a/crates/bevy_dev_tools/src/lib.rs b/crates/bevy_dev_tools/src/lib.rs new file mode 100644 index 0000000000000..b025539ebbb57 --- /dev/null +++ b/crates/bevy_dev_tools/src/lib.rs @@ -0,0 +1,44 @@ +//! This crate provides additional utilities for the [Bevy game engine](https://bevyengine.org), +//! focused on improving developer experience. + +use bevy_app::prelude::*; +#[cfg(feature = "bevy_ci_testing")] +pub mod ci_testing; + +/// Enables developer tools in an [`App`]. This plugin is added automatically with `bevy_dev_tools` +/// feature. +/// +/// Warning: It is not recommended to enable this in final shipped games or applications. +/// Dev tools provide a high level of access to the internals of your application, +/// and may interfere with ordinary use and gameplay. +/// +/// To enable developer tools, you can either: +/// +/// - Create a custom crate feature (e.g "`dev_mode`"), which enables the `bevy_dev_tools` feature +/// along with any other development tools you might be using: +/// +/// ```toml +/// [feature] +/// dev_mode = ["bevy/bevy_dev_tools", "other_dev_tools"] +/// ``` +/// +/// - Use `--feature bevy/bevy_dev_tools` flag when using the `cargo run` command: +/// +/// `cargo run --features bevy/bevy_dev_tools` +/// +/// - Add the `bevy_dev_tools` feature to the bevy dependency in your `Cargo.toml` file: +/// +/// `features = ["bevy_dev_tools"]` +/// +/// Note: The third method is not recommended, as it requires you to remove the feature before +/// creating a build for release to the public. +pub struct DevToolsPlugin; + +impl Plugin for DevToolsPlugin { + fn build(&self, _app: &mut App) { + #[cfg(feature = "bevy_ci_testing")] + { + ci_testing::setup_app(_app); + } + } +} diff --git a/crates/bevy_ecs/src/bundle.rs b/crates/bevy_ecs/src/bundle.rs index f5e9a32fd0614..f3d42a66ef29b 100644 --- a/crates/bevy_ecs/src/bundle.rs +++ b/crates/bevy_ecs/src/bundle.rs @@ -15,11 +15,12 @@ use crate::{ prelude::World, query::DebugCheckedUnwrap, storage::{SparseSetIndex, SparseSets, Storages, Table, TableRow}, - world::{unsafe_world_cell::UnsafeWorldCell, DeferredWorld}, + world::unsafe_world_cell::UnsafeWorldCell, }; -use bevy_ptr::OwningPtr; +use bevy_ptr::{ConstNonNull, OwningPtr}; use bevy_utils::all_tuples; use std::any::TypeId; +use std::ptr::NonNull; /// The `Bundle` trait enables insertion and removal of [`Component`]s from an entity. /// @@ -510,10 +511,10 @@ impl BundleInfo { // SAFETY: We have exclusive world access so our pointers can't be invalidated externally pub(crate) struct BundleInserter<'w> { world: UnsafeWorldCell<'w>, - bundle_info: *const BundleInfo, - add_bundle: *const AddBundle, - table: *mut Table, - archetype: *mut Archetype, + bundle_info: ConstNonNull, + add_bundle: ConstNonNull, + table: NonNull, + archetype: NonNull, result: InsertBundleResult, change_tick: Tick, } @@ -521,11 +522,11 @@ pub(crate) struct BundleInserter<'w> { pub(crate) enum InsertBundleResult { SameArchetype, NewArchetypeSameTable { - new_archetype: *mut Archetype, + new_archetype: NonNull, }, NewArchetypeNewTable { - new_archetype: *mut Archetype, - new_table: *mut Table, + new_archetype: NonNull, + new_table: NonNull
, }, } @@ -546,7 +547,7 @@ impl<'w> BundleInserter<'w> { /// Creates a new [`BundleInserter`]. /// /// # Safety - /// Caller must ensure that `bundle_id` exists in `world.bundles` + /// - Caller must ensure that `bundle_id` exists in `world.bundles`. #[inline] pub(crate) unsafe fn new_with_id( world: &'w mut World, @@ -575,10 +576,10 @@ impl<'w> BundleInserter<'w> { let table_id = archetype.table_id(); let table = &mut world.storages.tables[table_id]; Self { - add_bundle, - archetype, - bundle_info, - table, + add_bundle: add_bundle.into(), + archetype: archetype.into(), + bundle_info: bundle_info.into(), + table: table.into(), result: InsertBundleResult::SameArchetype, change_tick, world: world.as_unsafe_world_cell(), @@ -598,24 +599,26 @@ impl<'w> BundleInserter<'w> { if table_id == new_table_id { let table = &mut world.storages.tables[table_id]; Self { - add_bundle, - archetype, - bundle_info, - table, - result: InsertBundleResult::NewArchetypeSameTable { new_archetype }, + add_bundle: add_bundle.into(), + archetype: archetype.into(), + bundle_info: bundle_info.into(), + table: table.into(), + result: InsertBundleResult::NewArchetypeSameTable { + new_archetype: new_archetype.into(), + }, change_tick, world: world.as_unsafe_world_cell(), } } else { let (table, new_table) = world.storages.tables.get_2_mut(table_id, new_table_id); Self { - add_bundle, - archetype, - bundle_info, - table, + add_bundle: add_bundle.into(), + archetype: archetype.into(), + bundle_info: bundle_info.into(), + table: table.into(), result: InsertBundleResult::NewArchetypeNewTable { - new_archetype, - new_table, + new_archetype: new_archetype.into(), + new_table: new_table.into(), }, change_tick, world: world.as_unsafe_world_cell(), @@ -623,6 +626,7 @@ impl<'w> BundleInserter<'w> { } } } + /// # Safety /// `entity` must currently exist in the source archetype for this inserter. `location` /// must be `entity`'s location in the archetype. `T` must match this [`BundleInfo`]'s type @@ -633,191 +637,174 @@ impl<'w> BundleInserter<'w> { location: EntityLocation, bundle: T, ) -> EntityLocation { - // SAFETY: We do not make any structural changes to the archetype graph through self.world so these pointers always remain valid - let trigger_hooks = |archetype: &Archetype, mut world: DeferredWorld| { - let bundle_info = &*self.bundle_info; - let add_bundle = &*self.add_bundle; + let bundle_info = self.bundle_info.as_ref(); + let add_bundle = self.add_bundle.as_ref(); + let table = self.table.as_mut(); + let archetype = self.archetype.as_mut(); + + let (new_archetype, new_location) = match &mut self.result { + InsertBundleResult::SameArchetype => { + // SAFETY: Mutable references do not alias and will be dropped after this block + let sparse_sets = { + let world = self.world.world_mut(); + &mut world.storages.sparse_sets + }; - if archetype.has_on_add() { - world.trigger_on_add( + bundle_info.write_components( + table, + sparse_sets, + add_bundle, entity, - bundle_info - .iter_components() - .zip(add_bundle.bundle_status.iter()) - .filter(|(_, &status)| status == ComponentStatus::Added) - .map(|(id, _)| id), + location.table_row, + self.change_tick, + bundle, ); - } - if archetype.has_on_insert() { - world.trigger_on_insert(entity, bundle_info.iter_components()); - } - }; - match &mut self.result { - InsertBundleResult::SameArchetype => { - { - // SAFETY: Mutable references do not alias and will be dropped after this block - let sparse_sets = { - let world = self.world.world_mut(); - &mut world.storages.sparse_sets - }; - let table = &mut *self.table; - let bundle_info = &*self.bundle_info; - let add_bundle = &*self.add_bundle; - - bundle_info.write_components( - table, - sparse_sets, - add_bundle, - entity, - location.table_row, - self.change_tick, - bundle, - ); - } - // SAFETY: We have no outstanding mutable references to world as they were dropped - unsafe { - let archetype = &*self.archetype; - trigger_hooks(archetype, self.world.into_deferred()); - } - location + + (archetype, location) } InsertBundleResult::NewArchetypeSameTable { new_archetype } => { - let new_location = { - // SAFETY: Mutable references do not alias and will be dropped after this block - let (sparse_sets, entities) = { - let world = self.world.world_mut(); - (&mut world.storages.sparse_sets, &mut world.entities) - }; - let table = &mut *self.table; - let archetype = &mut *self.archetype; - let new_archetype = &mut **new_archetype; - - let result = archetype.swap_remove(location.archetype_row); - if let Some(swapped_entity) = result.swapped_entity { - let swapped_location = - // SAFETY: If the swap was successful, swapped_entity must be valid. - unsafe { entities.get(swapped_entity).debug_checked_unwrap() }; - entities.set( - swapped_entity.index(), - EntityLocation { - archetype_id: swapped_location.archetype_id, - archetype_row: location.archetype_row, - table_id: swapped_location.table_id, - table_row: swapped_location.table_row, - }, - ); - } - let new_location = new_archetype.allocate(entity, result.table_row); - entities.set(entity.index(), new_location); - - let bundle_info = &*self.bundle_info; - let add_bundle = &*self.add_bundle; - bundle_info.write_components( - table, - sparse_sets, - add_bundle, - entity, - result.table_row, - self.change_tick, - bundle, - ); - new_location + let new_archetype = new_archetype.as_mut(); + + // SAFETY: Mutable references do not alias and will be dropped after this block + let (sparse_sets, entities) = { + let world = self.world.world_mut(); + (&mut world.storages.sparse_sets, &mut world.entities) }; - // SAFETY: We have no outstanding mutable references to world as they were dropped - unsafe { trigger_hooks(&**new_archetype, self.world.into_deferred()) }; + let result = archetype.swap_remove(location.archetype_row); + if let Some(swapped_entity) = result.swapped_entity { + let swapped_location = + // SAFETY: If the swap was successful, swapped_entity must be valid. + unsafe { entities.get(swapped_entity).debug_checked_unwrap() }; + entities.set( + swapped_entity.index(), + EntityLocation { + archetype_id: swapped_location.archetype_id, + archetype_row: location.archetype_row, + table_id: swapped_location.table_id, + table_row: swapped_location.table_row, + }, + ); + } + let new_location = new_archetype.allocate(entity, result.table_row); + entities.set(entity.index(), new_location); + bundle_info.write_components( + table, + sparse_sets, + add_bundle, + entity, + result.table_row, + self.change_tick, + bundle, + ); - new_location + (new_archetype, new_location) } InsertBundleResult::NewArchetypeNewTable { new_archetype, new_table, } => { - let new_location = { - // SAFETY: Mutable references do not alias and will be dropped after this block - let (archetypes_ptr, sparse_sets, entities) = { - let world = self.world.world_mut(); - let archetype_ptr: *mut Archetype = - world.archetypes.archetypes.as_mut_ptr(); - ( - archetype_ptr, - &mut world.storages.sparse_sets, - &mut world.entities, - ) - }; - let table = &mut *self.table; - let new_table = &mut **new_table; - let archetype = &mut *self.archetype; - let new_archetype = &mut **new_archetype; - let result = archetype.swap_remove(location.archetype_row); - if let Some(swapped_entity) = result.swapped_entity { - let swapped_location = - // SAFETY: If the swap was successful, swapped_entity must be valid. - unsafe { entities.get(swapped_entity).debug_checked_unwrap() }; - entities.set( - swapped_entity.index(), - EntityLocation { - archetype_id: swapped_location.archetype_id, - archetype_row: location.archetype_row, - table_id: swapped_location.table_id, - table_row: swapped_location.table_row, - }, - ); - } - // PERF: store "non bundle" components in edge, then just move those to avoid - // redundant copies - let move_result = table.move_to_superset_unchecked(result.table_row, new_table); - let new_location = new_archetype.allocate(entity, move_result.new_row); - entities.set(entity.index(), new_location); - - // if an entity was moved into this entity's table spot, update its table row - if let Some(swapped_entity) = move_result.swapped_entity { - let swapped_location = - // SAFETY: If the swap was successful, swapped_entity must be valid. - unsafe { entities.get(swapped_entity).debug_checked_unwrap() }; - let swapped_archetype = if archetype.id() == swapped_location.archetype_id { - archetype - } else if new_archetype.id() == swapped_location.archetype_id { - new_archetype - } else { - // SAFETY: the only two borrowed archetypes are above and we just did collision checks - &mut *archetypes_ptr.add(swapped_location.archetype_id.index()) - }; - - entities.set( - swapped_entity.index(), - EntityLocation { - archetype_id: swapped_location.archetype_id, - archetype_row: swapped_location.archetype_row, - table_id: swapped_location.table_id, - table_row: result.table_row, - }, - ); - swapped_archetype + let new_table = new_table.as_mut(); + let new_archetype = new_archetype.as_mut(); + + // SAFETY: Mutable references do not alias and will be dropped after this block + let (archetypes_ptr, sparse_sets, entities) = { + let world = self.world.world_mut(); + let archetype_ptr: *mut Archetype = world.archetypes.archetypes.as_mut_ptr(); + ( + archetype_ptr, + &mut world.storages.sparse_sets, + &mut world.entities, + ) + }; + let result = archetype.swap_remove(location.archetype_row); + if let Some(swapped_entity) = result.swapped_entity { + let swapped_location = + // SAFETY: If the swap was successful, swapped_entity must be valid. + unsafe { entities.get(swapped_entity).debug_checked_unwrap() }; + entities.set( + swapped_entity.index(), + EntityLocation { + archetype_id: swapped_location.archetype_id, + archetype_row: location.archetype_row, + table_id: swapped_location.table_id, + table_row: swapped_location.table_row, + }, + ); + } + // PERF: store "non bundle" components in edge, then just move those to avoid + // redundant copies + let move_result = table.move_to_superset_unchecked(result.table_row, new_table); + let new_location = new_archetype.allocate(entity, move_result.new_row); + entities.set(entity.index(), new_location); + + // if an entity was moved into this entity's table spot, update its table row + if let Some(swapped_entity) = move_result.swapped_entity { + let swapped_location = + // SAFETY: If the swap was successful, swapped_entity must be valid. + unsafe { entities.get(swapped_entity).debug_checked_unwrap() }; + + entities.set( + swapped_entity.index(), + EntityLocation { + archetype_id: swapped_location.archetype_id, + archetype_row: swapped_location.archetype_row, + table_id: swapped_location.table_id, + table_row: result.table_row, + }, + ); + + if archetype.id() == swapped_location.archetype_id { + archetype + .set_entity_table_row(swapped_location.archetype_row, result.table_row); + } else if new_archetype.id() == swapped_location.archetype_id { + new_archetype + .set_entity_table_row(swapped_location.archetype_row, result.table_row); + } else { + // SAFETY: the only two borrowed archetypes are above and we just did collision checks + (*archetypes_ptr.add(swapped_location.archetype_id.index())) .set_entity_table_row(swapped_location.archetype_row, result.table_row); } + } - let bundle_info = &*self.bundle_info; - let add_bundle = &*self.add_bundle; - bundle_info.write_components( - new_table, - sparse_sets, - add_bundle, - entity, - move_result.new_row, - self.change_tick, - bundle, - ); + bundle_info.write_components( + new_table, + sparse_sets, + add_bundle, + entity, + move_result.new_row, + self.change_tick, + bundle, + ); - new_location - }; + (new_archetype, new_location) + } + }; - // SAFETY: We have no outstanding mutable references to world as they were dropped - unsafe { trigger_hooks(&**new_archetype, self.world.into_deferred()) }; + // SAFETY: We have no outstanding mutable references to world as they were dropped + let mut deferred_world = unsafe { self.world.into_deferred() }; - new_location + if new_archetype.has_on_add() { + // SAFETY: All components in the bundle are guaranteed to exist in the World + // as they must be initialized before creating the BundleInfo. + unsafe { + deferred_world.trigger_on_add( + entity, + bundle_info + .iter_components() + .zip(add_bundle.bundle_status.iter()) + .filter(|(_, &status)| status == ComponentStatus::Added) + .map(|(id, _)| id), + ); } } + if new_archetype.has_on_insert() { + // SAFETY: All components in the bundle are guaranteed to exist in the World + // as they must be initialized before creating the BundleInfo. + unsafe { deferred_world.trigger_on_insert(entity, bundle_info.iter_components()) } + } + + new_location } #[inline] @@ -830,9 +817,9 @@ impl<'w> BundleInserter<'w> { // SAFETY: We have exclusive world access so our pointers can't be invalidated externally pub(crate) struct BundleSpawner<'w> { world: UnsafeWorldCell<'w>, - bundle_info: *const BundleInfo, - table: *mut Table, - archetype: *mut Archetype, + bundle_info: ConstNonNull, + table: NonNull
, + archetype: NonNull, change_tick: Tick, } @@ -866,9 +853,9 @@ impl<'w> BundleSpawner<'w> { let archetype = &mut world.archetypes[new_archetype_id]; let table = &mut world.storages.tables[archetype.table_id()]; Self { - bundle_info, - table, - archetype, + bundle_info: bundle_info.into(), + table: table.into(), + archetype: archetype.into(), change_tick, world: world.as_unsafe_world_cell(), } @@ -877,7 +864,7 @@ impl<'w> BundleSpawner<'w> { #[inline] pub fn reserve_storage(&mut self, additional: usize) { // SAFETY: There are no outstanding world references - let (archetype, table) = unsafe { (&mut *self.archetype, &mut *self.table) }; + let (archetype, table) = unsafe { (self.archetype.as_mut(), self.table.as_mut()) }; archetype.reserve(additional); table.reserve(additional); } @@ -890,6 +877,10 @@ impl<'w> BundleSpawner<'w> { entity: Entity, bundle: T, ) -> EntityLocation { + let table = self.table.as_mut(); + let archetype = self.archetype.as_mut(); + let bundle_info = self.bundle_info.as_ref(); + // SAFETY: We do not make any structural changes to the archetype graph through self.world so this pointer always remain valid let location = { // SAFETY: Mutable references do not alias and will be dropped after this block @@ -897,11 +888,8 @@ impl<'w> BundleSpawner<'w> { let world = self.world.world_mut(); (&mut world.storages.sparse_sets, &mut world.entities) }; - let table = &mut *self.table; - let archetype = &mut *self.archetype; let table_row = table.allocate(entity); let location = archetype.allocate(entity, table_row); - let bundle_info = &*self.bundle_info; bundle_info.write_components( table, sparse_sets, @@ -916,16 +904,16 @@ impl<'w> BundleSpawner<'w> { }; // SAFETY: We have no outstanding mutable references to world as they were dropped - unsafe { - let archetype = &*self.archetype; - let bundle_info = &*self.bundle_info; - let mut world = self.world.into_deferred(); - if archetype.has_on_add() { - world.trigger_on_add(entity, bundle_info.iter_components()); - } - if archetype.has_on_insert() { - world.trigger_on_insert(entity, bundle_info.iter_components()); - } + let mut deferred_world = unsafe { self.world.into_deferred() }; + if archetype.has_on_add() { + // SAFETY: All components in the bundle are guaranteed to exist in the World + // as they must be initialized before creating the BundleInfo. + unsafe { deferred_world.trigger_on_add(entity, bundle_info.iter_components()) }; + } + if archetype.has_on_insert() { + // SAFETY: All components in the bundle are guaranteed to exist in the World + // as they must be initialized before creating the BundleInfo. + unsafe { deferred_world.trigger_on_insert(entity, bundle_info.iter_components()) }; } location diff --git a/crates/bevy_hierarchy/src/lib.rs b/crates/bevy_hierarchy/src/lib.rs index 83c0a10569ea3..5e1ad9e9ad4ef 100644 --- a/crates/bevy_hierarchy/src/lib.rs +++ b/crates/bevy_hierarchy/src/lib.rs @@ -84,13 +84,10 @@ use bevy_app::prelude::*; #[derive(Default)] pub struct HierarchyPlugin; -#[cfg(feature = "bevy_app")] -use bevy_utils::smallvec::SmallVec; impl Plugin for HierarchyPlugin { fn build(&self, app: &mut App) { app.register_type::() .register_type::() - .register_type::>() .add_event::(); } } diff --git a/crates/bevy_input/src/lib.rs b/crates/bevy_input/src/lib.rs index e6841ace81636..6513f174c1d29 100644 --- a/crates/bevy_input/src/lib.rs +++ b/crates/bevy_input/src/lib.rs @@ -34,19 +34,15 @@ pub mod prelude { use bevy_app::prelude::*; use bevy_ecs::prelude::*; use bevy_reflect::Reflect; -use keyboard::{keyboard_input_system, Key, KeyCode, KeyboardInput, NativeKey, NativeKeyCode}; -use mouse::{ - mouse_button_input_system, MouseButton, MouseButtonInput, MouseMotion, MouseScrollUnit, - MouseWheel, -}; -use touch::{touch_screen_input_system, ForceTouch, TouchInput, TouchPhase, Touches}; +use keyboard::{keyboard_input_system, KeyCode, KeyboardInput}; +use mouse::{mouse_button_input_system, MouseButton, MouseButtonInput, MouseMotion, MouseWheel}; +use touch::{touch_screen_input_system, TouchInput, Touches}; use touchpad::{TouchpadMagnify, TouchpadRotate}; use gamepad::{ gamepad_axis_event_system, gamepad_button_event_system, gamepad_connection_system, - gamepad_event_system, AxisSettings, ButtonAxisSettings, ButtonSettings, Gamepad, GamepadAxis, - GamepadAxisChangedEvent, GamepadAxisType, GamepadButton, GamepadButtonChangedEvent, - GamepadButtonInput, GamepadButtonType, GamepadConnection, GamepadConnectionEvent, GamepadEvent, + gamepad_event_system, GamepadAxis, GamepadAxisChangedEvent, GamepadButton, + GamepadButtonChangedEvent, GamepadButtonInput, GamepadConnectionEvent, GamepadEvent, GamepadRumbleRequest, GamepadSettings, Gamepads, }; @@ -108,43 +104,15 @@ impl Plugin for InputPlugin { .add_systems(PreUpdate, touch_screen_input_system.in_set(InputSystem)); // Register common types - app.register_type::(); - - // Register keyboard types - app.register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::(); - - // Register mouse types - app.register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::(); - - // Register touchpad types - app.register_type::() - .register_type::(); - - // Register touch types - app.register_type::() - .register_type::() - .register_type::(); - - // Register gamepad types - app.register_type::() - .register_type::() - .register_type::() - .register_type::() + app.register_type::() + .register_type::() + .register_type::() + .register_type::() + .register_type::() + .register_type::() + .register_type::() .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::(); + .register_type::(); } } diff --git a/crates/bevy_internal/Cargo.toml b/crates/bevy_internal/Cargo.toml index f243a40fbf7bc..38a935db843aa 100644 --- a/crates/bevy_internal/Cargo.toml +++ b/crates/bevy_internal/Cargo.toml @@ -114,7 +114,7 @@ webgpu = [ # enable systems that allow for automated testing on CI bevy_ci_testing = [ - "bevy_app/bevy_ci_testing", + "bevy_dev_tools/bevy_ci_testing", "bevy_time/bevy_ci_testing", "bevy_render?/bevy_ci_testing", "bevy_render?/ci_limits", @@ -166,6 +166,12 @@ bevy_debug_stepping = [ # Enables processing meshes into meshlet meshes for bevy_pbr meshlet_processor = ["bevy_pbr?/meshlet_processor"] +# Provides a collection of developer tools +bevy_dev_tools = ["dep:bevy_dev_tools"] + +# Enable support for the ios_simulator by downgrading some rendering capabilities +ios_simulator = ["bevy_pbr?/ios_simulator", "bevy_render?/ios_simulator"] + [dependencies] # bevy bevy_a11y = { path = "../bevy_a11y", version = "0.14.0-dev" } @@ -204,6 +210,7 @@ bevy_ui = { path = "../bevy_ui", optional = true, version = "0.14.0-dev" } bevy_winit = { path = "../bevy_winit", optional = true, version = "0.14.0-dev" } bevy_gilrs = { path = "../bevy_gilrs", optional = true, version = "0.14.0-dev" } bevy_gizmos = { path = "../bevy_gizmos", optional = true, version = "0.14.0-dev", default-features = false } +bevy_dev_tools = { path = "../bevy_dev_tools/", optional = true, version = "0.14.0-dev" } [lints] workspace = true diff --git a/crates/bevy_internal/src/default_plugins.rs b/crates/bevy_internal/src/default_plugins.rs index c0869a24909f2..08d68b0fdcff1 100644 --- a/crates/bevy_internal/src/default_plugins.rs +++ b/crates/bevy_internal/src/default_plugins.rs @@ -27,6 +27,7 @@ use bevy_app::{Plugin, PluginGroup, PluginGroupBuilder}; /// * [`AudioPlugin`](crate::audio::AudioPlugin) - with feature `bevy_audio` /// * [`GilrsPlugin`](crate::gilrs::GilrsPlugin) - with feature `bevy_gilrs` /// * [`AnimationPlugin`](crate::animation::AnimationPlugin) - with feature `bevy_animation` +/// * [`DevToolsPlugin`](crate::dev_tools::DevToolsPlugin) - with feature `bevy_dev_tools` /// /// [`DefaultPlugins`] obeys *Cargo* *feature* flags. Users may exert control over this plugin group /// by disabling `default-features` in their `Cargo.toml` and enabling only those features @@ -134,6 +135,11 @@ impl PluginGroup for DefaultPlugins { group = group.add(bevy_gizmos::GizmoPlugin); } + #[cfg(feature = "bevy_dev_tools")] + { + group = group.add(bevy_dev_tools::DevToolsPlugin); + } + group = group.add(IgnoreAmbiguitiesPlugin); group diff --git a/crates/bevy_internal/src/lib.rs b/crates/bevy_internal/src/lib.rs index 25a2584c7d83c..896091c404c98 100644 --- a/crates/bevy_internal/src/lib.rs +++ b/crates/bevy_internal/src/lib.rs @@ -199,3 +199,9 @@ pub mod dynamic_plugin { //! Dynamic linking of plugins pub use bevy_dynamic_plugin::*; } + +#[cfg(feature = "bevy_dev_tools")] +pub mod dev_tools { + //! Collection of developer tools + pub use bevy_dev_tools::*; +} diff --git a/crates/bevy_pbr/src/lib.rs b/crates/bevy_pbr/src/lib.rs index c4ae2c12a24d9..3c5ecb569fbee 100644 --- a/crates/bevy_pbr/src/lib.rs +++ b/crates/bevy_pbr/src/lib.rs @@ -246,13 +246,9 @@ impl Plugin for PbrPlugin { app.register_asset_reflect::() .register_type::() - .register_type::() .register_type::() - .register_type::() .register_type::() .register_type::() - .register_type::() - .register_type::() .register_type::() .register_type::() .register_type::() @@ -262,10 +258,7 @@ impl Plugin for PbrPlugin { .register_type::() .register_type::() .register_type::() - .register_type::() .register_type::() - .register_type::() - .register_type::() .init_resource::() .init_resource::() .init_resource::() diff --git a/crates/bevy_pbr/src/light.rs b/crates/bevy_pbr/src/light.rs index ac94689bc3089..e131d92d2c3ca 100644 --- a/crates/bevy_pbr/src/light.rs +++ b/crates/bevy_pbr/src/light.rs @@ -589,7 +589,7 @@ fn calculate_cascade( // It is critical for `world_to_cascade` to be stable. So rather than forming `cascade_to_world` // and inverting it, which risks instability due to numerical precision, we directly form - // `world_to_cascde` as the reference material suggests. + // `world_to_cascade` as the reference material suggests. let light_to_world_transpose = light_to_world.transpose(); let world_to_cascade = Mat4::from_cols( light_to_world_transpose.x_axis, diff --git a/crates/bevy_pbr/src/render/light.rs b/crates/bevy_pbr/src/render/light.rs index 54eec9411159a..0b3c65ddfaf6c 100644 --- a/crates/bevy_pbr/src/render/light.rs +++ b/crates/bevy_pbr/src/render/light.rs @@ -5,7 +5,7 @@ use bevy_math::{Mat4, UVec3, UVec4, Vec2, Vec3, Vec3Swizzles, Vec4, Vec4Swizzles use bevy_render::{ camera::Camera, mesh::Mesh, - primitives::{CascadesFrusta, CubemapFrusta, Frustum}, + primitives::{CascadesFrusta, CubemapFrusta, Frustum, HalfSpace}, render_asset::RenderAssets, render_graph::{Node, NodeRunError, RenderGraphContext}, render_phase::*, @@ -1144,7 +1144,7 @@ pub fn prepare_lights( .unwrap() .iter() .take(MAX_CASCADES_PER_LIGHT); - for (cascade_index, ((cascade, frusta), bound)) in cascades + for (cascade_index, ((cascade, frustum), bound)) in cascades .zip(frusta) .zip(&light.cascade_shadow_config.bounds) .enumerate() @@ -1171,6 +1171,11 @@ pub fn prepare_lights( }); directional_depth_texture_array_index += 1; + let mut frustum = *frustum; + // Push the near clip plane out to infinity for directional lights + frustum.half_spaces[4] = + HalfSpace::new(frustum.half_spaces[4].normal().extend(f32::INFINITY)); + let view_light_entity = commands .spawn(( ShadowView { @@ -1191,7 +1196,7 @@ pub fn prepare_lights( hdr: false, color_grading: Default::default(), }, - *frusta, + frustum, RenderPhase::::default(), LightEntity::Directional { light_entity, diff --git a/crates/bevy_ptr/src/lib.rs b/crates/bevy_ptr/src/lib.rs index d26cc1fcb2a5e..d6c0322461528 100644 --- a/crates/bevy_ptr/src/lib.rs +++ b/crates/bevy_ptr/src/lib.rs @@ -26,6 +26,119 @@ mod sealed { impl Sealed for super::Unaligned {} } +/// A newtype around [`NonNull`] that only allows conversion to read-only borrows or pointers. +/// +/// This type can be thought of as the `*const T` to [`NonNull`]'s `*mut T`. +#[repr(transparent)] +pub struct ConstNonNull(NonNull); + +impl ConstNonNull { + /// Creates a new `ConstNonNull` if `ptr` is non-null. + /// + /// # Examples + /// + /// ``` + /// use bevy_ptr::ConstNonNull; + /// + /// let x = 0u32; + /// let ptr = ConstNonNull::::new(&x as *const _).expect("ptr is null!"); + /// + /// if let Some(ptr) = ConstNonNull::::new(std::ptr::null()) { + /// unreachable!(); + /// } + /// ``` + pub fn new(ptr: *const T) -> Option { + NonNull::new(ptr.cast_mut()).map(Self) + } + + /// Creates a new `ConstNonNull`. + /// + /// # Safety + /// + /// `ptr` must be non-null. + /// + /// # Examples + /// + /// ``` + /// use bevy_ptr::ConstNonNull; + /// + /// let x = 0u32; + /// let ptr = unsafe { ConstNonNull::new_unchecked(&x as *const _) }; + /// ``` + /// + /// *Incorrect* usage of this function: + /// + /// ```rust,no_run + /// use bevy_ptr::ConstNonNull; + /// + /// // NEVER DO THAT!!! This is undefined behavior. ⚠️ + /// let ptr = unsafe { ConstNonNull::::new_unchecked(std::ptr::null()) }; + /// ``` + pub const unsafe fn new_unchecked(ptr: *const T) -> Self { + // SAFETY: This function's safety invariants are identical to `NonNull::new_unchecked` + // The caller must satisfy all of them. + unsafe { Self(NonNull::new_unchecked(ptr.cast_mut())) } + } + + /// Returns a shared reference to the value. + /// + /// # Safety + /// + /// When calling this method, you have to ensure that all of the following is true: + /// + /// * The pointer must be properly aligned. + /// + /// * It must be "dereferenceable" in the sense defined in [the module documentation]. + /// + /// * The pointer must point to an initialized instance of `T`. + /// + /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is + /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. + /// In particular, while this reference exists, the memory the pointer points to must + /// not get mutated (except inside `UnsafeCell`). + /// + /// This applies even if the result of this method is unused! + /// (The part about being initialized is not yet fully decided, but until + /// it is, the only safe approach is to ensure that they are indeed initialized.) + /// + /// # Examples + /// + /// ``` + /// use bevy_ptr::ConstNonNull; + /// + /// let mut x = 0u32; + /// let ptr = ConstNonNull::new(&mut x as *mut _).expect("ptr is null!"); + /// + /// let ref_x = unsafe { ptr.as_ref() }; + /// println!("{ref_x}"); + /// ``` + /// + /// [the module documentation]: core::ptr#safety + #[inline] + pub unsafe fn as_ref<'a>(&self) -> &'a T { + // SAFETY: This function's safety invariants are identical to `NonNull::as_ref` + // The caller must satisfy all of them. + unsafe { self.0.as_ref() } + } +} + +impl From> for ConstNonNull { + fn from(value: NonNull) -> ConstNonNull { + ConstNonNull(value) + } +} + +impl<'a, T: ?Sized> From<&'a T> for ConstNonNull { + fn from(value: &'a T) -> ConstNonNull { + ConstNonNull(NonNull::from(value)) + } +} + +impl<'a, T: ?Sized> From<&'a mut T> for ConstNonNull { + fn from(value: &'a mut T) -> ConstNonNull { + ConstNonNull(NonNull::from(value)) + } +} /// Type-erased borrow of some unknown type chosen when constructing this type. /// /// This type tries to act "borrow-like" which means that: @@ -280,6 +393,7 @@ impl<'a> OwningPtr<'a> { f(unsafe { PtrMut::from(&mut *temp).promote() }) } } + impl<'a, A: IsAligned> OwningPtr<'a, A> { /// Creates a new instance from a raw pointer. /// @@ -346,6 +460,7 @@ impl<'a, A: IsAligned> OwningPtr<'a, A> { unsafe { PtrMut::new(self.0) } } } + impl<'a> OwningPtr<'a, Unaligned> { /// Consumes the [`OwningPtr`] to obtain ownership of the underlying data of type `T`. /// diff --git a/crates/bevy_render/Cargo.toml b/crates/bevy_render/Cargo.toml index 84b58b00032a3..7e9012d99df3e 100644 --- a/crates/bevy_render/Cargo.toml +++ b/crates/bevy_render/Cargo.toml @@ -19,7 +19,7 @@ webp = ["image/webp"] dds = ["ddsfile"] pnm = ["image/pnm"] multi-threaded = ["bevy_tasks/multi-threaded"] -bevy_ci_testing = ["bevy_app/bevy_ci_testing"] +bevy_ci_testing = ["bevy_dev_tools/bevy_ci_testing"] shader_format_glsl = ["naga/glsl-in", "naga/wgsl-out", "naga_oil/glsl"] shader_format_spirv = ["wgpu/spirv", "naga/spv-in", "naga/spv-out"] @@ -57,6 +57,7 @@ bevy_transform = { path = "../bevy_transform", version = "0.14.0-dev" } bevy_window = { path = "../bevy_window", version = "0.14.0-dev" } bevy_utils = { path = "../bevy_utils", version = "0.14.0-dev" } bevy_tasks = { path = "../bevy_tasks", version = "0.14.0-dev" } +bevy_dev_tools = { path = "../bevy_dev_tools", version = "0.14.0-dev", optional = true } # rendering image = { version = "0.24", default-features = false } diff --git a/crates/bevy_render/src/camera/mod.rs b/crates/bevy_render/src/camera/mod.rs index a1e02be219857..579129bb0f014 100644 --- a/crates/bevy_render/src/camera/mod.rs +++ b/crates/bevy_render/src/camera/mod.rs @@ -24,12 +24,7 @@ pub struct CameraPlugin; impl Plugin for CameraPlugin { fn build(&self, app: &mut App) { app.register_type::() - .register_type::() - .register_type::>() - .register_type::() - .register_type::() .register_type::() - .register_type::() .register_type::() .register_type::() .register_type::() diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index d972356b02a7e..3227bd00137bd 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -329,17 +329,7 @@ impl Plugin for RenderPlugin { app.register_type::() // These types cannot be registered in bevy_color, as it does not depend on the rest of Bevy - // BLOCKED: once https://github.com/bevyengine/bevy/pull/5781 lands, we can remove all but the Color registration .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() .register_type::() .register_type::() .register_type::() diff --git a/crates/bevy_render/src/mesh/mod.rs b/crates/bevy_render/src/mesh/mod.rs index 0a40d9b724289..2cb30bb2dc5ad 100644 --- a/crates/bevy_render/src/mesh/mod.rs +++ b/crates/bevy_render/src/mesh/mod.rs @@ -13,7 +13,7 @@ use std::{ use crate::{prelude::Image, render_asset::RenderAssetPlugin, RenderApp}; use bevy_app::{App, Plugin}; -use bevy_asset::{AssetApp, Handle}; +use bevy_asset::AssetApp; use bevy_ecs::{entity::Entity, system::Resource}; /// Adds the [`Mesh`] as an asset and makes sure that they are extracted and prepared for the GPU. @@ -24,10 +24,6 @@ impl Plugin for MeshPlugin { app.init_asset::() .init_asset::() .register_asset_reflect::() - .register_type::>>() - .register_type::>>() - .register_type::>() - .register_type::() .register_type::() .register_type::>() // 'Mesh' must be prepared after 'Image' as meshes rely on the morph target image being ready diff --git a/crates/bevy_render/src/texture/mod.rs b/crates/bevy_render/src/texture/mod.rs index 866cbc928c68e..986ae7d104ea4 100644 --- a/crates/bevy_render/src/texture/mod.rs +++ b/crates/bevy_render/src/texture/mod.rs @@ -118,6 +118,8 @@ impl Plugin for ImagePlugin { feature = "bmp", feature = "basis-universal", feature = "ktx2", + feature = "webp", + feature = "pnm" ))] app.preregister_asset_loader::(IMG_FILE_EXTENSIONS); } @@ -131,6 +133,8 @@ impl Plugin for ImagePlugin { feature = "bmp", feature = "basis-universal", feature = "ktx2", + feature = "webp", + feature = "pnm" ))] { app.init_asset_loader::(); diff --git a/crates/bevy_render/src/view/window/screenshot.rs b/crates/bevy_render/src/view/window/screenshot.rs index ca93f73afd81f..b51c4f479770a 100644 --- a/crates/bevy_render/src/view/window/screenshot.rs +++ b/crates/bevy_render/src/view/window/screenshot.rs @@ -144,7 +144,7 @@ impl Plugin for ScreenshotPlugin { #[cfg(feature = "bevy_ci_testing")] if app .world - .contains_resource::() + .contains_resource::() { app.add_systems(bevy_app::Update, ci_testing_screenshot_at); } @@ -154,7 +154,7 @@ impl Plugin for ScreenshotPlugin { #[cfg(feature = "bevy_ci_testing")] fn ci_testing_screenshot_at( mut current_frame: Local, - ci_testing_config: Res, + ci_testing_config: Res, mut screenshot_manager: ResMut, main_window: Query>, ) { diff --git a/crates/bevy_text/src/lib.rs b/crates/bevy_text/src/lib.rs index 3ad31358ccf44..e0824cf9e3671 100644 --- a/crates/bevy_text/src/lib.rs +++ b/crates/bevy_text/src/lib.rs @@ -77,11 +77,6 @@ impl Plugin for TextPlugin { app.init_asset::() .register_type::() .register_type::() - .register_type::() - .register_type::>() - .register_type::() - .register_type::() - .register_type::() .init_asset_loader::() .init_resource::() .init_resource::() diff --git a/crates/bevy_time/Cargo.toml b/crates/bevy_time/Cargo.toml index beb9d0db56108..5b586ebab3d03 100644 --- a/crates/bevy_time/Cargo.toml +++ b/crates/bevy_time/Cargo.toml @@ -11,7 +11,7 @@ keywords = ["bevy"] [features] default = [] serialize = ["serde"] -bevy_ci_testing = ["bevy_app/bevy_ci_testing"] +bevy_ci_testing = ["bevy_dev_tools/bevy_ci_testing"] [dependencies] # bevy @@ -23,6 +23,7 @@ bevy_reflect = { path = "../bevy_reflect", version = "0.14.0-dev", features = [ "bevy", ] } bevy_utils = { path = "../bevy_utils", version = "0.14.0-dev" } +bevy_dev_tools = { path = "../bevy_dev_tools", version = "0.14.0-dev", optional = true } # other crossbeam-channel = "0.5.0" diff --git a/crates/bevy_time/src/lib.rs b/crates/bevy_time/src/lib.rs index 98c075e9985ff..c94e6f46db0ba 100644 --- a/crates/bevy_time/src/lib.rs +++ b/crates/bevy_time/src/lib.rs @@ -51,7 +51,6 @@ impl Plugin for TimePlugin { .register_type::>() .register_type::>() .register_type::() - .register_type::() .add_systems( First, (time_system, virtual_time_system.after(time_system)).in_set(TimeSystem), @@ -69,7 +68,7 @@ impl Plugin for TimePlugin { #[cfg(feature = "bevy_ci_testing")] if let Some(ci_testing_config) = app .world - .get_resource::() + .get_resource::() { if let Some(frame_time) = ci_testing_config.frame_time { app.world diff --git a/crates/bevy_ui/src/lib.rs b/crates/bevy_ui/src/lib.rs index 2e4306ee598c0..17daf47fb1c74 100644 --- a/crates/bevy_ui/src/lib.rs +++ b/crates/bevy_ui/src/lib.rs @@ -97,37 +97,19 @@ impl Plugin for UiPlugin { app.init_resource::() .init_resource::() .init_resource::() - .register_type::() - .register_type::() - .register_type::() .register_type::() .register_type::() .register_type::() - .register_type::() - .register_type::() - .register_type::() - .register_type::() .register_type::() - .register_type::() - .register_type::() - .register_type::() .register_type::() - .register_type::() - .register_type::() - .register_type::() .register_type::() - .register_type::() - .register_type::() - .register_type::() .register_type::() - .register_type::() .register_type::