Make bevy_app and reflect opt-out for bevy_hierarchy. (#10721)

# Objective

Bevy_hierarchy is very useful for ECS only usages of bevy_ecs, but it
currently pulls in bevy_reflect, bevy_app and bevy_core with no way to
opt out.

## Solution

This PR provides features `bevy_app` and `reflect` that are enabled by
default. If disabled, they should remove these dependencies from
bevy_hierarchy.

---

## Changelog

Added features `bevy_app` and `reflect` to bevy_hierarchy.
This commit is contained in:
Mincong Lu 2023-11-25 11:05:38 +08:00 committed by GitHub
parent 1065028154
commit c33bacd5fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 36 additions and 30 deletions

View File

@ -9,19 +9,20 @@ license = "MIT OR Apache-2.0"
keywords = ["bevy"]
[features]
default = ["bevy_app"]
trace = []
bevy_app = ["reflect", "dep:bevy_app", "bevy_core", "bevy_log"]
reflect = ["bevy_ecs/bevy_reflect", "bevy_reflect"]
[dependencies]
# bevy
bevy_app = { path = "../bevy_app", version = "0.12.0" }
bevy_core = { path = "../bevy_core", version = "0.12.0" }
bevy_ecs = { path = "../bevy_ecs", version = "0.12.0", features = [
"bevy_reflect",
] }
bevy_log = { path = "../bevy_log", version = "0.12.0" }
bevy_app = { path = "../bevy_app", version = "0.12.0", optional = true }
bevy_core = { path = "../bevy_core", version = "0.12.0", optional = true }
bevy_ecs = { path = "../bevy_ecs", version = "0.12.0", default-features = false }
bevy_log = { path = "../bevy_log", version = "0.12.0", optional = true }
bevy_reflect = { path = "../bevy_reflect", version = "0.12.0", features = [
"bevy",
] }
], optional = true }
bevy_utils = { path = "../bevy_utils", version = "0.12.0" }
# other

View File

@ -1,11 +1,11 @@
#[cfg(feature = "reflect")]
use bevy_ecs::reflect::{ReflectComponent, ReflectMapEntities};
use bevy_ecs::{
component::Component,
entity::{Entity, EntityMapper, MapEntities},
prelude::FromWorld,
reflect::{ReflectComponent, ReflectMapEntities},
world::World,
};
use bevy_reflect::Reflect;
use core::slice;
use smallvec::SmallVec;
use std::ops::Deref;
@ -23,8 +23,9 @@ use std::ops::Deref;
/// [`Query`]: bevy_ecs::system::Query
/// [`Parent`]: crate::components::parent::Parent
/// [`BuildChildren::with_children`]: crate::child_builder::BuildChildren::with_children
#[derive(Component, Debug, Reflect)]
#[reflect(Component, MapEntities)]
#[derive(Component, Debug)]
#[cfg_attr(feature = "reflect", derive(bevy_reflect::Reflect))]
#[cfg_attr(feature = "reflect", reflect(Component, MapEntities))]
pub struct Children(pub(crate) SmallVec<[Entity; 8]>);
impl MapEntities for Children {

View File

@ -1,10 +1,10 @@
#[cfg(feature = "reflect")]
use bevy_ecs::reflect::{ReflectComponent, ReflectMapEntities};
use bevy_ecs::{
component::Component,
entity::{Entity, EntityMapper, MapEntities},
reflect::{ReflectComponent, ReflectMapEntities},
world::{FromWorld, World},
};
use bevy_reflect::Reflect;
use std::ops::Deref;
/// Holds a reference to the parent entity of this entity.
@ -20,8 +20,9 @@ use std::ops::Deref;
/// [`Query`]: bevy_ecs::system::Query
/// [`Children`]: super::children::Children
/// [`BuildChildren::with_children`]: crate::child_builder::BuildChildren::with_children
#[derive(Component, Debug, Eq, PartialEq, Reflect)]
#[reflect(Component, MapEntities, PartialEq)]
#[derive(Component, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "reflect", derive(bevy_reflect::Reflect))]
#[cfg_attr(feature = "reflect", reflect(Component, MapEntities, PartialEq))]
pub struct Parent(pub(crate) Entity);
impl Parent {

View File

@ -25,18 +25,21 @@ pub use query_extension::*;
#[doc(hidden)]
pub mod prelude {
#[doc(hidden)]
pub use crate::{
child_builder::*, components::*, hierarchy::*, query_extension::*, HierarchyPlugin,
ValidParentCheckPlugin,
};
pub use crate::{child_builder::*, components::*, hierarchy::*, query_extension::*};
#[doc(hidden)]
#[cfg(feature = "bevy_app")]
pub use crate::{HierarchyPlugin, ValidParentCheckPlugin};
}
#[cfg(feature = "bevy_app")]
use bevy_app::prelude::*;
/// The base plugin for handling [`Parent`] and [`Children`] components
#[derive(Default)]
pub struct HierarchyPlugin;
#[cfg(feature = "bevy_app")]
impl Plugin for HierarchyPlugin {
fn build(&self, app: &mut App) {
app.register_type::<Children>()

View File

@ -1,12 +1,10 @@
use std::marker::PhantomData;
use bevy_app::{App, Last, Plugin};
use bevy_core::Name;
use bevy_ecs::prelude::*;
use bevy_log::warn;
use bevy_utils::{get_short_name, HashSet};
#[cfg(feature = "bevy_app")]
use crate::Parent;
use bevy_ecs::prelude::*;
#[cfg(feature = "bevy_app")]
use bevy_utils::{get_short_name, HashSet};
/// When enabled, runs [`check_hierarchy_component_has_valid_parent<T>`].
///
@ -45,6 +43,7 @@ impl<T> Default for ReportHierarchyIssue<T> {
}
}
#[cfg(feature = "bevy_app")]
/// System to print a warning for each [`Entity`] with a `T` component
/// which parent hasn't a `T` component.
///
@ -55,7 +54,7 @@ impl<T> Default for ReportHierarchyIssue<T> {
/// (See B0004 explanation linked in warning message)
pub fn check_hierarchy_component_has_valid_parent<T: Component>(
parent_query: Query<
(Entity, &Parent, Option<&Name>),
(Entity, &Parent, Option<&bevy_core::Name>),
(With<T>, Or<(Changed<Parent>, Added<T>)>),
>,
component_query: Query<(), With<T>>,
@ -65,7 +64,7 @@ pub fn check_hierarchy_component_has_valid_parent<T: Component>(
let parent = parent.get();
if !component_query.contains(parent) && !already_diagnosed.contains(&entity) {
already_diagnosed.insert(entity);
warn!(
bevy_log::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::<T>()),
@ -94,10 +93,11 @@ impl<T: Component> Default for ValidParentCheckPlugin<T> {
}
}
impl<T: Component> Plugin for ValidParentCheckPlugin<T> {
fn build(&self, app: &mut App) {
#[cfg(feature = "bevy_app")]
impl<T: Component> bevy_app::Plugin for ValidParentCheckPlugin<T> {
fn build(&self, app: &mut bevy_app::App) {
app.init_resource::<ReportHierarchyIssue<T>>().add_systems(
Last,
bevy_app::Last,
check_hierarchy_component_has_valid_parent::<T>
.run_if(resource_equals(ReportHierarchyIssue::<T>::new(true))),
);