add a SpatialBundle with visibility and transform components (#5344)

# Objective

- Help user when they need to add both a `TransformBundle` and a `VisibilityBundle`

## Solution

- Add a `SpatialBundle` adding all components
This commit is contained in:
François 2022-07-18 23:27:30 +00:00
parent 9c116d557d
commit 4affc8cd93
8 changed files with 92 additions and 12 deletions

View file

@ -22,16 +22,17 @@ use bevy_render::{
skinning::{SkinnedMesh, SkinnedMeshInverseBindposes},
Indices, Mesh, VertexAttributeValues,
},
prelude::SpatialBundle,
primitives::{Aabb, Frustum},
render_resource::{AddressMode, Face, FilterMode, PrimitiveTopology, SamplerDescriptor},
renderer::RenderDevice,
texture::{CompressedImageFormats, Image, ImageSampler, ImageType, TextureError},
view::{VisibilityBundle, VisibleEntities},
view::VisibleEntities,
};
use bevy_scene::Scene;
#[cfg(not(target_arch = "wasm32"))]
use bevy_tasks::IoTaskPool;
use bevy_transform::{components::Transform, TransformBundle};
use bevy_transform::components::Transform;
use bevy_utils::{HashMap, HashSet};
use gltf::{
@ -465,8 +466,7 @@ async fn load_gltf<'a, 'b>(
world
.spawn()
.insert_bundle(TransformBundle::identity())
.insert_bundle(VisibilityBundle::default())
.insert_bundle(SpatialBundle::visible_identity())
.with_children(|parent| {
for node in scene.nodes() {
let result = load_node(
@ -705,10 +705,9 @@ fn load_node(
) -> Result<(), GltfError> {
let transform = gltf_node.transform();
let mut gltf_error = None;
let mut node = world_builder.spawn_bundle(TransformBundle::from(Transform::from_matrix(
let mut node = world_builder.spawn_bundle(SpatialBundle::from(Transform::from_matrix(
Mat4::from_cols_array_2d(&transform.matrix()),
)));
node.insert_bundle(VisibilityBundle::default());
node.insert(node_name(gltf_node));

View file

@ -14,6 +14,7 @@ pub mod render_phase;
pub mod render_resource;
pub mod renderer;
pub mod settings;
mod spatial_bundle;
pub mod texture;
pub mod view;
@ -26,6 +27,7 @@ pub mod prelude {
color::Color,
mesh::{shape, Mesh},
render_resource::Shader,
spatial_bundle::SpatialBundle,
texture::Image,
view::{ComputedVisibility, Msaa, Visibility, VisibilityBundle},
};

View file

@ -0,0 +1,59 @@
use bevy_ecs::prelude::Bundle;
use bevy_transform::prelude::{GlobalTransform, Transform};
use crate::view::{ComputedVisibility, Visibility};
/// A [`Bundle`] with the following [`Component`](bevy_ecs::component::Component)s:
/// * [`Visibility`] and [`ComputedVisibility`], which describe the visibility of an entity
/// * [`Transform`] and [`GlobalTransform`], which describe the position of an entity
///
/// * To show or hide an entity, you should set its [`Visibility`].
/// * To get the computed visibility of an entity, you should get its [`ComputedVisibility`].
/// * To place or move an entity, you should set its [`Transform`].
/// * To get the global transform of an entity, you should get its [`GlobalTransform`].
/// * For hierarchies to work correctly, you must have all four components.
/// * You may use the [`SpatialBundle`] to guarantee this.
#[derive(Bundle, Debug, Default)]
pub struct SpatialBundle {
/// The visibility of the entity.
pub visibility: Visibility,
/// The computed visibility of the entity.
pub computed: ComputedVisibility,
/// The transform of the entity.
pub transform: Transform,
/// The global transform of the entity.
pub global_transform: GlobalTransform,
}
impl SpatialBundle {
/// Creates a new [`SpatialBundle`] from a [`Transform`].
///
/// This initializes [`GlobalTransform`] as identity, and visibility as visible
#[inline]
pub const fn from_transform(transform: Transform) -> Self {
SpatialBundle {
transform,
// Note: `..Default::default()` cannot be used here, because it isn't const
..Self::visible_identity()
}
}
/// Creates a new identity [`SpatialBundle`], with no translation, rotation, and a scale of 1
/// on all axes.
#[inline]
pub const fn visible_identity() -> Self {
SpatialBundle {
transform: Transform::identity(),
global_transform: GlobalTransform::identity(),
visibility: Visibility::visible(),
computed: ComputedVisibility::not_visible(),
}
}
}
impl From<Transform> for SpatialBundle {
#[inline]
fn from(transform: Transform) -> Self {
Self::from_transform(transform)
}
}

View file

@ -34,19 +34,40 @@ pub struct Visibility {
impl Default for Visibility {
fn default() -> Self {
Self::visible()
}
}
impl Visibility {
/// Creates a new [`Visibility`], set as visible
pub const fn visible() -> Self {
Self { is_visible: true }
}
}
/// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering
#[derive(Component, Clone, Reflect, Debug, Eq, PartialEq, Default)]
#[derive(Component, Clone, Reflect, Debug, Eq, PartialEq)]
#[reflect(Component)]
pub struct ComputedVisibility {
is_visible_in_hierarchy: bool,
is_visible_in_view: bool,
}
impl Default for ComputedVisibility {
fn default() -> Self {
Self::not_visible()
}
}
impl ComputedVisibility {
/// Creates a new [`ComputedVisibility`], set as not visible
pub const fn not_visible() -> Self {
Self {
is_visible_in_hierarchy: false,
is_visible_in_view: false,
}
}
/// Whether this entity is visible to something this frame. This is true if and only if [`Self::is_visible_in_hierarchy`] and [`Self::is_visible_in_view`]
/// are true. This is the canonical method to call to determine if an entity should be drawn.
/// This value is updated in [`CoreStage::PostUpdate`] during the [`VisibilitySystems::CheckVisibility`] system label. Reading it from the

View file

@ -8,7 +8,7 @@ use bevy_reflect::Reflect;
/// Describe the position of an entity relative to the reference frame.
///
/// * To place or move an entity, you should set its [`Transform`].
/// * To get the global position of an entity, you should get its [`GlobalTransform`].
/// * To get the global transform of an entity, you should get its [`GlobalTransform`].
/// * For transform hierarchies to work correctly, you must have both a [`Transform`] and a [`GlobalTransform`].
/// * You may use the [`TransformBundle`](crate::TransformBundle) to guarantee this.
///

View file

@ -9,7 +9,7 @@ use std::ops::Mul;
/// to its parent position.
///
/// * To place or move an entity, you should set its [`Transform`].
/// * To get the global position of an entity, you should get its [`GlobalTransform`].
/// * To get the global transform of an entity, you should get its [`GlobalTransform`].
/// * To be displayed, an entity must have both a [`Transform`] and a [`GlobalTransform`].
/// * You may use the [`TransformBundle`](crate::TransformBundle) to guarantee this.
///

View file

@ -20,7 +20,7 @@ use prelude::{GlobalTransform, Transform};
/// [`Component`](bevy_ecs::component::Component)s, which describe the position of an entity.
///
/// * To place or move an entity, you should set its [`Transform`].
/// * To get the global position of an entity, you should get its [`GlobalTransform`].
/// * To get the global transform of an entity, you should get its [`GlobalTransform`].
/// * For transform hierarchies to work correctly, you must have both a [`Transform`] and a [`GlobalTransform`].
/// * You may use the [`TransformBundle`] to guarantee this.
///

View file

@ -125,8 +125,7 @@ fn setup(
.insert_bundle((planet, player))
.with_children(|p| {
// This entity is just used for animation, but doesn't display anything
p.spawn_bundle(TransformBundle::default())
.insert_bundle(VisibilityBundle::default())
p.spawn_bundle(SpatialBundle::default())
// Add the Name component
.insert(orbit_controller)
.with_children(|p| {